14 #include <linux/dvb/dmx.h>
15 #include <linux/dvb/frontend.h>
16 #include <sys/ioctl.h>
26 #define DVBS_TUNE_TIMEOUT 9000 //ms
27 #define DVBS_LOCK_TIMEOUT 2000 //ms
28 #define DVBC_TUNE_TIMEOUT 9000 //ms
29 #define DVBC_LOCK_TIMEOUT 2000 //ms
30 #define DVBT_TUNE_TIMEOUT 9000 //ms
31 #define DVBT_LOCK_TIMEOUT 2000 //ms
32 #define ATSC_TUNE_TIMEOUT 9000 //ms
33 #define ATSC_LOCK_TIMEOUT 2000 //ms
35 #define SCR_RANDOM_TIMEOUT 500 // ms (add random value up to this when tuning SCR device to avoid lockups)
37 #define TSBUFFERSIZE MEGABYTE(16)
42 { 0, PILOT_OFF,
trNOOP(
"off") },
43 { 1, PILOT_ON,
trNOOP(
"on") },
44 { 999, PILOT_AUTO,
trNOOP(
"auto") },
49 { 0, INVERSION_OFF,
trNOOP(
"off") },
50 { 1, INVERSION_ON,
trNOOP(
"on") },
51 { 999, INVERSION_AUTO,
trNOOP(
"auto") },
56 { 5, 5000000,
"5 MHz" },
57 { 6, 6000000,
"6 MHz" },
58 { 7, 7000000,
"7 MHz" },
59 { 8, 8000000,
"8 MHz" },
60 { 10, 10000000,
"10 MHz" },
61 { 1712, 1712000,
"1.712 MHz" },
66 { 0, FEC_NONE,
trNOOP(
"none") },
67 { 12, FEC_1_2,
"1/2" },
68 { 23, FEC_2_3,
"2/3" },
69 { 34, FEC_3_4,
"3/4" },
70 { 35, FEC_3_5,
"3/5" },
71 { 45, FEC_4_5,
"4/5" },
72 { 56, FEC_5_6,
"5/6" },
73 { 67, FEC_6_7,
"6/7" },
74 { 78, FEC_7_8,
"7/8" },
75 { 89, FEC_8_9,
"8/9" },
76 { 910, FEC_9_10,
"9/10" },
77 { 999, FEC_AUTO,
trNOOP(
"auto") },
82 { 16, QAM_16,
"QAM16" },
83 { 32, QAM_32,
"QAM32" },
84 { 64, QAM_64,
"QAM64" },
85 { 128, QAM_128,
"QAM128" },
86 { 256, QAM_256,
"QAM256" },
89 { 6, APSK_16,
"16APSK" },
90 { 7, APSK_32,
"32APSK" },
91 { 10, VSB_8,
"VSB8" },
92 { 11, VSB_16,
"VSB16" },
93 { 12, DQPSK,
"DQPSK" },
94 { 999, QAM_AUTO,
trNOOP(
"auto") },
98 #define DVB_SYSTEM_1 0 // see also nit.c
99 #define DVB_SYSTEM_2 1
115 { 2, TRANSMISSION_MODE_2K,
"2K" },
117 { 8, TRANSMISSION_MODE_8K,
"8K" },
120 { 999, TRANSMISSION_MODE_AUTO,
trNOOP(
"auto") },
125 { 4, GUARD_INTERVAL_1_4,
"1/4" },
126 { 8, GUARD_INTERVAL_1_8,
"1/8" },
127 { 16, GUARD_INTERVAL_1_16,
"1/16" },
128 { 32, GUARD_INTERVAL_1_32,
"1/32" },
132 { 999, GUARD_INTERVAL_AUTO,
trNOOP(
"auto") },
137 { 0, HIERARCHY_NONE,
trNOOP(
"none") },
138 { 1, HIERARCHY_1,
"1" },
139 { 2, HIERARCHY_2,
"2" },
140 { 4, HIERARCHY_4,
"4" },
141 { 999, HIERARCHY_AUTO,
trNOOP(
"auto") },
146 { 0, ROLLOFF_AUTO,
trNOOP(
"auto") },
147 { 20, ROLLOFF_20,
"0.20" },
148 { 25, ROLLOFF_25,
"0.25" },
149 { 35, ROLLOFF_35,
"0.35" },
180 *String =
tr(Map[n].userString);
211 return Value >= 0 && Value != 999 ? sprintf(p,
"%c%d", Name, Value) : 0;
216 #define ST(s) if (strchr(s, Type) && (strchr(s, '0' + system + 1) || strchr(s, '*')))
243 int n = strtol(s, &p, 10);
244 if (!errno && p != s) {
250 esyslog(
"ERROR: invalid value for parameter '%c'", *(s - 1));
264 guard = GUARD_INTERVAL_AUTO;
272 switch (toupper(*s)) {
291 default:
esyslog(
"ERROR: unknown parameter key '%c'", *s);
333 #define MAXFRONTENDCMDS 16
334 #define SETCMD(c, d) { Props[CmdSeq.num].cmd = (c);\
335 Props[CmdSeq.num].u.data = (d);\
336 if (CmdSeq.num++ > MAXFRONTENDCMDS) {\
337 esyslog("ERROR: too many tuning commands on frontend %d/%d", adapter, frontend);\
412 if (Modulation == QPSK && !(
frontendInfo.caps & FE_CAN_QPSK) ||
413 Modulation == QAM_16 && !(
frontendInfo.caps & FE_CAN_QAM_16) ||
414 Modulation == QAM_32 && !(
frontendInfo.caps & FE_CAN_QAM_32) ||
415 Modulation == QAM_64 && !(
frontendInfo.caps & FE_CAN_QAM_64) ||
416 Modulation == QAM_128 && !(
frontendInfo.caps & FE_CAN_QAM_128) ||
417 Modulation == QAM_256 && !(
frontendInfo.caps & FE_CAN_QAM_256) ||
418 Modulation == QAM_AUTO && !(
frontendInfo.caps & FE_CAN_QAM_AUTO) ||
419 Modulation == VSB_8 && !(
frontendInfo.caps & FE_CAN_8VSB) ||
420 Modulation == VSB_16 && !(
frontendInfo.caps & FE_CAN_16VSB) ||
434 dtv_property Props[1];
435 dtv_properties CmdSeq;
438 memset(&Props, 0,
sizeof(Props));
439 memset(&CmdSeq, 0,
sizeof(CmdSeq));
440 CmdSeq.props = Props;
441 SETCMD(DTV_API_VERSION, 0);
442 if (ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
450 bool LegacyMode =
true;
452 memset(&Props, 0,
sizeof(Props));
453 memset(&CmdSeq, 0,
sizeof(CmdSeq));
454 CmdSeq.props = Props;
456 int Result = ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq);
458 for (uint i = 0; i < Props[0].u.buffer.len; i++) {
466 esyslog(
"ERROR: can't query delivery systems on frontend %d/%d - falling back to legacy mode",
adapter,
frontend);
500 ms =
"unknown modulations";
511 #define TUNER_POLL_TIMEOUT 10 // ms
515 int ds = SYS_UNDEFINED;
519 ds = SYS_DVBC_ANNEX_AC;
520 else if (Channel->
IsSat())
522 else if (Channel->
IsTerr())
525 esyslog(
"ERROR: can't determine frontend type for channel %d (%s)", Channel->
Number(), Channel->
Name());
570 virtual void Action(
void);
588 bool Locked(
int TimeoutMs = 0);
590 bool GetSignalStats(
int &Valid,
double *Strength = NULL,
double *Cnr = NULL,
double *BerPre = NULL,
double *BerPost = NULL,
double *Per = NULL,
int *Status = NULL)
const;
627 for (
int i = 1; ; i++) {
727 while (t->bondedTuner !=
this)
730 t->bondedTuner = NULL;
745 return diseqc->Commands();
761 if (t->device->Priority() >
IDLEPRIORITY || ConsiderOccupied && t->device->Occupied()) {
762 if (strcmp(BondingParams, t->GetBondedMaster()->GetBondingParams()) != 0)
808 if (BondedMaster ==
this) {
838 if (isLocked || !TimeoutMs)
851 dvb_frontend_event Event;
852 while (ioctl(
fd_frontend, FE_GET_EVENT, &Event) == 0)
860 Status = (fe_status_t)0;
862 if (ioctl(
fd_frontend, FE_READ_STATUS, &Status) != -1)
874 bool cDvbTuner::GetSignalStats(
int &Valid,
double *Strength,
double *Cnr,
double *BerPre,
double *BerPost,
double *Per,
int *Status)
const
877 fe_status_t FeStatus = (fe_status_t)0;
879 dtv_properties CmdSeq;
880 memset(&Props, 0,
sizeof(Props));
881 memset(&CmdSeq, 0,
sizeof(CmdSeq));
882 CmdSeq.props = Props;
884 if (ioctl(
fd_frontend, FE_READ_STATUS, &FeStatus) != 0) {
897 if (Strength)
SETCMD(DTV_STAT_SIGNAL_STRENGTH, 0);
898 if (Cnr)
SETCMD(DTV_STAT_CNR, 0);
899 if (BerPre) {
SETCMD(DTV_STAT_PRE_ERROR_BIT_COUNT, 0);
900 SETCMD(DTV_STAT_PRE_TOTAL_BIT_COUNT, 0); }
901 if (BerPost) {
SETCMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0);
902 SETCMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0); }
903 if (Per) {
SETCMD(DTV_STAT_ERROR_BLOCK_COUNT, 0);
904 SETCMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0); }
905 if (CmdSeq.num && ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
911 if (Props[i].u.st.len > 0) {
912 switch (Props[i].u.st.stat[0].scale) {
913 case FE_SCALE_DECIBEL: *Strength = double(Props[i].u.st.stat[0].svalue) / 1000;
922 if (Props[i].u.st.len > 0) {
923 switch (Props[i].u.st.stat[0].scale) {
924 case FE_SCALE_DECIBEL: *Cnr = double(Props[i].u.st.stat[0].svalue) / 1000;
933 if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
934 if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
935 uint64_t ebc = Props[i].u.st.stat[0].uvalue;
936 uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue;
938 *BerPre = double(ebc) / tbc;
946 if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
947 if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
948 uint64_t ebc = Props[i].u.st.stat[0].uvalue;
949 uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue;
951 *BerPost = double(ebc) / tbc;
959 if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
960 if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
961 uint64_t ebc = Props[i].u.st.stat[0].uvalue;
962 uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue;
964 *Per = double(ebc) / tbc;
971 #ifdef DEBUG_SIGNALSTATS
979 fprintf(stderr,
"\n");
995 double v = 10.0 * (dB1000 - High) / (Low - High);
999 #define REF_S1(q1) (mod == QPSK) ? q1 : 0
1000 #define REF_S2(q1, q2, q3, q4) (mod == QPSK) ? q1 : (mod == PSK_8) ? q2 : (mod == APSK_16) ? q3 : (mod == APSK_32) ? q4 : 0
1001 #define REF_T1(q1, q2, q3) (mod == QPSK) ? q1 : (mod == QAM_16) ? q2 : (mod == QAM_64) ? q3 : 0
1002 #define REF_T2(q1, q2, q3, q4) (mod == QPSK) ? q1 : (mod == QAM_16) ? q2 : (mod == QAM_64) ? q3 : (mod == QAM_256) ? q4 : 0
1003 #define REF_C1(q1, q2, q3, q4, q5) (mod == QAM_16) ? q1 : (mod == QAM_32) ? q2 : (mod == QAM_64) ? q3 : (mod == QAM_128) ? q4 : (mod == QAM_256) ? q5: 0
1010 int mod = (FeModulation >= 0) ? FeModulation : dtp.
Modulation();
1011 int cod = (FeCoderateH >= 0) ? FeCoderateH : dtp.
CoderateH();
1012 int fec = (FeFec >= 0) ? FeFec : dtp.
CoderateH();
1019 if (mod == QAM_AUTO) mod = QPSK;
1021 case FEC_1_2: pref =
REF_T1(-93, -87, -82);
break;
1023 case FEC_2_3: pref =
REF_T1(-91, -85, -80);
break;
1024 case FEC_3_4: pref =
REF_T1(-90, -84, -78);
break;
1025 case FEC_5_6: pref =
REF_T1(-89, -83, -77);
break;
1026 case FEC_7_8: pref =
REF_T1(-88, -82, -76);
break;
1030 if (mod == QAM_AUTO) mod = QAM_64;
1032 case FEC_1_2: pref =
REF_T2(-96, -91, -86, -82);
break;
1034 case FEC_3_5: pref =
REF_T2(-95, -89, -85, -80);
break;
1035 case FEC_2_3: pref =
REF_T2(-94, -88, -83, -78);
break;
1036 case FEC_3_4: pref =
REF_T2(-93, -87, -82, -76);
break;
1037 case FEC_4_5: pref =
REF_T2(-92, -86, -81, -75);
break;
1038 case FEC_5_6: pref =
REF_T2(-92, -86, -80, -74);
break;
1042 int prel = (Strength / 1000) - pref;
1043 ssi = (prel < -15) ? 0 :
1044 (prel < 0) ? (prel + 15) * 2 / 3 :
1045 (prel < 20) ? prel * 4 + 10 :
1046 (prel < 35) ? (prel - 20) * 2 / 3 + 90 :
1048 #ifdef DEBUG_SIGNALSTRENGTH
1049 fprintf(stderr,
"SSI-T: STR:%d, Pref:%d, Prel:%d, ssi:%d%%(sys:%d, mod:%d, fec:%d)\n", Strength, pref, prel, ssi, dtp.
System(), mod, fec);
1053 else if (Channel->
IsCable()) {
1058 if (mod == QAM_AUTO) mod = QAM_256;
1060 int pref =
REF_C1(-79, -76, -73, -70, -67);
1062 int prel = (Strength / 1000) - pref;
1063 ssi = (prel < -15) ? 0 :
1064 (prel < 0) ? (prel + 15) * 2 / 3 :
1065 (prel < 20) ? prel * 4 + 10 :
1066 (prel < 35) ? (prel - 20) * 2 / 3 + 90 :
1068 #ifdef DEBUG_SIGNALSTRENGTH
1069 fprintf(stderr,
"SSI-C: STR:%d, Pref:%d, Prel:%d, ssi:%d%%(mod:%d)\n", Strength, pref, prel, ssi, mod);
1073 else if (Channel->
IsSat())
1079 #define IGNORE_BER 1
1080 #define BER_ERROR_FREE (1000*1000*1000) // 1/10^-9
1090 int mod = (FeModulation >= 0) ? FeModulation : dtp.
Modulation();
1091 int cod = (FeCoderateH >= 0) ? FeCoderateH : dtp.
CoderateH();
1092 int fec = (FeFec >= 0) ? FeFec : dtp.
CoderateH();
1099 if (mod == QAM_AUTO) mod = QPSK;
1101 case FEC_1_2: cnref =
REF_T1(51, 108, 165);
break;
1103 case FEC_2_3: cnref =
REF_T1(69, 131, 187);
break;
1104 case FEC_3_4: cnref =
REF_T1(79, 146, 202);
break;
1105 case FEC_5_6: cnref =
REF_T1(89, 156, 216);
break;
1106 case FEC_7_8: cnref =
REF_T1(97, 160, 225);
break;
1110 if (mod == QAM_AUTO) mod = QAM_64;
1112 case FEC_1_2: cnref =
REF_T2(35, 87, 130, 170);
break;
1114 case FEC_3_5: cnref =
REF_T2(47, 101, 148, 194);
break;
1115 case FEC_2_3: cnref =
REF_T2(56, 114, 162, 208);
break;
1116 case FEC_3_4: cnref =
REF_T2(66, 125, 177, 229);
break;
1117 case FEC_4_5: cnref =
REF_T2(72, 133, 187, 243);
break;
1118 case FEC_5_6: cnref =
REF_T2(77, 138, 194, 251);
break;
1122 int cnrel = (Signal/100) - cnref;
1126 ber_sqi = (Ber < 1000) ? 0 :
1127 (Ber >= 10000000) ? 100 :
1128 (int)(20 * log10(Ber)) - 40;
1130 cnr_sqi = (cnrel < -70) ? 0 :
1131 (cnrel < +30) ? (100 + (cnrel - 30)) :
1133 sqi = (cnr_sqi * ber_sqi) / 100;
1138 ber_sqi = (Ber < 10000) ? 0 :
1139 (Ber >= 10000000) ? 100 * 100 / 6 :
1142 sqi = (cnrel < -30) ? 0 :
1143 (cnrel <= +30) ? (cnrel + 30) * ber_sqi / 1000 :
1148 #ifdef DEBUG_SIGNALQUALITY
1149 fprintf(stderr,
"SQI-T: SIG:%d, BER:%d, CNref:%d, CNrel:%d, bersqi:%d, sqi:%d%%(sys:%d, mod:%d, fec:%d)\n", Signal, Ber, cnref, cnrel, ber_sqi, sqi, dtp.
System(), mod, fec);
1153 else if (Channel->
IsCable()) {
1154 if (mod == QAM_AUTO) mod = QAM_256;
1156 int cnref =
REF_C1(200, 230, 260, 290, 320);
1158 int cnrel = (Signal / 100) - cnref;
1159 int ber_sqi = (Ber < 1000) ? 0 :
1160 (Ber >= 10000000) ? 100 :
1161 (int)(20 * log10(Ber)) - 40;
1163 int cnr_sqi = (cnrel < -70) ? 0 :
1164 (cnrel < +30) ? (100 + (cnrel - 30)) :
1166 sqi = (cnr_sqi * ber_sqi) / 100;
1169 #ifdef DEBUG_SIGNALQUALITY
1170 dsyslog(
"SQI-C: SIG:%d, BER:%d, CNref:%d, CNrel:%d, bersqi:%d, sqi:%d%%(sys:%d, mod:%d, fec:%d)\n", Signal, Ber, cnref, cnrel, ber_sqi, sqi, dtp.
System(), mod, fec);
1174 else if (Channel->
IsSat()) {
1177 if (mod == QAM_AUTO) mod = QPSK;
1179 case FEC_1_2: cnref =
REF_S1(38);
break;
1181 case FEC_2_3: cnref =
REF_S1(56);
break;
1182 case FEC_3_4: cnref =
REF_S1(67);
break;
1183 case FEC_5_6: cnref =
REF_S1(77);
break;
1184 case FEC_7_8: cnref =
REF_S1(84);
break;
1190 #ifdef DEBUG_SIGNALQUALITY
1191 dsyslog(
"SQI-S1: SIG:%d, BER:%d, CNref:%d, sqi:%d%%(mod:%d, fec:%d)\n", Signal, Ber, cnref, sqi, mod, fec);
1196 if (mod == QAM_AUTO) mod = QAM_64;
1200 case FEC_2_5: cnref =
REF_S2( 7, 65, 90, 126);
break;
1201 case FEC_1_2: cnref =
REF_S2( 20, 65, 90, 126);
break;
1202 case FEC_3_5: cnref =
REF_S2( 32, 65, 90, 126);
break;
1204 case FEC_2_3: cnref =
REF_S2( 41, 76, 90, 126);
break;
1205 case FEC_3_4: cnref =
REF_S2( 50, 66, 102, 126);
break;
1206 case FEC_4_5: cnref =
REF_S2( 57, 89, 110, 136);
break;
1207 case FEC_5_6: cnref =
REF_S2( 62, 104, 116, 143);
break;
1208 case FEC_8_9: cnref =
REF_S2( 72, 117, 129, 157);
break;
1209 case FEC_9_10: cnref =
REF_S2( 74, 120, 131, 161);
break;
1215 #ifdef DEBUG_SIGNALQUALITY
1216 dsyslog(
"SQI-S2: SIG:%d, BER:%d, CNref:%d, sqi:%d%%(mod:%d, fec:%d)\n", Signal, Ber, cnref, sqi, mod, fec);
1228 for (
int i = 0; i < 1; i++) {
1230 dtv_properties CmdSeq;
1231 memset(&Props, 0,
sizeof(Props));
1232 memset(&CmdSeq, 0,
sizeof(CmdSeq));
1233 CmdSeq.props = Props;
1234 SETCMD(DTV_STAT_SIGNAL_STRENGTH, 0);
1235 SETCMD(DTV_MODULATION, 0);
1236 SETCMD(DTV_CODE_RATE_HP, 0);
1237 SETCMD(DTV_INNER_FEC, 0);
1238 if (ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
1242 int FeMod = (Props[1].u.st.len > 0) ? (
int)Props[1].u.data : -1;
1243 int FeCod = (Props[2].u.st.len > 0) ? (
int)Props[2].u.data : -1;
1244 int FeFec = (Props[3].u.st.len > 0) ? (
int)Props[3].u.data : -1;
1246 if (Props[0].u.st.len > 0) {
1247 switch (Props[0].u.st.stat[0].scale) {
1248 case FE_SCALE_DECIBEL: Signal =
StrengthToSSI(&
channel, Props[0].u.st.stat[0].svalue, FeMod, FeCod, FeFec);
1250 case FE_SCALE_RELATIVE: Signal = 100 * Props[0].u.st.stat[0].uvalue / 0xFFFF;
1254 #ifdef DEBUG_SIGNALSTRENGTH
1255 fprintf(stderr,
"FE %d/%d: API5 %d %08X %.1f S = %d\n",
adapter,
frontend, Props[0].u.st.stat[0].scale,
int(Props[0].u.st.stat[0].svalue),
int(Props[0].u.st.stat[0].svalue) / 1000.0, Signal);
1265 if (ioctl(
fd_frontend, FE_READ_SIGNAL_STRENGTH, &Signal) != -1)
1270 uint16_t MaxSignal = 0xFFFF;
1276 MaxSignal = 670;
break;
1278 int s = int(Signal) * 100 / MaxSignal;
1281 #ifdef DEBUG_SIGNALSTRENGTH
1287 #define LOCK_THRESHOLD 5 // indicates that all 5 FE_HAS_* flags are set
1292 for (
int i = 0; i < 1; i++) {
1294 dtv_properties CmdSeq;
1295 memset(&Props, 0,
sizeof(Props));
1296 memset(&CmdSeq, 0,
sizeof(CmdSeq));
1297 CmdSeq.props = Props;
1299 SETCMD(DTV_MODULATION, 0);
1300 SETCMD(DTV_CODE_RATE_HP, 0);
1301 SETCMD(DTV_INNER_FEC, 0);
1302 SETCMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0);
1303 SETCMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0);
1304 if (ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
1308 int FeMod = (Props[1].u.st.len > 0) ? (
int)Props[1].u.data : -1;
1309 int FeCod = (Props[2].u.st.len > 0) ? (
int)Props[2].u.data : -1;
1310 int FeFec = (Props[3].u.st.len > 0) ? (
int)Props[3].u.data : -1;
1312 if (Props[4].u.st.len > 0 && Props[4].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[5].u.st.len > 0 && Props[5].u.st.stat[0].scale == FE_SCALE_COUNTER) {
1313 uint64_t ebc = Props[4].u.st.stat[0].uvalue;
1314 uint64_t tbc = Props[5].u.st.stat[0].uvalue;
1316 uint64_t BerRev = tbc / ebc;
1322 if (Props[0].u.st.len > 0) {
1323 switch (Props[0].u.st.stat[0].scale) {
1324 case FE_SCALE_DECIBEL: Cnr =
SignalToSQI(&
channel, Props[0].u.st.stat[0].svalue, Ber, FeMod, FeCod, FeFec);
1326 case FE_SCALE_RELATIVE: Cnr = 100 * Props[0].u.st.stat[0].uvalue / 0xFFFF;
1330 #ifdef DEBUG_SIGNALQUALITY
1331 fprintf(stderr,
"FE %d/%d: API5 %d %08X %.1f Q = %d\n",
adapter,
frontend, Props[0].u.st.stat[0].scale,
int(Props[0].u.st.stat[0].svalue),
int(Props[0].u.st.stat[0].svalue) / 1000.0, Cnr);
1342 if ((Status & FE_HAS_LOCK) == 0) {
1343 if ((Status & FE_HAS_SIGNAL) == 0)
1345 if ((Status & FE_HAS_CARRIER) == 0)
1347 if ((Status & FE_HAS_VITERBI) == 0)
1349 if ((Status & FE_HAS_SYNC) == 0)
1353 #ifdef DEBUG_SIGNALQUALITY
1360 if (errno != EINTR) {
1362 #ifdef DEBUG_SIGNALQUALITY
1368 #ifdef DEBUG_SIGNALQUALITY
1375 if (errno != EINTR) {
1377 #ifdef DEBUG_SIGNALQUALITY
1383 #ifdef DEBUG_SIGNALQUALITY
1388 if (ioctl(
fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &Unc) != -1) {
1390 #ifdef DEBUG_SIGNALQUALITY
1411 Unc >>=
min(t,
int(
sizeof(Unc) * 8 - 1));
1414 #ifdef DEBUG_SIGNALQUALITY
1420 if (errno != EINTR) {
1422 #ifdef DEBUG_SIGNALQUALITY
1428 uint16_t MinSnr = 0x0000;
1429 uint16_t MaxSnr = 0xFFFF;
1444 MaxSnr = 255;
break;
1446 int a = int(
constrain(Snr, MinSnr, MaxSnr)) * 100 / (MaxSnr - MinSnr);
1447 int b = 100 - (Unc * 10 + (Ber / 256) * 5);
1453 #ifdef DEBUG_SIGNALQUALITY
1454 fprintf(stderr,
"FE %d/%d: API3 %08X Q = %04X %04X %d %5d %5d %3d%%\n",
adapter,
frontend,
dvbFrontend->
SubsystemId(), MaxSnr, Snr, HasSnr, HasBer ?
int(Ber) : -1, HasUnc ?
int(Unc) : -1, q);
1463 while (f && f < 1000000)
1484 if (Diseqc->
IsScr())
1486 struct dvb_diseqc_master_cmd cmd;
1487 const char *CurrentAction = NULL;
1490 for (
int i = 0; !Break; i++) {
1491 cmd.msg_len =
sizeof(cmd.msg);
1522 default:
esyslog(
"ERROR: unknown diseqc command %d", da);
1530 if (Diseqc->
IsScr())
1543 memset(&Props, 0,
sizeof(Props));
1544 dtv_properties CmdSeq;
1545 memset(&CmdSeq, 0,
sizeof(CmdSeq));
1546 CmdSeq.props = Props;
1548 if (ioctl(
fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
1566 frequency -= diseqc->Lof();
1585 int tone = SEC_TONE_OFF;
1588 tone = SEC_TONE_OFF;
1596 tone = SEC_TONE_OFF;
1597 volt = SEC_VOLTAGE_13;
1602 frequency = abs(frequency);
1605 SETCMD(DTV_FREQUENCY, frequency * 1000UL);
1619 SETCMD(DTV_ROLLOFF, ROLLOFF_35);
1669 esyslog(
"ERROR: attempt to set channel with unknown DVB frontend type");
1673 if (ioctl(
fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
1683 bool LostLock =
false;
1684 fe_status_t Status = (fe_status_t)0;
1686 int WaitTime = 1000;
1687 fe_status_t NewStatus;
1728 if (Status & FE_REINIT) {
1736 else if (Status & FE_HAS_LOCK) {
1806 #define ST(s) if (strchr(s, type))
1824 default:
return NULL;
1878 int DvbOpen(
const char *Name,
int Adapter,
int Frontend,
int Mode,
bool ReportError)
1881 int fd = open(FileName, Mode);
1882 if (fd < 0 && ReportError)
1895 if (access(FileName, F_OK) == 0) {
1896 int f = open(FileName, O_RDONLY);
1901 else if (errno != ENODEV && errno != EINVAL)
1904 else if (errno != ENOENT)
1912 dsyslog(
"probing %s", *FileName);
1917 dsyslog(
"creating cDvbDevice");
1946 while ((a = DvbDir.
Next()) != NULL) {
1950 if (AdapterDir.
Ok()) {
1952 while ((f = AdapterDir.
Next()) != NULL) {
1967 if (Nodes.
Size() > 0) {
1969 for (
int i = 0; i < Nodes.
Size(); i++) {
1990 isyslog(
"found %d DVB device%s", Found, Found > 1 ?
"s" :
"");
1992 isyslog(
"using only %d DVB device%s", Used, Used != 1 ?
"s" :
"");
1995 isyslog(
"no DVB device found");
2007 int ErrorDevice = 0;
2012 if (!DvbDevice1->Bond(DvbDevice2))
2016 ErrorDevice = d + 1;
2019 ErrorDevice = i + 1;
2021 esyslog(
"ERROR: device '%d' in device bondings '%s' is not a cDvbDevice", ErrorDevice, Bondings);
2026 ErrorDevice = d + 1;
2029 ErrorDevice = i + 1;
2031 esyslog(
"ERROR: unknown device '%d' in device bondings '%s'", ErrorDevice, Bondings);
2052 if (Device !=
this) {
2079 while (d->bondedDevice !=
this)
2080 d = d->bondedDevice;
2082 d->bondedDevice = NULL;
2105 dmx_pes_filter_params pesFilterParams;
2106 memset(&pesFilterParams, 0,
sizeof(pesFilterParams));
2108 if (Handle->
handle < 0) {
2110 if (Handle->
handle < 0) {
2115 pesFilterParams.pid = Handle->
pid;
2116 pesFilterParams.input = DMX_IN_FRONTEND;
2117 pesFilterParams.output = DMX_OUT_TS_TAP;
2118 pesFilterParams.pes_type= DMX_PES_OTHER;
2119 pesFilterParams.flags = DMX_IMMEDIATE_START;
2120 if (ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
2125 else if (!Handle->
used) {
2128 pesFilterParams.pid = 0x1FFF;
2129 pesFilterParams.input = DMX_IN_FRONTEND;
2130 pesFilterParams.output = DMX_OUT_DECODER;
2131 pesFilterParams.pes_type= DMX_PES_OTHER;
2132 pesFilterParams.flags = DMX_IMMEDIATE_START;
2133 CHECK(ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams));
2142 #define RB_NUM_SECTIONS 8 // default: 2 sections = 8192 bytes
2147 int f = open(FileName, O_RDWR | O_NONBLOCK);
2151 dsyslog(
"OpenFilter (pid=%d, tid=%02X): ioctl DMX_SET_BUFFER_SIZE failed", Pid, Tid);
2153 dmx_sct_filter_params sctFilterParams;
2154 memset(&sctFilterParams, 0,
sizeof(sctFilterParams));
2155 sctFilterParams.pid = Pid;
2156 sctFilterParams.timeout = 0;
2157 sctFilterParams.flags = DMX_IMMEDIATE_START;
2158 sctFilterParams.filter.filter[0] = Tid;
2159 sctFilterParams.filter.mask[0] = Mask;
2160 if (ioctl(f, DMX_SET_FILTER, &sctFilterParams) >= 0)
2163 esyslog(
"ERROR: can't set filter (pid=%d, tid=%02X, mask=%02X): %m", Pid, Tid, Mask);
2168 esyslog(
"ERROR: can't open filter handle on '%s'", *FileName);
2207 bool result =
false;
2209 bool needsDetachReceivers =
false;
2213 result = hasPriority;
2219 if (
CamSlot()->CanDecrypt(Channel))
2222 needsDetachReceivers =
true;
2242 needsDetachReceivers |= d->Receiving();
2250 if (NeedsDetachReceivers)
2251 *NeedsDetachReceivers = needsDetachReceivers;
2270 bool cDvbDevice::SignalStats(
int &Valid,
double *Strength,
double *Cnr,
double *BerPre,
double *BerPost,
double *Per,
int *Status)
const
2342 if (cs->WantsTsData()) {
2347 Data = cs->Decrypt(Data, Available);
2364 d->cDevice::DetachAllReceivers();
2386 uint32_t SubsystemId = 0;
2389 if (stat(FileName, &st) == 0) {
2393 while ((e = d.
Next()) != NULL) {
2394 if (strstr(e->d_name,
"frontend")) {
2396 if (FILE *f = fopen(FileName,
"r")) {
2398 char *s = ReadLine.
Read(f);
2402 if (s && 2 == sscanf(s,
"%u:%u", &Major, &Minor)) {
2403 if (((Major << 8) | Minor) == st.st_rdev) {
2404 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/subsystem_vendor", e->d_name);
2405 if ((f = fopen(FileName,
"r")) != NULL) {
2406 if (
char *s = ReadLine.
Read(f))
2407 SubsystemId = strtoul(s, NULL, 0) << 16;
2411 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/idVendor", e->d_name);
2412 if ((f = fopen(FileName,
"r")) != NULL) {
2413 if (
char *s = ReadLine.
Read(f))
2414 SubsystemId = strtoul(s, NULL, 16) << 16;
2418 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/subsystem_device", e->d_name);
2419 if ((f = fopen(FileName,
"r")) != NULL) {
2420 if (
char *s = ReadLine.
Read(f))
2421 SubsystemId |= strtoul(s, NULL, 0);
2425 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/idProduct", e->d_name);
2426 if ((f = fopen(FileName,
"r")) != NULL) {
2427 if (
char *s = ReadLine.
Read(f))
2428 SubsystemId |= strtoul(s, NULL, 16);