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)
40 { 0, PILOT_OFF,
trNOOP(
"off") },
41 { 1, PILOT_ON,
trNOOP(
"on") },
42 { 999, PILOT_AUTO,
trNOOP(
"auto") },
47 { 0, INVERSION_OFF,
trNOOP(
"off") },
48 { 1, INVERSION_ON,
trNOOP(
"on") },
49 { 999, INVERSION_AUTO,
trNOOP(
"auto") },
54 { 5, 5000000,
"5 MHz" },
55 { 6, 6000000,
"6 MHz" },
56 { 7, 7000000,
"7 MHz" },
57 { 8, 8000000,
"8 MHz" },
58 { 10, 10000000,
"10 MHz" },
59 { 1712, 1712000,
"1.712 MHz" },
64 { 0, FEC_NONE,
trNOOP(
"none") },
65 { 12, FEC_1_2,
"1/2" },
66 { 23, FEC_2_3,
"2/3" },
67 { 34, FEC_3_4,
"3/4" },
68 { 35, FEC_3_5,
"3/5" },
69 { 45, FEC_4_5,
"4/5" },
70 { 56, FEC_5_6,
"5/6" },
71 { 67, FEC_6_7,
"6/7" },
72 { 78, FEC_7_8,
"7/8" },
73 { 89, FEC_8_9,
"8/9" },
74 { 910, FEC_9_10,
"9/10" },
75 { 999, FEC_AUTO,
trNOOP(
"auto") },
80 { 16, QAM_16,
"QAM16" },
81 { 32, QAM_32,
"QAM32" },
82 { 64, QAM_64,
"QAM64" },
83 { 128, QAM_128,
"QAM128" },
84 { 256, QAM_256,
"QAM256" },
87 { 6, APSK_16,
"16APSK" },
88 { 7, APSK_32,
"32APSK" },
89 { 10, VSB_8,
"VSB8" },
90 { 11, VSB_16,
"VSB16" },
91 { 12, DQPSK,
"DQPSK" },
92 { 999, QAM_AUTO,
trNOOP(
"auto") },
96 #define DVB_SYSTEM_1 0 // see also nit.c
97 #define DVB_SYSTEM_2 1
113 { 2, TRANSMISSION_MODE_2K,
"2K" },
115 { 8, TRANSMISSION_MODE_8K,
"8K" },
118 { 999, TRANSMISSION_MODE_AUTO,
trNOOP(
"auto") },
123 { 4, GUARD_INTERVAL_1_4,
"1/4" },
124 { 8, GUARD_INTERVAL_1_8,
"1/8" },
125 { 16, GUARD_INTERVAL_1_16,
"1/16" },
126 { 32, GUARD_INTERVAL_1_32,
"1/32" },
130 { 999, GUARD_INTERVAL_AUTO,
trNOOP(
"auto") },
135 { 0, HIERARCHY_NONE,
trNOOP(
"none") },
136 { 1, HIERARCHY_1,
"1" },
137 { 2, HIERARCHY_2,
"2" },
138 { 4, HIERARCHY_4,
"4" },
139 { 999, HIERARCHY_AUTO,
trNOOP(
"auto") },
144 { 0, ROLLOFF_AUTO,
trNOOP(
"auto") },
145 { 20, ROLLOFF_20,
"0.20" },
146 { 25, ROLLOFF_25,
"0.25" },
147 { 35, ROLLOFF_35,
"0.35" },
178 *String =
tr(Map[n].userString);
209 return Value >= 0 && Value != 999 ? sprintf(p,
"%c%d", Name, Value) : 0;
214 #define ST(s) if (strchr(s, Type) && (strchr(s, '0' + system + 1) || strchr(s, '*')))
242 int n = strtol(s, &p, 10);
243 if (!errno && p != s) {
249 esyslog(
"ERROR: invalid value for parameter '%c'", *(s - 1));
263 guard = GUARD_INTERVAL_AUTO;
272 switch (toupper(*s)) {
292 default:
esyslog(
"ERROR: unknown parameter key '%c'", *s);
334 #define MAXFRONTENDCMDS 16
335 #define SETCMD(c, d) { Props[CmdSeq.num].cmd = (c);\
336 Props[CmdSeq.num].u.data = (d);\
337 if (CmdSeq.num++ > MAXFRONTENDCMDS) {\
338 esyslog("ERROR: too many tuning commands on frontend %d/%d", adapter, frontend);\
411 if (Modulation == QPSK && !(
frontendInfo.caps & FE_CAN_QPSK) ||
412 Modulation == QAM_16 && !(
frontendInfo.caps & FE_CAN_QAM_16) ||
413 Modulation == QAM_32 && !(
frontendInfo.caps & FE_CAN_QAM_32) ||
414 Modulation == QAM_64 && !(
frontendInfo.caps & FE_CAN_QAM_64) ||
415 Modulation == QAM_128 && !(
frontendInfo.caps & FE_CAN_QAM_128) ||
416 Modulation == QAM_256 && !(
frontendInfo.caps & FE_CAN_QAM_256) ||
417 Modulation == QAM_AUTO && !(
frontendInfo.caps & FE_CAN_QAM_AUTO) ||
418 Modulation == VSB_8 && !(
frontendInfo.caps & FE_CAN_8VSB) ||
419 Modulation == VSB_16 && !(
frontendInfo.caps & FE_CAN_16VSB) ||
433 dtv_property Props[1];
434 dtv_properties CmdSeq;
437 memset(&Props, 0,
sizeof(Props));
438 memset(&CmdSeq, 0,
sizeof(CmdSeq));
439 CmdSeq.props = Props;
440 SETCMD(DTV_API_VERSION, 0);
441 if (ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
449 bool LegacyMode =
true;
451 memset(&Props, 0,
sizeof(Props));
452 memset(&CmdSeq, 0,
sizeof(CmdSeq));
453 CmdSeq.props = Props;
455 int Result = ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq);
457 for (uint i = 0; i < Props[0].u.buffer.len; i++) {
465 esyslog(
"ERROR: can't query delivery systems on frontend %d/%d - falling back to legacy mode",
adapter,
frontend);
499 ms =
"unknown modulations";
510 #define TUNER_POLL_TIMEOUT 10 // ms
514 int ds = SYS_UNDEFINED;
518 ds = SYS_DVBC_ANNEX_AC;
519 else if (Channel->
IsSat())
521 else if (Channel->
IsTerr())
524 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)
861 if (ioctl(
fd_frontend, FE_READ_STATUS, &Status) != -1)
873 bool cDvbTuner::GetSignalStats(
int &Valid,
double *Strength,
double *Cnr,
double *BerPre,
double *BerPost,
double *Per,
int *Status)
const
876 fe_status_t FeStatus;
878 dtv_properties CmdSeq;
879 memset(&Props, 0,
sizeof(Props));
880 memset(&CmdSeq, 0,
sizeof(CmdSeq));
881 CmdSeq.props = Props;
883 if (ioctl(
fd_frontend, FE_READ_STATUS, &FeStatus) != 0) {
896 if (Strength)
SETCMD(DTV_STAT_SIGNAL_STRENGTH, 0);
897 if (Cnr)
SETCMD(DTV_STAT_CNR, 0);
898 if (BerPre) {
SETCMD(DTV_STAT_PRE_ERROR_BIT_COUNT, 0);
899 SETCMD(DTV_STAT_PRE_TOTAL_BIT_COUNT, 0); }
900 if (BerPost) {
SETCMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0);
901 SETCMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0); }
902 if (Per) {
SETCMD(DTV_STAT_ERROR_BLOCK_COUNT, 0);
903 SETCMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0); }
904 if (ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
910 if (Props[i].u.st.len > 0) {
911 switch (Props[i].u.st.stat[0].scale) {
912 case FE_SCALE_DECIBEL: *Strength = double(Props[i].u.st.stat[0].svalue) / 1000;
921 if (Props[i].u.st.len > 0) {
922 switch (Props[i].u.st.stat[0].scale) {
923 case FE_SCALE_DECIBEL: *Cnr = double(Props[i].u.st.stat[0].svalue) / 1000;
932 if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
933 if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
934 uint64_t ebc = Props[i].u.st.stat[0].uvalue;
935 uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue;
937 *BerPre = double(ebc) / tbc;
945 if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
946 if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
947 uint64_t ebc = Props[i].u.st.stat[0].uvalue;
948 uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue;
950 *BerPost = double(ebc) / tbc;
958 if (Props[i].u.st.len > 0 && Props[i + 1].u.st.len > 0) {
959 if (Props[i].u.st.stat[0].scale == FE_SCALE_COUNTER && Props[i + 1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
960 uint64_t ebc = Props[i].u.st.stat[0].uvalue;
961 uint64_t tbc = Props[i + 1].u.st.stat[0].uvalue;
963 *Per = double(ebc) / tbc;
970 #ifdef DEBUG_SIGNALSTATS
978 fprintf(stderr,
"\n");
994 double v = 10.0 * (dB1000 - High) / (Low - High);
998 #define REF_S1(q1) (mod == QPSK) ? q1 : 0
999 #define REF_S2(q1, q2, q3, q4) (mod == QPSK) ? q1 : (mod == PSK_8) ? q2 : (mod == APSK_16) ? q3 : (mod == APSK_32) ? q4 : 0
1000 #define REF_T1(q1, q2, q3) (mod == QPSK) ? q1 : (mod == QAM_16) ? q2 : (mod == QAM_64) ? q3 : 0
1001 #define REF_T2(q1, q2, q3, q4) (mod == QPSK) ? q1 : (mod == QAM_16) ? q2 : (mod == QAM_64) ? q3 : (mod == QAM_256) ? q4 : 0
1002 #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
1009 int mod = (FeModulation >= 0) ? FeModulation : dtp.
Modulation();
1010 int cod = (FeCoderateH >= 0) ? FeCoderateH : dtp.
CoderateH();
1011 int fec = (FeFec >= 0) ? FeFec : dtp.
CoderateH();
1018 if (mod == QAM_AUTO) mod = QPSK;
1020 case FEC_1_2: pref =
REF_T1(-93, -87, -82);
break;
1022 case FEC_2_3: pref =
REF_T1(-91, -85, -80);
break;
1023 case FEC_3_4: pref =
REF_T1(-90, -84, -78);
break;
1024 case FEC_5_6: pref =
REF_T1(-89, -83, -77);
break;
1025 case FEC_7_8: pref =
REF_T1(-88, -82, -76);
break;
1029 if (mod == QAM_AUTO) mod = QAM_64;
1031 case FEC_1_2: pref =
REF_T2(-96, -91, -86, -82);
break;
1033 case FEC_3_5: pref =
REF_T2(-95, -89, -85, -80);
break;
1034 case FEC_2_3: pref =
REF_T2(-94, -88, -83, -78);
break;
1035 case FEC_3_4: pref =
REF_T2(-93, -87, -82, -76);
break;
1036 case FEC_4_5: pref =
REF_T2(-92, -86, -81, -75);
break;
1037 case FEC_5_6: pref =
REF_T2(-92, -86, -80, -74);
break;
1041 int prel = (Strength / 1000) - pref;
1042 ssi = (prel < -15) ? 0 :
1043 (prel < 0) ? (prel + 15) * 2 / 3 :
1044 (prel < 20) ? prel * 4 + 10 :
1045 (prel < 35) ? (prel - 20) * 2 / 3 + 90 :
1047 #ifdef DEBUG_SIGNALSTRENGTH
1048 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);
1052 else if (Channel->
IsCable()) {
1057 if (mod == QAM_AUTO) mod = QAM_256;
1059 int pref =
REF_C1(-79, -76, -73, -70, -67);
1061 int prel = (Strength / 1000) - pref;
1062 ssi = (prel < -15) ? 0 :
1063 (prel < 0) ? (prel + 15) * 2 / 3 :
1064 (prel < 20) ? prel * 4 + 10 :
1065 (prel < 35) ? (prel - 20) * 2 / 3 + 90 :
1067 #ifdef DEBUG_SIGNALSTRENGTH
1068 fprintf(stderr,
"SSI-C: STR:%d, Pref:%d, Prel:%d, ssi:%d%%(mod:%d)\n", Strength, pref, prel, ssi, mod);
1072 else if (Channel->
IsSat())
1078 #define IGNORE_BER 1
1079 #define BER_ERROR_FREE (1000*1000*1000) // 1/10^-9
1089 int mod = (FeModulation >= 0) ? FeModulation : dtp.
Modulation();
1090 int cod = (FeCoderateH >= 0) ? FeCoderateH : dtp.
CoderateH();
1091 int fec = (FeFec >= 0) ? FeFec : dtp.
CoderateH();
1098 if (mod == QAM_AUTO) mod = QPSK;
1100 case FEC_1_2: cnref =
REF_T1(51, 108, 165);
break;
1102 case FEC_2_3: cnref =
REF_T1(69, 131, 187);
break;
1103 case FEC_3_4: cnref =
REF_T1(79, 146, 202);
break;
1104 case FEC_5_6: cnref =
REF_T1(89, 156, 216);
break;
1105 case FEC_7_8: cnref =
REF_T1(97, 160, 225);
break;
1109 if (mod == QAM_AUTO) mod = QAM_64;
1111 case FEC_1_2: cnref =
REF_T2(35, 87, 130, 170);
break;
1113 case FEC_3_5: cnref =
REF_T2(47, 101, 148, 194);
break;
1114 case FEC_2_3: cnref =
REF_T2(56, 114, 162, 208);
break;
1115 case FEC_3_4: cnref =
REF_T2(66, 125, 177, 229);
break;
1116 case FEC_4_5: cnref =
REF_T2(72, 133, 187, 243);
break;
1117 case FEC_5_6: cnref =
REF_T2(77, 138, 194, 251);
break;
1121 int cnrel = (Signal/100) - cnref;
1125 ber_sqi = (Ber < 1000) ? 0 :
1126 (Ber >= 10000000) ? 100 :
1127 (int)(20 * log10(Ber)) - 40;
1129 cnr_sqi = (cnrel < -70) ? 0 :
1130 (cnrel < +30) ? (100 + (cnrel - 30)) :
1132 sqi = (cnr_sqi * ber_sqi) / 100;
1137 ber_sqi = (Ber < 10000) ? 0 :
1138 (Ber >= 10000000) ? 100 * 100 / 6 :
1141 sqi = (cnrel < -30) ? 0 :
1142 (cnrel <= +30) ? (cnrel + 30) * ber_sqi / 1000 :
1147 #ifdef DEBUG_SIGNALQUALITY
1148 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);
1152 else if (Channel->
IsCable()) {
1153 if (mod == QAM_AUTO) mod = QAM_256;
1155 int cnref =
REF_C1(200, 230, 260, 290, 320);
1157 int cnrel = (Signal / 100) - cnref;
1158 int ber_sqi = (Ber < 1000) ? 0 :
1159 (Ber >= 10000000) ? 100 :
1160 (int)(20 * log10(Ber)) - 40;
1162 int cnr_sqi = (cnrel < -70) ? 0 :
1163 (cnrel < +30) ? (100 + (cnrel - 30)) :
1165 sqi = (cnr_sqi * ber_sqi) / 100;
1168 #ifdef DEBUG_SIGNALQUALITY
1169 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);
1173 else if (Channel->
IsSat()) {
1176 if (mod == QAM_AUTO) mod = QPSK;
1178 case FEC_1_2: cnref =
REF_S1(38);
break;
1180 case FEC_2_3: cnref =
REF_S1(56);
break;
1181 case FEC_3_4: cnref =
REF_S1(67);
break;
1182 case FEC_5_6: cnref =
REF_S1(77);
break;
1183 case FEC_7_8: cnref =
REF_S1(84);
break;
1189 #ifdef DEBUG_SIGNALQUALITY
1190 dsyslog(
"SQI-S1: SIG:%d, BER:%d, CNref:%d, sqi:%d%%(mod:%d, fec:%d)\n", Signal, Ber, cnref, sqi, mod, fec);
1195 if (mod == QAM_AUTO) mod = QAM_64;
1199 case FEC_2_5: cnref =
REF_S2( 7, 65, 90, 126);
break;
1200 case FEC_1_2: cnref =
REF_S2( 20, 65, 90, 126);
break;
1201 case FEC_3_5: cnref =
REF_S2( 32, 65, 90, 126);
break;
1203 case FEC_2_3: cnref =
REF_S2( 41, 76, 90, 126);
break;
1204 case FEC_3_4: cnref =
REF_S2( 50, 66, 102, 126);
break;
1205 case FEC_4_5: cnref =
REF_S2( 57, 89, 110, 136);
break;
1206 case FEC_5_6: cnref =
REF_S2( 62, 104, 116, 143);
break;
1207 case FEC_8_9: cnref =
REF_S2( 72, 117, 129, 157);
break;
1208 case FEC_9_10: cnref =
REF_S2( 74, 120, 131, 161);
break;
1214 #ifdef DEBUG_SIGNALQUALITY
1215 dsyslog(
"SQI-S2: SIG:%d, BER:%d, CNref:%d, sqi:%d%%(mod:%d, fec:%d)\n", Signal, Ber, cnref, sqi, mod, fec);
1227 for (
int i = 0; i < 1; i++) {
1229 dtv_properties CmdSeq;
1230 memset(&Props, 0,
sizeof(Props));
1231 memset(&CmdSeq, 0,
sizeof(CmdSeq));
1232 CmdSeq.props = Props;
1233 SETCMD(DTV_STAT_SIGNAL_STRENGTH, 0);
1234 SETCMD(DTV_MODULATION, 0);
1235 SETCMD(DTV_CODE_RATE_HP, 0);
1236 SETCMD(DTV_INNER_FEC, 0);
1237 if (ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
1241 int FeMod = (Props[1].u.st.len > 0) ? (
int)Props[1].u.data : -1;
1242 int FeCod = (Props[2].u.st.len > 0) ? (
int)Props[2].u.data : -1;
1243 int FeFec = (Props[3].u.st.len > 0) ? (
int)Props[3].u.data : -1;
1245 if (Props[0].u.st.len > 0) {
1246 switch (Props[0].u.st.stat[0].scale) {
1247 case FE_SCALE_DECIBEL: Signal =
StrengthToSSI(&
channel, Props[0].u.st.stat[0].svalue, FeMod, FeCod, FeFec);
1249 case FE_SCALE_RELATIVE: Signal = 100 * Props[0].u.st.stat[0].uvalue / 0xFFFF;
1253 #ifdef DEBUG_SIGNALSTRENGTH
1254 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);
1264 if (ioctl(
fd_frontend, FE_READ_SIGNAL_STRENGTH, &Signal) != -1)
1269 uint16_t MaxSignal = 0xFFFF;
1275 MaxSignal = 670;
break;
1277 int s = int(Signal) * 100 / MaxSignal;
1280 #ifdef DEBUG_SIGNALSTRENGTH
1286 #define LOCK_THRESHOLD 5 // indicates that all 5 FE_HAS_* flags are set
1291 for (
int i = 0; i < 1; i++) {
1293 dtv_properties CmdSeq;
1294 memset(&Props, 0,
sizeof(Props));
1295 memset(&CmdSeq, 0,
sizeof(CmdSeq));
1296 CmdSeq.props = Props;
1298 SETCMD(DTV_MODULATION, 0);
1299 SETCMD(DTV_CODE_RATE_HP, 0);
1300 SETCMD(DTV_INNER_FEC, 0);
1301 SETCMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0);
1302 SETCMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0);
1303 if (ioctl(
fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
1307 int FeMod = (Props[1].u.st.len > 0) ? (
int)Props[1].u.data : -1;
1308 int FeCod = (Props[2].u.st.len > 0) ? (
int)Props[2].u.data : -1;
1309 int FeFec = (Props[3].u.st.len > 0) ? (
int)Props[3].u.data : -1;
1311 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) {
1312 uint64_t ebc = Props[4].u.st.stat[0].uvalue;
1313 uint64_t tbc = Props[5].u.st.stat[0].uvalue;
1315 uint64_t BerRev = tbc / ebc;
1321 if (Props[0].u.st.len > 0) {
1322 switch (Props[0].u.st.stat[0].scale) {
1323 case FE_SCALE_DECIBEL: Cnr =
SignalToSQI(&
channel, Props[0].u.st.stat[0].svalue, Ber, FeMod, FeCod, FeFec);
1325 case FE_SCALE_RELATIVE: Cnr = 100 * Props[0].u.st.stat[0].uvalue / 0xFFFF;
1329 #ifdef DEBUG_SIGNALQUALITY
1330 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);
1341 if ((Status & FE_HAS_LOCK) == 0) {
1342 if ((Status & FE_HAS_SIGNAL) == 0)
1344 if ((Status & FE_HAS_CARRIER) == 0)
1346 if ((Status & FE_HAS_VITERBI) == 0)
1348 if ((Status & FE_HAS_SYNC) == 0)
1352 #ifdef DEBUG_SIGNALQUALITY
1359 if (errno != EINTR) {
1361 #ifdef DEBUG_SIGNALQUALITY
1367 #ifdef DEBUG_SIGNALQUALITY
1374 if (errno != EINTR) {
1376 #ifdef DEBUG_SIGNALQUALITY
1382 #ifdef DEBUG_SIGNALQUALITY
1387 if (ioctl(
fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &Unc) != -1) {
1389 #ifdef DEBUG_SIGNALQUALITY
1410 Unc >>=
min(t,
int(
sizeof(Unc) * 8 - 1));
1413 #ifdef DEBUG_SIGNALQUALITY
1419 if (errno != EINTR) {
1421 #ifdef DEBUG_SIGNALQUALITY
1427 uint16_t MinSnr = 0x0000;
1428 uint16_t MaxSnr = 0xFFFF;
1443 MaxSnr = 255;
break;
1445 int a = int(
constrain(Snr, MinSnr, MaxSnr)) * 100 / (MaxSnr - MinSnr);
1446 int b = 100 - (Unc * 10 + (Ber / 256) * 5);
1452 #ifdef DEBUG_SIGNALQUALITY
1453 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);
1462 while (f && f < 1000000)
1483 if (Diseqc->
IsScr())
1485 struct dvb_diseqc_master_cmd cmd;
1486 const char *CurrentAction = NULL;
1489 for (
int i = 0; !Break; i++) {
1490 cmd.msg_len =
sizeof(cmd.msg);
1521 default:
esyslog(
"ERROR: unknown diseqc command %d", da);
1529 if (Diseqc->
IsScr())
1542 memset(&Props, 0,
sizeof(Props));
1543 dtv_properties CmdSeq;
1544 memset(&CmdSeq, 0,
sizeof(CmdSeq));
1545 CmdSeq.props = Props;
1547 if (ioctl(
fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
1565 frequency -= diseqc->Lof();
1584 int tone = SEC_TONE_OFF;
1587 tone = SEC_TONE_OFF;
1595 tone = SEC_TONE_OFF;
1596 volt = SEC_VOLTAGE_13;
1601 frequency = abs(frequency);
1604 SETCMD(DTV_FREQUENCY, frequency * 1000UL);
1618 SETCMD(DTV_ROLLOFF, ROLLOFF_35);
1668 esyslog(
"ERROR: attempt to set channel with unknown DVB frontend type");
1672 if (ioctl(
fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
1682 bool LostLock =
false;
1683 fe_status_t Status = (fe_status_t)0;
1685 int WaitTime = 1000;
1686 fe_status_t NewStatus;
1726 if (Status & FE_REINIT) {
1734 else if (Status & FE_HAS_LOCK) {
1796 #define ST(s) if (strchr(s, type))
1814 default:
return NULL;
1868 int DvbOpen(
const char *Name,
int Adapter,
int Frontend,
int Mode,
bool ReportError)
1871 int fd = open(FileName, Mode);
1872 if (fd < 0 && ReportError)
1885 if (access(FileName, F_OK) == 0) {
1886 int f = open(FileName, O_RDONLY);
1891 else if (errno != ENODEV && errno != EINVAL)
1894 else if (errno != ENOENT)
1902 dsyslog(
"probing %s", *FileName);
1907 dsyslog(
"creating cDvbDevice");
1936 while ((a = DvbDir.
Next()) != NULL) {
1940 if (AdapterDir.
Ok()) {
1942 while ((f = AdapterDir.
Next()) != NULL) {
1957 if (Nodes.
Size() > 0) {
1959 for (
int i = 0; i < Nodes.
Size(); i++) {
1980 isyslog(
"found %d DVB device%s", Found, Found > 1 ?
"s" :
"");
1982 isyslog(
"using only %d DVB device%s", Used, Used != 1 ?
"s" :
"");
1985 isyslog(
"no DVB device found");
1997 int ErrorDevice = 0;
2002 if (!DvbDevice1->Bond(DvbDevice2))
2006 ErrorDevice = d + 1;
2009 ErrorDevice = i + 1;
2011 esyslog(
"ERROR: device '%d' in device bondings '%s' is not a cDvbDevice", ErrorDevice, Bondings);
2016 ErrorDevice = d + 1;
2019 ErrorDevice = i + 1;
2021 esyslog(
"ERROR: unknown device '%d' in device bondings '%s'", ErrorDevice, Bondings);
2042 if (Device !=
this) {
2069 while (d->bondedDevice !=
this)
2070 d = d->bondedDevice;
2072 d->bondedDevice = NULL;
2095 dmx_pes_filter_params pesFilterParams;
2096 memset(&pesFilterParams, 0,
sizeof(pesFilterParams));
2098 if (Handle->
handle < 0) {
2100 if (Handle->
handle < 0) {
2105 pesFilterParams.pid = Handle->
pid;
2106 pesFilterParams.input = DMX_IN_FRONTEND;
2107 pesFilterParams.output = DMX_OUT_TS_TAP;
2108 pesFilterParams.pes_type= DMX_PES_OTHER;
2109 pesFilterParams.flags = DMX_IMMEDIATE_START;
2110 if (ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
2115 else if (!Handle->
used) {
2118 pesFilterParams.pid = 0x1FFF;
2119 pesFilterParams.input = DMX_IN_FRONTEND;
2120 pesFilterParams.output = DMX_OUT_DECODER;
2121 pesFilterParams.pes_type= DMX_PES_OTHER;
2122 pesFilterParams.flags = DMX_IMMEDIATE_START;
2123 CHECK(ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams));
2135 int f = open(FileName, O_RDWR | O_NONBLOCK);
2137 dmx_sct_filter_params sctFilterParams;
2138 memset(&sctFilterParams, 0,
sizeof(sctFilterParams));
2139 sctFilterParams.pid = Pid;
2140 sctFilterParams.timeout = 0;
2141 sctFilterParams.flags = DMX_IMMEDIATE_START;
2142 sctFilterParams.filter.filter[0] = Tid;
2143 sctFilterParams.filter.mask[0] = Mask;
2144 if (ioctl(f, DMX_SET_FILTER, &sctFilterParams) >= 0)
2147 esyslog(
"ERROR: can't set filter (pid=%d, tid=%02X, mask=%02X): %m", Pid, Tid, Mask);
2152 esyslog(
"ERROR: can't open filter handle on '%s'", *FileName);
2191 bool result =
false;
2193 bool needsDetachReceivers =
false;
2197 result = hasPriority;
2203 if (
CamSlot()->CanDecrypt(Channel))
2206 needsDetachReceivers =
true;
2226 needsDetachReceivers |= d->Receiving();
2234 if (NeedsDetachReceivers)
2235 *NeedsDetachReceivers = needsDetachReceivers;
2254 bool cDvbDevice::SignalStats(
int &Valid,
double *Strength,
double *Cnr,
double *BerPre,
double *BerPost,
double *Per,
int *Status)
const
2326 if (cs->WantsTsData()) {
2331 Data = cs->Decrypt(Data, Available);
2348 d->cDevice::DetachAllReceivers();
2370 uint32_t SubsystemId = 0;
2373 if (stat(FileName, &st) == 0) {
2377 while ((e = d.
Next()) != NULL) {
2378 if (strstr(e->d_name,
"frontend")) {
2380 if (FILE *f = fopen(FileName,
"r")) {
2382 char *s = ReadLine.
Read(f);
2386 if (s && 2 == sscanf(s,
"%u:%u", &Major, &Minor)) {
2387 if (((Major << 8) | Minor) == st.st_rdev) {
2388 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/subsystem_vendor", e->d_name);
2389 if ((f = fopen(FileName,
"r")) != NULL) {
2390 if (
char *s = ReadLine.
Read(f))
2391 SubsystemId = strtoul(s, NULL, 0) << 16;
2395 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/idVendor", e->d_name);
2396 if ((f = fopen(FileName,
"r")) != NULL) {
2397 if (
char *s = ReadLine.
Read(f))
2398 SubsystemId = strtoul(s, NULL, 16) << 16;
2402 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/subsystem_device", e->d_name);
2403 if ((f = fopen(FileName,
"r")) != NULL) {
2404 if (
char *s = ReadLine.
Read(f))
2405 SubsystemId |= strtoul(s, NULL, 0);
2409 FileName =
cString::sprintf(
"/sys/class/dvb/%s/device/idProduct", e->d_name);
2410 if ((f = fopen(FileName,
"r")) != NULL) {
2411 if (
char *s = ReadLine.
Read(f))
2412 SubsystemId |= strtoul(s, NULL, 16);