File indexing completed on 2025-01-19 04:27:59
0001 /* 0002 * dvbdevice_linux.cpp 0003 * 0004 * Copyright (C) 2007-2011 Christoph Pfister <christophpfister@gmail.com> 0005 * Copyright (c) 2014 Mauro Carvalho Chehab <mchehab+samsung@kernel.org> 0006 * 0007 * This program is free software; you can redistribute it and/or modify 0008 * it under the terms of the GNU General Public License as published by 0009 * the Free Software Foundation; either version 2 of the License, or 0010 * (at your option) any later version. 0011 * 0012 * This program is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public License along 0018 * with this program; if not, write to the Free Software Foundation, Inc., 0019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 0020 */ 0021 0022 #include "../log.h" 0023 0024 extern "C" { 0025 #include <dmx.h> 0026 #include <errno.h> 0027 #include <fcntl.h> 0028 #include <frontend.h> 0029 #include <poll.h> 0030 } 0031 0032 #include <QFile> 0033 #include <QCheckBox> 0034 #include <QMessageLogger> 0035 #include <QRegularExpressionMatch> 0036 #include <Solid/Device> 0037 #include <Solid/DeviceNotifier> 0038 0039 #include "dvbdevice_linux.h" 0040 #include "dvbtransponder.h" 0041 0042 #if EAGAIN == EWOULDBLOCK 0043 #define IS_EAGAIN(e) (e == EAGAIN) 0044 #else 0045 #define IS_EAGAIN(e) (e == EAGAIN || e == EWOULDBLOCK) 0046 #endif 0047 0048 // krazy:excludeall=syscalls 0049 0050 DvbLinuxDevice::DvbLinuxDevice(QObject *parent) : QThread(parent), ready(false), frontend(NULL), 0051 enabled(false), dvrFd(-1), dvrBuffer(NULL, 0), cam(parent) 0052 { 0053 verbose = 1; 0054 numDemux = 0; 0055 dvrPipe[0] = -1; 0056 dvrPipe[1] = -1; 0057 } 0058 0059 DvbLinuxDevice::~DvbLinuxDevice() 0060 { 0061 stopDevice(); 0062 } 0063 0064 static void dvbv5_log(int level, const char *fmt, ...) 0065 { 0066 va_list ap; 0067 char log[1024]; 0068 0069 va_start(ap, fmt); 0070 vsnprintf(log, sizeof(log), fmt, ap); 0071 va_end(ap); 0072 0073 switch(LOG_PRI(level)) { 0074 case LOG_DEBUG: 0075 case LOG_INFO: 0076 qCDebug(logDev, "%s", log); 0077 break; 0078 case LOG_NOTICE: 0079 qCInfo(logDev, "%s", log); 0080 break; 0081 case LOG_WARNING: 0082 qCWarning(logDev, "%s", log); 0083 break; 0084 case LOG_ERR: 0085 case LOG_CRIT: 0086 case LOG_ALERT: 0087 case LOG_EMERG: 0088 qCCritical(logDev, "%s", log); 0089 break; 0090 } 0091 } 0092 0093 bool DvbLinuxDevice::isReady() const 0094 { 0095 return ready; 0096 } 0097 0098 void DvbLinuxDevice::startDevice(const QString &deviceId_) 0099 { 0100 Q_ASSERT(!ready); 0101 struct dvb_v5_fe_parms *parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log); 0102 0103 if (!parms) { 0104 qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath)); 0105 return; 0106 } 0107 0108 transmissionTypes = Nothing; 0109 for (int i = 0; i < parms->num_systems; i++) { 0110 switch (parms->systems[i]) { 0111 case SYS_DVBS: 0112 transmissionTypes |= DvbS; 0113 break; 0114 case SYS_DVBS2: 0115 transmissionTypes |= DvbS2; 0116 break; 0117 case SYS_DVBT: 0118 transmissionTypes |= DvbT; 0119 break; 0120 case SYS_DVBT2: 0121 transmissionTypes |= DvbT2; 0122 break; 0123 case SYS_DVBC_ANNEX_A: 0124 case SYS_DVBC_ANNEX_C: 0125 transmissionTypes |= DvbC; 0126 break; 0127 case SYS_ATSC: 0128 case SYS_DVBC_ANNEX_B: 0129 transmissionTypes |= Atsc; 0130 break; 0131 case SYS_ISDBT: 0132 transmissionTypes |= IsdbT; 0133 break; 0134 default: /* not supported yet */ 0135 qCWarning(logDev, "Unsupported transmission type: %d", parms->systems[i]); 0136 break; 0137 } 0138 } 0139 0140 deviceId = deviceId_; 0141 frontendName = QString::fromUtf8(parms->info.name); 0142 0143 capabilities = None; 0144 0145 if ((parms->info.caps & FE_CAN_QAM_AUTO) != 0) { 0146 capabilities |= DvbTModulationAuto; 0147 } 0148 0149 if ((parms->info.caps & FE_CAN_FEC_AUTO) != 0) { 0150 capabilities |= DvbTFecAuto; 0151 } 0152 0153 if ((parms->info.caps & FE_CAN_TRANSMISSION_MODE_AUTO) != 0) { 0154 capabilities |= DvbTTransmissionModeAuto; 0155 } 0156 0157 if ((parms->info.caps & FE_CAN_GUARD_INTERVAL_AUTO) != 0) { 0158 capabilities |= DvbTGuardIntervalAuto; 0159 } 0160 0161 // Get the supported LNBf types if the device supports satellite 0162 if (transmissionTypes & (DvbS | DvbS2)) { 0163 for (int i = 0;; i++) { 0164 const struct dvb_sat_lnb *lnb = dvb_sat_get_lnb(i); 0165 0166 if (!lnb) 0167 break; 0168 0169 struct lnbSat lnbSat; 0170 0171 // FIXME: on newer libdvbv5, use dvb_sat_get_lnb_name() in 0172 // order to get the name i18n translated 0173 lnbSat.name = QString::fromUtf8(lnb->name); 0174 lnbSat.alias = QString::fromUtf8(lnb->alias); 0175 lnbSat.lowFreq = lnb->lowfreq; 0176 lnbSat.highFreq = lnb->highfreq; 0177 lnbSat.rangeSwitch = lnb->rangeswitch; 0178 lnbSat.freqRange[0].low = lnb->freqrange[0].low; 0179 lnbSat.freqRange[0].high = lnb->freqrange[0].high; 0180 lnbSat.freqRange[1].low = lnb->freqrange[1].low; 0181 lnbSat.freqRange[1].high = lnb->freqrange[1].high; 0182 0183 qCDebug(logDev, "supports lnb %s", lnb->alias); 0184 0185 lnbSatModels.append(lnbSat); 0186 } 0187 } 0188 0189 dvb_fe_close(parms); 0190 0191 ready = true; 0192 0193 qCInfo(logDev, "Found dvb device %s: %s", qPrintable(deviceId), qPrintable(frontendName)); 0194 } 0195 0196 void DvbLinuxDevice::startCa() 0197 { 0198 Q_ASSERT(ready && !caPath.isEmpty()); 0199 0200 if (enabled) { 0201 cam.startCa(caPath); 0202 } 0203 } 0204 0205 void DvbLinuxDevice::stopCa() 0206 { 0207 Q_ASSERT(ready && caPath.isEmpty()); 0208 0209 if (enabled) { 0210 cam.stopCa(); 0211 } 0212 } 0213 0214 void DvbLinuxDevice::stopDevice() 0215 { 0216 setDeviceEnabled(false); 0217 ready = false; 0218 } 0219 0220 QString DvbLinuxDevice::getDeviceId() 0221 { 0222 Q_ASSERT(ready); 0223 return deviceId; 0224 } 0225 0226 QString DvbLinuxDevice::getFrontendName() 0227 { 0228 Q_ASSERT(ready); 0229 return frontendName; 0230 } 0231 0232 DvbLinuxDevice::TransmissionTypes DvbLinuxDevice::getTransmissionTypes() 0233 { 0234 Q_ASSERT(ready); 0235 return transmissionTypes; 0236 } 0237 0238 DvbLinuxDevice::Capabilities DvbLinuxDevice::getCapabilities() 0239 { 0240 Q_ASSERT(ready); 0241 return capabilities; 0242 } 0243 0244 void DvbLinuxDevice::setFrontendDevice(DvbFrontendDevice *frontend_) 0245 { 0246 frontend = frontend_; 0247 } 0248 0249 void DvbLinuxDevice::setDeviceEnabled(bool enabled_) 0250 { 0251 Q_ASSERT(ready); 0252 0253 if (enabled != enabled_) { 0254 enabled = enabled_; 0255 0256 if (enabled) { 0257 if (!caPath.isEmpty()) { 0258 cam.startCa(caPath); 0259 } 0260 } else { 0261 release(); 0262 cam.stopCa(); 0263 } 0264 } 0265 } 0266 0267 bool DvbLinuxDevice::acquire() 0268 { 0269 Q_ASSERT(enabled && (!dvbv5_parms) && (dvrFd < 0)); 0270 dvbv5_parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log); 0271 0272 if (!dvbv5_parms) { 0273 qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath)); 0274 return false; 0275 } 0276 0277 dvrFd = open(QFile::encodeName(dvrPath).constData(), O_RDONLY | O_NONBLOCK | O_CLOEXEC); 0278 0279 if (dvrFd < 0) { 0280 qCWarning(logDev, "Cannot open dvr %s", qPrintable(dvrPath)); 0281 dvb_fe_close(dvbv5_parms); 0282 dvbv5_parms = NULL; 0283 return false; 0284 } 0285 0286 return true; 0287 } 0288 0289 bool DvbLinuxDevice::setHighVoltage(int higherVoltage) 0290 { 0291 Q_ASSERT(dvbv5_parms); 0292 0293 if ((Qt::CheckState)higherVoltage == Qt::PartiallyChecked) 0294 return true; 0295 0296 if (dvb_fe_lnb_high_voltage(dvbv5_parms, higherVoltage ? 1 : 0)) 0297 return false; 0298 0299 return true; 0300 } 0301 0302 bool DvbLinuxDevice::sendMessage(const char *message, int length) 0303 { 0304 Q_ASSERT(dvbv5_parms && (length >= 0) && (length <= 6)); 0305 0306 if (dvb_fe_diseqc_cmd(dvbv5_parms, length, (const unsigned char *)message) != 0) { 0307 qCWarning(logDev, "ioctl FE_DISEQC_SEND_MASTER_CMD failed for frontend %s", qPrintable(frontendPath)); 0308 return false; 0309 } 0310 0311 return true; 0312 } 0313 0314 bool DvbLinuxDevice::sendBurst(SecBurst burst) 0315 { 0316 Q_ASSERT(dvbv5_parms); 0317 0318 if (dvb_fe_diseqc_burst(dvbv5_parms, burst == BurstMiniB) != 0) { 0319 qCWarning(logDev, "ioctl FE_DISEQC_SEND_BURST failed for frontend %s", qPrintable(frontendPath)); 0320 return false; 0321 } 0322 0323 return true; 0324 } 0325 0326 static fe_modulation_t toDvbModulation(DvbCTransponder::Modulation modulation) 0327 { 0328 switch (modulation) { 0329 case DvbCTransponder::Qam16: return QAM_16; 0330 case DvbCTransponder::Qam32: return QAM_32; 0331 case DvbCTransponder::Qam64: return QAM_64; 0332 case DvbCTransponder::Qam128: return QAM_128; 0333 case DvbCTransponder::Qam256: return QAM_256; 0334 case DvbCTransponder::ModulationAuto: return QAM_AUTO; 0335 } 0336 0337 return QAM_AUTO; 0338 } 0339 0340 static fe_modulation_t toDvbModulation(DvbS2Transponder::Modulation modulation) 0341 { 0342 switch (modulation) { 0343 case DvbS2Transponder::Qpsk: return QPSK; 0344 case DvbS2Transponder::Psk8: return PSK_8; 0345 case DvbS2Transponder::Apsk16: return APSK_16; 0346 case DvbS2Transponder::Apsk32: return APSK_32; 0347 case DvbS2Transponder::ModulationAuto: return QAM_AUTO; 0348 } 0349 0350 return QAM_AUTO; 0351 } 0352 0353 static fe_rolloff toDvbRollOff(DvbS2Transponder::RollOff rollOff) 0354 { 0355 switch (rollOff) { 0356 case DvbS2Transponder::RollOff20: return ROLLOFF_20; 0357 case DvbS2Transponder::RollOff25: return ROLLOFF_25; 0358 case DvbS2Transponder::RollOff35: return ROLLOFF_35; 0359 case DvbS2Transponder::RollOffAuto: return ROLLOFF_AUTO; 0360 } 0361 0362 return ROLLOFF_AUTO; 0363 } 0364 0365 static fe_modulation_t toDvbModulation(DvbTTransponder::Modulation modulation) 0366 { 0367 switch (modulation) { 0368 case DvbTTransponder::Qpsk: return QPSK; 0369 case DvbTTransponder::Qam16: return QAM_16; 0370 case DvbTTransponder::Qam64: return QAM_64; 0371 case DvbTTransponder::ModulationAuto: return QAM_AUTO; 0372 } 0373 0374 return QAM_AUTO; 0375 } 0376 0377 static fe_modulation_t toDvbModulation(DvbT2Transponder::Modulation modulation) 0378 { 0379 switch (modulation) { 0380 case DvbT2Transponder::Qpsk: return QPSK; 0381 case DvbT2Transponder::Qam16: return QAM_16; 0382 case DvbT2Transponder::Qam64: return QAM_64; 0383 case DvbT2Transponder::Qam256: return QAM_256; 0384 case DvbT2Transponder::ModulationAuto: return QAM_AUTO; 0385 } 0386 0387 return QAM_AUTO; 0388 } 0389 0390 static fe_modulation_t toDvbModulation(IsdbTTransponder::Modulation modulation) 0391 { 0392 switch (modulation) { 0393 case IsdbTTransponder::Qpsk: return QPSK; 0394 case IsdbTTransponder::Dqpsk: return DQPSK; 0395 case IsdbTTransponder::Qam16: return QAM_16; 0396 case IsdbTTransponder::Qam64: return QAM_64; 0397 case IsdbTTransponder::ModulationAuto: return QAM_AUTO; 0398 } 0399 0400 return QAM_AUTO; 0401 } 0402 0403 static fe_modulation_t toDvbModulation(AtscTransponder::Modulation modulation) 0404 { 0405 switch (modulation) { 0406 case AtscTransponder::Qam64: return QAM_64; 0407 case AtscTransponder::Qam256: return QAM_256; 0408 case AtscTransponder::Vsb8: return VSB_8; 0409 case AtscTransponder::Vsb16: return VSB_16; 0410 case AtscTransponder::ModulationAuto: return QAM_AUTO; 0411 } 0412 0413 return QAM_AUTO; 0414 } 0415 0416 static fe_code_rate toDvbFecRate(DvbTransponderBase::FecRate fecRate) 0417 { 0418 switch (fecRate) { 0419 case DvbTransponderBase::FecNone: return FEC_NONE; 0420 case DvbTransponderBase::Fec1_2: return FEC_1_2; 0421 case DvbTransponderBase::Fec1_3: return FEC_AUTO; // FIXME 0422 case DvbTransponderBase::Fec1_4: return FEC_AUTO; // FIXME 0423 case DvbTransponderBase::Fec2_3: return FEC_2_3; 0424 case DvbTransponderBase::Fec2_5: return FEC_2_5; 0425 case DvbTransponderBase::Fec3_4: return FEC_3_4; 0426 case DvbTransponderBase::Fec3_5: return FEC_3_5; 0427 case DvbTransponderBase::Fec4_5: return FEC_4_5; 0428 case DvbTransponderBase::Fec5_6: return FEC_5_6; 0429 case DvbTransponderBase::Fec6_7: return FEC_6_7; 0430 case DvbTransponderBase::Fec7_8: return FEC_7_8; 0431 case DvbTransponderBase::Fec8_9: return FEC_8_9; 0432 case DvbTransponderBase::Fec9_10: return FEC_9_10; 0433 case DvbTransponderBase::FecAuto: return FEC_AUTO; 0434 } 0435 0436 return FEC_AUTO; 0437 } 0438 0439 static uint32_t toDvbBandwidth(DvbTTransponder::Bandwidth bandwidth) 0440 { 0441 switch (bandwidth) { 0442 case DvbTTransponder::Bandwidth5MHz: return 5000000; 0443 case DvbTTransponder::Bandwidth6MHz: return 6000000; 0444 case DvbTTransponder::Bandwidth7MHz: return 7000000; 0445 case DvbTTransponder::Bandwidth8MHz: return 8000000; 0446 case DvbTTransponder::BandwidthAuto: return 0; 0447 } 0448 0449 return BANDWIDTH_AUTO; 0450 } 0451 0452 static uint32_t toDvbBandwidth(DvbT2Transponder::Bandwidth bandwidth) 0453 { 0454 switch (bandwidth) { 0455 case DvbT2Transponder::Bandwidth1_7MHz: return 1700000; 0456 case DvbT2Transponder::Bandwidth5MHz: return 5000000; 0457 case DvbT2Transponder::Bandwidth6MHz: return 6000000; 0458 case DvbT2Transponder::Bandwidth7MHz: return 7000000; 0459 case DvbT2Transponder::Bandwidth8MHz: return 8000000; 0460 case DvbT2Transponder::Bandwidth10MHz: return 10000000; 0461 case DvbT2Transponder::BandwidthAuto: return 0; 0462 } 0463 0464 return BANDWIDTH_AUTO; 0465 } 0466 0467 static uint32_t toDvbBandwidth(IsdbTTransponder::Bandwidth bandwidth) 0468 { 0469 switch (bandwidth) { 0470 case IsdbTTransponder::Bandwidth6MHz: return 6000000; 0471 case IsdbTTransponder::Bandwidth7MHz: return 7000000; 0472 case IsdbTTransponder::Bandwidth8MHz: return 8000000; 0473 } 0474 0475 return BANDWIDTH_AUTO; 0476 } 0477 0478 static fe_transmit_mode toDvbTransmissionMode(DvbTTransponder::TransmissionMode mode) 0479 { 0480 switch (mode) { 0481 case DvbTTransponder::TransmissionMode2k: return TRANSMISSION_MODE_2K; 0482 case DvbTTransponder::TransmissionMode4k: return TRANSMISSION_MODE_4K; 0483 case DvbTTransponder::TransmissionMode8k: return TRANSMISSION_MODE_8K; 0484 case DvbTTransponder::TransmissionModeAuto: return TRANSMISSION_MODE_AUTO; 0485 } 0486 0487 return TRANSMISSION_MODE_AUTO; 0488 } 0489 0490 static fe_transmit_mode toDvbTransmissionMode(DvbT2Transponder::TransmissionMode mode) 0491 { 0492 switch (mode) { 0493 case DvbT2Transponder::TransmissionMode1k: return TRANSMISSION_MODE_1K; 0494 case DvbT2Transponder::TransmissionMode2k: return TRANSMISSION_MODE_2K; 0495 case DvbT2Transponder::TransmissionMode4k: return TRANSMISSION_MODE_4K; 0496 case DvbT2Transponder::TransmissionMode8k: return TRANSMISSION_MODE_8K; 0497 case DvbT2Transponder::TransmissionMode16k: return TRANSMISSION_MODE_16K; 0498 case DvbT2Transponder::TransmissionMode32k: return TRANSMISSION_MODE_32K; 0499 case DvbT2Transponder::TransmissionModeAuto: return TRANSMISSION_MODE_AUTO; 0500 } 0501 0502 return TRANSMISSION_MODE_AUTO; 0503 } 0504 0505 static fe_transmit_mode toDvbTransmissionMode(IsdbTTransponder::TransmissionMode mode) 0506 { 0507 switch (mode) { 0508 case IsdbTTransponder::TransmissionMode2k: return TRANSMISSION_MODE_2K; 0509 case IsdbTTransponder::TransmissionMode4k: return TRANSMISSION_MODE_4K; 0510 case IsdbTTransponder::TransmissionMode8k: return TRANSMISSION_MODE_8K; 0511 case IsdbTTransponder::TransmissionModeAuto: return TRANSMISSION_MODE_AUTO; 0512 } 0513 0514 return TRANSMISSION_MODE_AUTO; 0515 } 0516 0517 static fe_guard_interval toDvbGuardInterval(DvbTTransponder::GuardInterval guardInterval) 0518 { 0519 switch (guardInterval) { 0520 case DvbTTransponder::GuardInterval1_4: return GUARD_INTERVAL_1_4; 0521 case DvbTTransponder::GuardInterval1_8: return GUARD_INTERVAL_1_8; 0522 case DvbTTransponder::GuardInterval1_16: return GUARD_INTERVAL_1_16; 0523 case DvbTTransponder::GuardInterval1_32: return GUARD_INTERVAL_1_32; 0524 case DvbTTransponder::GuardIntervalAuto: return GUARD_INTERVAL_AUTO; 0525 } 0526 0527 return GUARD_INTERVAL_AUTO; 0528 } 0529 0530 static fe_guard_interval toDvbGuardInterval(DvbT2Transponder::GuardInterval guardInterval) 0531 { 0532 switch (guardInterval) { 0533 case DvbT2Transponder::GuardInterval1_4: return GUARD_INTERVAL_1_4; 0534 case DvbT2Transponder::GuardInterval19_128: return GUARD_INTERVAL_19_128; 0535 case DvbT2Transponder::GuardInterval1_8: return GUARD_INTERVAL_1_8; 0536 case DvbT2Transponder::GuardInterval19_256: return GUARD_INTERVAL_19_256; 0537 case DvbT2Transponder::GuardInterval1_16: return GUARD_INTERVAL_1_16; 0538 case DvbT2Transponder::GuardInterval1_32: return GUARD_INTERVAL_1_32; 0539 case DvbT2Transponder::GuardInterval1_128: return GUARD_INTERVAL_1_128; 0540 case DvbT2Transponder::GuardIntervalAuto: return GUARD_INTERVAL_AUTO; 0541 } 0542 0543 return GUARD_INTERVAL_AUTO; 0544 } 0545 0546 static fe_guard_interval toDvbGuardInterval(IsdbTTransponder::GuardInterval guardInterval) 0547 { 0548 switch (guardInterval) { 0549 case IsdbTTransponder::GuardInterval1_4: return GUARD_INTERVAL_1_4; 0550 case IsdbTTransponder::GuardInterval1_8: return GUARD_INTERVAL_1_8; 0551 case IsdbTTransponder::GuardInterval1_16: return GUARD_INTERVAL_1_16; 0552 case IsdbTTransponder::GuardInterval1_32: return GUARD_INTERVAL_1_32; 0553 case IsdbTTransponder::GuardIntervalAuto: return GUARD_INTERVAL_AUTO; 0554 } 0555 0556 return GUARD_INTERVAL_AUTO; 0557 } 0558 0559 static uint32_t toDvbPartialReception(IsdbTTransponder::PartialReception partialReception) 0560 { 0561 switch (partialReception) { 0562 case IsdbTTransponder::PR_disabled: return 0; 0563 case IsdbTTransponder::PR_enabled: return 1; 0564 case IsdbTTransponder::PR_AUTO: return (uint32_t)-1; 0565 } 0566 0567 return (uint32_t)-1; 0568 } 0569 0570 static uint32_t toDvbSoundBroadcasting(IsdbTTransponder::SoundBroadcasting partialReception) 0571 { 0572 switch (partialReception) { 0573 case IsdbTTransponder::SB_disabled: return 0; 0574 case IsdbTTransponder::SB_enabled: return 1; 0575 case IsdbTTransponder::SB_AUTO: return (uint32_t)-1; 0576 } 0577 0578 return (uint32_t)-1; 0579 } 0580 0581 static uint32_t toDvbInterleaving(IsdbTTransponder::Interleaving interleaving) 0582 { 0583 switch (interleaving) { 0584 case IsdbTTransponder::I_0: return 0; 0585 case IsdbTTransponder::I_1: return 1; 0586 case IsdbTTransponder::I_2: return 2; 0587 case IsdbTTransponder::I_4: return 4; 0588 case IsdbTTransponder::I_8: return 8; 0589 case IsdbTTransponder::I_16: return 16; 0590 case IsdbTTransponder::I_AUTO: return (uint32_t)-1; 0591 } 0592 0593 return (uint32_t)-1; 0594 } 0595 0596 static uint32_t toDvbPolarization(DvbSTransponder::Polarization polarization) 0597 { 0598 switch (polarization) { 0599 case DvbSTransponder::Off: return POLARIZATION_OFF; 0600 case DvbSTransponder::Horizontal: return POLARIZATION_H; 0601 case DvbSTransponder::Vertical: return POLARIZATION_V; 0602 case DvbSTransponder::CircularLeft: return POLARIZATION_L; 0603 case DvbSTransponder::CircularRight: return POLARIZATION_R; 0604 } 0605 0606 return (uint32_t)-1; 0607 } 0608 0609 static fe_hierarchy toDvbHierarchy(DvbTTransponder::Hierarchy hierarchy) 0610 { 0611 switch (hierarchy) { 0612 case DvbTTransponder::HierarchyNone: return HIERARCHY_NONE; 0613 case DvbTTransponder::Hierarchy1: return HIERARCHY_1; 0614 case DvbTTransponder::Hierarchy2: return HIERARCHY_2; 0615 case DvbTTransponder::Hierarchy4: return HIERARCHY_4; 0616 case DvbTTransponder::HierarchyAuto: return HIERARCHY_AUTO; 0617 } 0618 0619 return HIERARCHY_AUTO; 0620 } 0621 0622 static fe_hierarchy toDvbHierarchy(DvbT2Transponder::Hierarchy hierarchy) 0623 { 0624 switch (hierarchy) { 0625 case DvbT2Transponder::HierarchyNone: return HIERARCHY_NONE; 0626 case DvbT2Transponder::Hierarchy1: return HIERARCHY_1; 0627 case DvbT2Transponder::Hierarchy2: return HIERARCHY_2; 0628 case DvbT2Transponder::Hierarchy4: return HIERARCHY_4; 0629 case DvbT2Transponder::HierarchyAuto: return HIERARCHY_AUTO; 0630 } 0631 0632 return HIERARCHY_AUTO; 0633 } 0634 0635 static DvbCTransponder::Modulation DvbCtoModulation(uint32_t modulation) 0636 { 0637 switch (modulation) { 0638 case QAM_16: return DvbCTransponder::Qam16; 0639 case QAM_32: return DvbCTransponder::Qam32; 0640 case QAM_64: return DvbCTransponder::Qam64; 0641 case QAM_128: return DvbCTransponder::Qam128; 0642 case QAM_256: return DvbCTransponder::Qam256; 0643 default: return DvbCTransponder::ModulationAuto; 0644 } 0645 } 0646 0647 static DvbS2Transponder::Modulation DvbS2toModulation(uint32_t modulation) 0648 { 0649 switch (modulation) { 0650 case QPSK: return DvbS2Transponder::Qpsk; 0651 case PSK_8: return DvbS2Transponder::Psk8; 0652 case APSK_16: return DvbS2Transponder::Apsk16; 0653 case APSK_32: return DvbS2Transponder::Apsk32; 0654 default: return DvbS2Transponder::ModulationAuto; 0655 } 0656 } 0657 0658 static DvbS2Transponder::RollOff DvbS2toRollOff(uint32_t rollOff) 0659 { 0660 switch (rollOff) { 0661 case ROLLOFF_20: return DvbS2Transponder::RollOff20; 0662 case ROLLOFF_25: return DvbS2Transponder::RollOff25; 0663 case ROLLOFF_35: return DvbS2Transponder::RollOff35; 0664 default: return DvbS2Transponder::RollOffAuto; 0665 } 0666 } 0667 0668 static DvbTTransponder::Modulation DvbTtoModulation(uint32_t modulation) 0669 { 0670 switch (modulation) { 0671 case QPSK: return DvbTTransponder::Qpsk; 0672 case QAM_16: return DvbTTransponder::Qam16; 0673 case QAM_64: return DvbTTransponder::Qam64; 0674 default: return DvbTTransponder::ModulationAuto; 0675 } 0676 } 0677 0678 static DvbT2Transponder::Modulation DvbT2toModulation(uint32_t modulation) 0679 { 0680 switch (modulation) { 0681 case QPSK: return DvbT2Transponder::Qpsk; 0682 case QAM_16: return DvbT2Transponder::Qam16; 0683 case QAM_64: return DvbT2Transponder::Qam64; 0684 case QAM_256: return DvbT2Transponder::Qam256; 0685 default: return DvbT2Transponder::ModulationAuto; 0686 } 0687 } 0688 0689 static IsdbTTransponder::Modulation IsdbTtoModulation(uint32_t modulation) 0690 { 0691 switch (modulation) { 0692 case QPSK: return IsdbTTransponder::Qpsk; 0693 case DQPSK: return IsdbTTransponder::Dqpsk; 0694 case QAM_16: return IsdbTTransponder::Qam16; 0695 case QAM_64: return IsdbTTransponder::Qam64; 0696 default: return IsdbTTransponder::ModulationAuto; 0697 } 0698 } 0699 0700 static AtscTransponder::Modulation AtsctoModulation(uint32_t modulation) 0701 { 0702 switch (modulation) { 0703 case QAM_64: return AtscTransponder::Qam64; 0704 case QAM_256: return AtscTransponder::Qam256; 0705 case VSB_8: return AtscTransponder::Vsb8; 0706 case VSB_16: return AtscTransponder::Vsb16; 0707 default: return AtscTransponder::ModulationAuto; 0708 } 0709 } 0710 0711 static DvbTransponderBase::FecRate DvbtoFecRate(uint32_t fecRate) 0712 { 0713 switch (fecRate) { 0714 case FEC_NONE: return DvbTransponderBase::FecNone; 0715 case FEC_1_2: return DvbTransponderBase::Fec1_2; 0716 // case FEC_AUTO: return DvbTransponderBase::Fec1_3; // FIXME 0717 // case FEC_AUTO: return DvbTransponderBase::Fec1_4; // FIXME 0718 case FEC_2_3: return DvbTransponderBase::Fec2_3; 0719 case FEC_2_5: return DvbTransponderBase::Fec2_5; 0720 case FEC_3_4: return DvbTransponderBase::Fec3_4; 0721 case FEC_3_5: return DvbTransponderBase::Fec3_5; 0722 case FEC_4_5: return DvbTransponderBase::Fec4_5; 0723 case FEC_5_6: return DvbTransponderBase::Fec5_6; 0724 case FEC_6_7: return DvbTransponderBase::Fec6_7; 0725 case FEC_7_8: return DvbTransponderBase::Fec7_8; 0726 case FEC_8_9: return DvbTransponderBase::Fec8_9; 0727 case FEC_9_10: return DvbTransponderBase::Fec9_10; 0728 default: return DvbTransponderBase::FecAuto; 0729 } 0730 } 0731 0732 static DvbTTransponder::Bandwidth DvbTtoBandwidth(uint32_t bandwidth) 0733 { 0734 switch (bandwidth) { 0735 case 5000000: return DvbTTransponder::Bandwidth5MHz; 0736 case 6000000: return DvbTTransponder::Bandwidth6MHz; 0737 case 7000000: return DvbTTransponder::Bandwidth7MHz; 0738 case 8000000: return DvbTTransponder::Bandwidth8MHz; 0739 default: return DvbTTransponder::BandwidthAuto; 0740 } 0741 } 0742 0743 static DvbT2Transponder::Bandwidth DvbT2toBandwidth(uint32_t bandwidth) 0744 { 0745 switch (bandwidth) { 0746 case 1700000: return DvbT2Transponder::Bandwidth1_7MHz; 0747 case 5000000: return DvbT2Transponder::Bandwidth5MHz; 0748 case 6000000: return DvbT2Transponder::Bandwidth6MHz; 0749 case 7000000: return DvbT2Transponder::Bandwidth7MHz; 0750 case 8000000: return DvbT2Transponder::Bandwidth8MHz; 0751 case 10000000: return DvbT2Transponder::Bandwidth10MHz; 0752 default: return DvbT2Transponder::BandwidthAuto; 0753 } 0754 } 0755 0756 static IsdbTTransponder::Bandwidth IsdbTtoBandwidth(uint32_t bandwidth) 0757 { 0758 switch (bandwidth) { 0759 default: return IsdbTTransponder::Bandwidth6MHz; 0760 case 7000000: return IsdbTTransponder::Bandwidth7MHz; 0761 case 8000000: return IsdbTTransponder::Bandwidth8MHz; 0762 } 0763 } 0764 0765 static DvbTTransponder::TransmissionMode DvbTtoTransmissionMode(uint32_t mode) 0766 { 0767 switch (mode) { 0768 case TRANSMISSION_MODE_2K: return DvbTTransponder::TransmissionMode2k; 0769 case TRANSMISSION_MODE_4K: return DvbTTransponder::TransmissionMode4k; 0770 case TRANSMISSION_MODE_8K: return DvbTTransponder::TransmissionMode8k; 0771 default: return DvbTTransponder::TransmissionModeAuto; 0772 } 0773 } 0774 0775 static DvbT2Transponder::TransmissionMode DvbT2toTransmissionMode(uint32_t mode) 0776 { 0777 switch (mode) { 0778 case TRANSMISSION_MODE_1K: return DvbT2Transponder::TransmissionMode1k; 0779 case TRANSMISSION_MODE_2K: return DvbT2Transponder::TransmissionMode2k; 0780 case TRANSMISSION_MODE_4K: return DvbT2Transponder::TransmissionMode4k; 0781 case TRANSMISSION_MODE_8K: return DvbT2Transponder::TransmissionMode8k; 0782 case TRANSMISSION_MODE_16K: return DvbT2Transponder::TransmissionMode16k; 0783 case TRANSMISSION_MODE_32K: return DvbT2Transponder::TransmissionMode32k; 0784 default: return DvbT2Transponder::TransmissionModeAuto; 0785 } 0786 } 0787 0788 static IsdbTTransponder::TransmissionMode IsdbTtoTransmissionMode(uint32_t mode) 0789 { 0790 switch (mode) { 0791 case TRANSMISSION_MODE_2K: return IsdbTTransponder::TransmissionMode2k; 0792 case TRANSMISSION_MODE_4K: return IsdbTTransponder::TransmissionMode4k; 0793 case TRANSMISSION_MODE_8K: return IsdbTTransponder::TransmissionMode8k; 0794 default: return IsdbTTransponder::TransmissionModeAuto; 0795 } 0796 } 0797 0798 static DvbTTransponder::GuardInterval DvbTtoGuardInterval(uint32_t guardInterval) 0799 { 0800 switch (guardInterval) { 0801 case GUARD_INTERVAL_1_4: return DvbTTransponder::GuardInterval1_4; 0802 case GUARD_INTERVAL_1_8: return DvbTTransponder::GuardInterval1_8; 0803 case GUARD_INTERVAL_1_16: return DvbTTransponder::GuardInterval1_16; 0804 case GUARD_INTERVAL_1_32: return DvbTTransponder::GuardInterval1_32; 0805 default: return DvbTTransponder::GuardIntervalAuto; 0806 } 0807 } 0808 0809 static DvbT2Transponder::GuardInterval DvbT2toGuardInterval(uint32_t guardInterval) 0810 { 0811 switch (guardInterval) { 0812 case GUARD_INTERVAL_1_4: return DvbT2Transponder::GuardInterval1_4; 0813 case GUARD_INTERVAL_19_128: return DvbT2Transponder::GuardInterval19_128; 0814 case GUARD_INTERVAL_1_8: return DvbT2Transponder::GuardInterval1_8; 0815 case GUARD_INTERVAL_19_256: return DvbT2Transponder::GuardInterval19_256; 0816 case GUARD_INTERVAL_1_16: return DvbT2Transponder::GuardInterval1_16; 0817 case GUARD_INTERVAL_1_32: return DvbT2Transponder::GuardInterval1_32; 0818 case GUARD_INTERVAL_1_128: return DvbT2Transponder::GuardInterval1_128; 0819 default: return DvbT2Transponder::GuardIntervalAuto; 0820 } 0821 } 0822 0823 static IsdbTTransponder::GuardInterval IsdbTtoGuardInterval(uint32_t guardInterval) 0824 { 0825 switch (guardInterval) { 0826 case GUARD_INTERVAL_1_4: return IsdbTTransponder::GuardInterval1_4; 0827 case GUARD_INTERVAL_1_8: return IsdbTTransponder::GuardInterval1_8; 0828 case GUARD_INTERVAL_1_16: return IsdbTTransponder::GuardInterval1_16; 0829 case GUARD_INTERVAL_1_32: return IsdbTTransponder::GuardInterval1_32; 0830 default: return IsdbTTransponder::GuardIntervalAuto; 0831 } 0832 } 0833 0834 static IsdbTTransponder::PartialReception IsdbTtoPartialReception(uint32_t partialReception) 0835 { 0836 switch (partialReception) { 0837 case 0: return IsdbTTransponder::PR_disabled; 0838 case 1: return IsdbTTransponder::PR_enabled; 0839 default: return IsdbTTransponder::PR_AUTO; 0840 } 0841 } 0842 0843 static IsdbTTransponder::SoundBroadcasting IsdbTtoSoundBroadcasting(uint32_t partialReception) 0844 { 0845 switch (partialReception) { 0846 case 0: return IsdbTTransponder::SB_disabled; 0847 case 1: return IsdbTTransponder::SB_enabled; 0848 default: return IsdbTTransponder::SB_AUTO; 0849 } 0850 } 0851 0852 static IsdbTTransponder::Interleaving IsdbTtoInterleaving(uint32_t interleaving) 0853 { 0854 switch (interleaving) { 0855 case 0: return IsdbTTransponder::I_0; 0856 case 1: return IsdbTTransponder::I_1; 0857 case 2: return IsdbTTransponder::I_2; 0858 case 4: return IsdbTTransponder::I_4; 0859 case 8: return IsdbTTransponder::I_8; 0860 case 16: return IsdbTTransponder::I_16; 0861 default: return IsdbTTransponder::I_AUTO; 0862 } 0863 } 0864 0865 static DvbTTransponder::Hierarchy DvbTtoHierarchy(uint32_t hierarchy) 0866 { 0867 switch (hierarchy) { 0868 case HIERARCHY_NONE: return DvbTTransponder::HierarchyNone; 0869 case HIERARCHY_1: return DvbTTransponder::Hierarchy1; 0870 case HIERARCHY_2: return DvbTTransponder::Hierarchy2; 0871 case HIERARCHY_4: return DvbTTransponder::Hierarchy4; 0872 default: return DvbTTransponder::HierarchyAuto; 0873 } 0874 } 0875 0876 static DvbT2Transponder::Hierarchy DvbT2toHierarchy(uint32_t hierarchy) 0877 { 0878 switch (hierarchy) { 0879 case HIERARCHY_NONE: return DvbT2Transponder::HierarchyNone; 0880 case HIERARCHY_1: return DvbT2Transponder::Hierarchy1; 0881 case HIERARCHY_2: return DvbT2Transponder::Hierarchy2; 0882 case HIERARCHY_4: return DvbT2Transponder::Hierarchy4; 0883 default: return DvbT2Transponder::HierarchyAuto; 0884 } 0885 } 0886 0887 bool DvbLinuxDevice::satSetup(QString lnbModel, int satNumber, int bpf) 0888 { 0889 Q_ASSERT(dvbv5_parms); 0890 0891 int lnb = dvb_sat_search_lnb(lnbModel.toUtf8()); 0892 dvbv5_parms->lnb = dvb_sat_get_lnb(lnb); 0893 if (!dvbv5_parms->lnb) { 0894 qCCritical(logDev, "Cannot set LNBf type to %s", qPrintable(lnbModel)); 0895 return false; 0896 } 0897 0898 qCDebug(logDev, "Using LNBf type %s", qPrintable(lnbModel)); 0899 0900 dvbv5_parms->sat_number = satNumber; 0901 dvbv5_parms->freq_bpf = bpf; 0902 0903 return true; 0904 } 0905 0906 bool DvbLinuxDevice::tune(const DvbTransponder &transponder) 0907 { 0908 Q_ASSERT(dvbv5_parms); 0909 stopDvr(); 0910 fe_delivery_system_t delsys; 0911 0912 qCDebug(logDev, "tune to: %s", qPrintable(transponder.toString())); 0913 0914 // FIXME: add support for LNA on/off 0915 0916 switch (transponder.getTransmissionType()) { 0917 case DvbTransponderBase::DvbS: { 0918 const DvbSTransponder *dvbSTransponder = transponder.as<DvbSTransponder>(); 0919 0920 delsys = SYS_DVBS; 0921 dvb_set_sys(dvbv5_parms, delsys); 0922 0923 dvb_fe_store_parm(dvbv5_parms, DTV_POLARIZATION, toDvbPolarization(dvbSTransponder->polarization)); 0924 dvb_fe_store_parm(dvbv5_parms, DTV_FREQUENCY, dvbSTransponder->frequency); 0925 dvb_fe_store_parm(dvbv5_parms, DTV_INVERSION, INVERSION_AUTO); 0926 dvb_fe_store_parm(dvbv5_parms, DTV_SYMBOL_RATE, dvbSTransponder->symbolRate); 0927 dvb_fe_store_parm(dvbv5_parms, DTV_INNER_FEC, toDvbFecRate(dvbSTransponder->fecRate)); 0928 freqMHz = dvbSTransponder->frequency / 1000.; 0929 0930 /// FIXME 0931 0932 break; 0933 } 0934 case DvbTransponderBase::DvbS2: { 0935 const DvbS2Transponder *dvbS2Transponder = transponder.as<DvbS2Transponder>(); 0936 0937 delsys = SYS_DVBS2; 0938 dvb_set_sys(dvbv5_parms, delsys); 0939 0940 dvb_fe_store_parm(dvbv5_parms, DTV_POLARIZATION, toDvbPolarization(dvbS2Transponder->polarization)); 0941 dvb_fe_store_parm(dvbv5_parms, DTV_FREQUENCY, dvbS2Transponder->frequency); 0942 dvb_fe_store_parm(dvbv5_parms, DTV_INVERSION, INVERSION_AUTO); 0943 dvb_fe_store_parm(dvbv5_parms, DTV_SYMBOL_RATE, dvbS2Transponder->symbolRate); 0944 dvb_fe_store_parm(dvbv5_parms, DTV_INNER_FEC, toDvbFecRate(dvbS2Transponder->fecRate)); 0945 dvb_fe_store_parm(dvbv5_parms, DTV_MODULATION, toDvbModulation(dvbS2Transponder->modulation)); 0946 dvb_fe_store_parm(dvbv5_parms, DTV_PILOT, PILOT_AUTO); 0947 dvb_fe_store_parm(dvbv5_parms, DTV_ROLLOFF, toDvbRollOff(dvbS2Transponder->rollOff)); 0948 freqMHz = dvbS2Transponder->frequency / 1000.; 0949 break; 0950 } 0951 case DvbTransponderBase::DvbC: { 0952 const DvbCTransponder *dvbCTransponder = transponder.as<DvbCTransponder>(); 0953 0954 delsys = SYS_DVBC_ANNEX_A; 0955 dvb_set_sys(dvbv5_parms, delsys); 0956 0957 dvb_fe_store_parm(dvbv5_parms, DTV_FREQUENCY, dvbCTransponder->frequency); 0958 dvb_fe_store_parm(dvbv5_parms, DTV_MODULATION, toDvbModulation(dvbCTransponder->modulation)); 0959 dvb_fe_store_parm(dvbv5_parms, DTV_INVERSION, INVERSION_AUTO); 0960 dvb_fe_store_parm(dvbv5_parms, DTV_SYMBOL_RATE, dvbCTransponder->symbolRate); 0961 dvb_fe_store_parm(dvbv5_parms, DTV_INNER_FEC, toDvbFecRate(dvbCTransponder->fecRate)); 0962 freqMHz = dvbCTransponder->frequency / 1000000.; 0963 0964 break; 0965 } 0966 case DvbTransponderBase::DvbT: { 0967 const DvbTTransponder *dvbTTransponder = transponder.as<DvbTTransponder>(); 0968 0969 delsys = SYS_DVBT; 0970 dvb_set_sys(dvbv5_parms, delsys); 0971 0972 dvb_fe_store_parm(dvbv5_parms, DTV_FREQUENCY, dvbTTransponder->frequency); 0973 dvb_fe_store_parm(dvbv5_parms, DTV_MODULATION, toDvbModulation(dvbTTransponder->modulation)); 0974 dvb_fe_store_parm(dvbv5_parms, DTV_BANDWIDTH_HZ, toDvbBandwidth(dvbTTransponder->bandwidth)); 0975 dvb_fe_store_parm(dvbv5_parms, DTV_INVERSION, INVERSION_AUTO); 0976 dvb_fe_store_parm(dvbv5_parms, DTV_CODE_RATE_HP, toDvbFecRate(dvbTTransponder->fecRateHigh)); 0977 dvb_fe_store_parm(dvbv5_parms, DTV_CODE_RATE_LP, toDvbFecRate(dvbTTransponder->fecRateLow)); 0978 dvb_fe_store_parm(dvbv5_parms, DTV_GUARD_INTERVAL, toDvbGuardInterval(dvbTTransponder->guardInterval)); 0979 dvb_fe_store_parm(dvbv5_parms, DTV_TRANSMISSION_MODE, toDvbTransmissionMode(dvbTTransponder->transmissionMode)); 0980 dvb_fe_store_parm(dvbv5_parms, DTV_HIERARCHY, toDvbHierarchy(dvbTTransponder->hierarchy)); 0981 freqMHz = dvbTTransponder->frequency / 1000000.; 0982 break; 0983 } 0984 case DvbTransponderBase::DvbT2: { 0985 const DvbT2Transponder *dvbT2Transponder = transponder.as<DvbT2Transponder>(); 0986 0987 delsys = SYS_DVBT2; 0988 dvb_set_sys(dvbv5_parms, delsys); 0989 0990 dvb_fe_store_parm(dvbv5_parms, DTV_FREQUENCY, dvbT2Transponder->frequency); 0991 dvb_fe_store_parm(dvbv5_parms, DTV_MODULATION, toDvbModulation(dvbT2Transponder->modulation)); 0992 dvb_fe_store_parm(dvbv5_parms, DTV_BANDWIDTH_HZ, toDvbBandwidth(dvbT2Transponder->bandwidth)); 0993 dvb_fe_store_parm(dvbv5_parms, DTV_INVERSION, INVERSION_AUTO); 0994 dvb_fe_store_parm(dvbv5_parms, DTV_CODE_RATE_HP, toDvbFecRate(dvbT2Transponder->fecRateHigh)); 0995 dvb_fe_store_parm(dvbv5_parms, DTV_CODE_RATE_LP, toDvbFecRate(dvbT2Transponder->fecRateLow)); 0996 dvb_fe_store_parm(dvbv5_parms, DTV_GUARD_INTERVAL, toDvbGuardInterval(dvbT2Transponder->guardInterval)); 0997 dvb_fe_store_parm(dvbv5_parms, DTV_TRANSMISSION_MODE, toDvbTransmissionMode(dvbT2Transponder->transmissionMode)); 0998 dvb_fe_store_parm(dvbv5_parms, DTV_HIERARCHY, toDvbHierarchy(dvbT2Transponder->hierarchy)); 0999 dvb_fe_store_parm(dvbv5_parms, DTV_STREAM_ID, dvbT2Transponder->streamId); 1000 freqMHz = dvbT2Transponder->frequency / 1000000.; 1001 break; 1002 } 1003 case DvbTransponderBase::Atsc: { 1004 const AtscTransponder *atscTransponder = transponder.as<AtscTransponder>(); 1005 1006 switch (atscTransponder->modulation) { 1007 case AtscTransponder::Vsb8: 1008 case AtscTransponder::Vsb16: 1009 delsys = SYS_ATSC; 1010 break; 1011 default: 1012 delsys = SYS_DVBC_ANNEX_B; 1013 } 1014 dvb_set_sys(dvbv5_parms, delsys); 1015 1016 dvb_fe_store_parm(dvbv5_parms, DTV_FREQUENCY, atscTransponder->frequency); 1017 dvb_fe_store_parm(dvbv5_parms, DTV_MODULATION, toDvbModulation(atscTransponder->modulation)); 1018 /* dvb_fe_store_parm(dvbv5_parms, DTV_INVERSION, INVERSION_AUTO); */ 1019 freqMHz = atscTransponder->frequency / 1000000.; 1020 break; 1021 } 1022 case DvbTransponderBase::IsdbT: { 1023 const IsdbTTransponder *isdbTTransponder = transponder.as<IsdbTTransponder>(); 1024 int i; 1025 uint32_t layers = 0; 1026 1027 delsys = SYS_ISDBT; 1028 dvb_set_sys(dvbv5_parms, delsys); 1029 1030 dvb_fe_store_parm(dvbv5_parms, DTV_FREQUENCY, isdbTTransponder->frequency); 1031 dvb_fe_store_parm(dvbv5_parms, DTV_BANDWIDTH_HZ, toDvbBandwidth(isdbTTransponder->bandwidth)); 1032 dvb_fe_store_parm(dvbv5_parms, DTV_INVERSION, INVERSION_AUTO); 1033 dvb_fe_store_parm(dvbv5_parms, DTV_GUARD_INTERVAL, toDvbGuardInterval(isdbTTransponder->guardInterval)); 1034 dvb_fe_store_parm(dvbv5_parms, DTV_TRANSMISSION_MODE, toDvbTransmissionMode(isdbTTransponder->transmissionMode)); 1035 1036 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_PARTIAL_RECEPTION, toDvbPartialReception(isdbTTransponder->partialReception)); 1037 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_SOUND_BROADCASTING, toDvbSoundBroadcasting(isdbTTransponder->soundBroadcasting)); 1038 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_SB_SUBCHANNEL_ID, isdbTTransponder->subChannelId); 1039 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_SB_SEGMENT_IDX, isdbTTransponder->sbSegmentIdx); 1040 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_SB_SEGMENT_COUNT, isdbTTransponder->sbSegmentCount); 1041 1042 for (i = 0; i < 3; ++i) { 1043 if (isdbTTransponder->layerEnabled[i]) 1044 layers |= 1 << i; 1045 } 1046 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYER_ENABLED, layers); 1047 1048 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERA_FEC, toDvbFecRate(isdbTTransponder->fecRate[0])); 1049 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERA_MODULATION, toDvbModulation(isdbTTransponder->modulation[0])); 1050 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERA_SEGMENT_COUNT, isdbTTransponder->segmentCount[0]); 1051 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERA_TIME_INTERLEAVING, toDvbInterleaving(isdbTTransponder->interleaving[0])); 1052 1053 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERB_FEC, toDvbFecRate(isdbTTransponder->fecRate[1])); 1054 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERB_MODULATION, toDvbModulation(isdbTTransponder->modulation[1])); 1055 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERB_SEGMENT_COUNT, isdbTTransponder->segmentCount[1]); 1056 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERA_TIME_INTERLEAVING, toDvbInterleaving(isdbTTransponder->interleaving[1])); 1057 1058 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERC_FEC, toDvbFecRate(isdbTTransponder->fecRate[2])); 1059 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERC_MODULATION, toDvbModulation(isdbTTransponder->modulation[2])); 1060 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERC_SEGMENT_COUNT, isdbTTransponder->segmentCount[2]); 1061 dvb_fe_store_parm(dvbv5_parms, DTV_ISDBT_LAYERA_TIME_INTERLEAVING, toDvbInterleaving(isdbTTransponder->interleaving[2])); 1062 1063 freqMHz = isdbTTransponder->frequency / 1000000.; 1064 1065 break; 1066 } 1067 case DvbTransponderBase::Invalid: 1068 qCWarning(logDev, "Invalid transmission type when tuning to %s", 1069 qPrintable(transponder.toString())); 1070 return false; 1071 default: 1072 qCWarning(logDev, "Unknown transmission type %d when tuning to %s", 1073 transponder.getTransmissionType(), 1074 qPrintable(transponder.toString())); 1075 return false; 1076 } 1077 1078 if (dvb_fe_set_parms(dvbv5_parms) != 0) { 1079 qCWarning(logDev, "ioctl FE_SET_PROPERTY failed for frontend %s", qPrintable(frontendPath)); 1080 return false; 1081 } 1082 1083 startDvr(); 1084 return true; 1085 } 1086 1087 bool DvbLinuxDevice::getProps(DvbTransponder &transponder) 1088 { 1089 Q_ASSERT(dvbv5_parms); 1090 uint32_t value; 1091 1092 /* Update properties with the detected stuff */ 1093 if (!isTuned()) 1094 return false; 1095 1096 dvb_fe_get_parms(dvbv5_parms); 1097 1098 switch (transponder.getTransmissionType()) { 1099 case DvbTransponderBase::DvbS: { 1100 DvbSTransponder *dvbSTransponder = transponder.as<DvbSTransponder>(); 1101 1102 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1103 dvbSTransponder->frequency = (int)value; 1104 dvb_fe_retrieve_parm(dvbv5_parms, DTV_SYMBOL_RATE, &value); 1105 dvbSTransponder->symbolRate = (int)value; 1106 dvb_fe_retrieve_parm(dvbv5_parms, DTV_INNER_FEC, &value); 1107 dvbSTransponder->fecRate = DvbtoFecRate(value); 1108 break; 1109 } 1110 case DvbTransponderBase::DvbS2: { 1111 DvbS2Transponder *dvbS2Transponder = transponder.as<DvbS2Transponder>(); 1112 1113 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1114 dvbS2Transponder->frequency = (int)value; 1115 dvb_fe_retrieve_parm(dvbv5_parms, DTV_SYMBOL_RATE, &value); 1116 dvbS2Transponder->symbolRate = (int)value; 1117 dvb_fe_retrieve_parm(dvbv5_parms, DTV_INNER_FEC, &value); 1118 dvbS2Transponder->fecRate = DvbtoFecRate(value); 1119 dvb_fe_retrieve_parm(dvbv5_parms, DTV_MODULATION, &value); 1120 dvbS2Transponder->modulation = DvbS2toModulation(value); 1121 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ROLLOFF, &value); 1122 dvbS2Transponder->rollOff = DvbS2toRollOff(value); 1123 break; 1124 } 1125 case DvbTransponderBase::DvbC: { 1126 DvbCTransponder *dvbCTransponder = transponder.as<DvbCTransponder>(); 1127 1128 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1129 dvbCTransponder->frequency = (int)value; 1130 dvb_fe_retrieve_parm(dvbv5_parms, DTV_MODULATION, &value); 1131 dvbCTransponder->modulation = DvbCtoModulation(value); 1132 dvb_fe_retrieve_parm(dvbv5_parms, DTV_SYMBOL_RATE, &value); 1133 dvbCTransponder->symbolRate = (int)value; 1134 dvb_fe_retrieve_parm(dvbv5_parms, DTV_INNER_FEC, &value); 1135 dvbCTransponder->fecRate = DvbtoFecRate(value); 1136 1137 break; 1138 } 1139 case DvbTransponderBase::DvbT: { 1140 DvbTTransponder *dvbTTransponder = transponder.as<DvbTTransponder>(); 1141 1142 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1143 dvbTTransponder->frequency = (int)value; 1144 dvb_fe_retrieve_parm(dvbv5_parms, DTV_MODULATION, &value); 1145 dvbTTransponder->modulation = DvbTtoModulation(value); 1146 dvb_fe_retrieve_parm(dvbv5_parms, DTV_BANDWIDTH_HZ, &value); 1147 dvbTTransponder->bandwidth = DvbTtoBandwidth(value); 1148 dvb_fe_retrieve_parm(dvbv5_parms, DTV_CODE_RATE_HP, &value); 1149 dvbTTransponder->fecRateHigh = DvbtoFecRate(value); 1150 dvb_fe_retrieve_parm(dvbv5_parms, DTV_CODE_RATE_LP, &value); 1151 dvbTTransponder->fecRateLow = DvbtoFecRate(value); 1152 dvb_fe_retrieve_parm(dvbv5_parms, DTV_GUARD_INTERVAL, &value); 1153 dvbTTransponder->guardInterval = DvbTtoGuardInterval(value); 1154 dvb_fe_retrieve_parm(dvbv5_parms, DTV_TRANSMISSION_MODE, &value); 1155 dvbTTransponder->transmissionMode = DvbTtoTransmissionMode(value); 1156 dvb_fe_retrieve_parm(dvbv5_parms, DTV_HIERARCHY, &value); 1157 dvbTTransponder->hierarchy = DvbTtoHierarchy(value); 1158 break; 1159 } 1160 case DvbTransponderBase::DvbT2: { 1161 DvbT2Transponder *dvbT2Transponder = transponder.as<DvbT2Transponder>(); 1162 1163 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1164 dvbT2Transponder->frequency = (int)value; 1165 dvb_fe_retrieve_parm(dvbv5_parms, DTV_MODULATION, &value); 1166 dvbT2Transponder->modulation = DvbT2toModulation(value); 1167 dvb_fe_retrieve_parm(dvbv5_parms, DTV_BANDWIDTH_HZ, &value); 1168 dvbT2Transponder->bandwidth = DvbT2toBandwidth(value); 1169 dvb_fe_retrieve_parm(dvbv5_parms, DTV_CODE_RATE_HP, &value); 1170 dvbT2Transponder->fecRateHigh = DvbtoFecRate(value); 1171 dvb_fe_retrieve_parm(dvbv5_parms, DTV_CODE_RATE_LP, &value); 1172 dvbT2Transponder->fecRateLow = DvbtoFecRate(value); 1173 dvb_fe_retrieve_parm(dvbv5_parms, DTV_GUARD_INTERVAL, &value); 1174 dvbT2Transponder->guardInterval = DvbT2toGuardInterval(value); 1175 dvb_fe_retrieve_parm(dvbv5_parms, DTV_TRANSMISSION_MODE, &value); 1176 dvbT2Transponder->transmissionMode = DvbT2toTransmissionMode(value); 1177 dvb_fe_retrieve_parm(dvbv5_parms, DTV_HIERARCHY, &value); 1178 dvbT2Transponder->hierarchy = DvbT2toHierarchy(value); 1179 dvb_fe_retrieve_parm(dvbv5_parms, DTV_STREAM_ID, &value); 1180 dvbT2Transponder->streamId = (int)value; 1181 break; 1182 } 1183 case DvbTransponderBase::Atsc: { 1184 AtscTransponder *atscTransponder = transponder.as<AtscTransponder>(); 1185 1186 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1187 atscTransponder->frequency = (int)value; 1188 dvb_fe_retrieve_parm(dvbv5_parms, DTV_MODULATION, &value); 1189 atscTransponder->modulation = AtsctoModulation(value); 1190 break; 1191 } 1192 case DvbTransponderBase::IsdbT: { 1193 IsdbTTransponder *isdbTTransponder = transponder.as<IsdbTTransponder>(); 1194 int i; 1195 uint32_t layers = 0; 1196 1197 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1198 isdbTTransponder->frequency = (int)value; 1199 dvb_fe_retrieve_parm(dvbv5_parms, DTV_BANDWIDTH_HZ, &value); 1200 isdbTTransponder->bandwidth = IsdbTtoBandwidth(value); 1201 dvb_fe_retrieve_parm(dvbv5_parms, DTV_GUARD_INTERVAL, &value); 1202 isdbTTransponder->guardInterval = IsdbTtoGuardInterval(value); 1203 dvb_fe_retrieve_parm(dvbv5_parms, DTV_TRANSMISSION_MODE, &value); 1204 isdbTTransponder->transmissionMode = IsdbTtoTransmissionMode(value); 1205 1206 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_PARTIAL_RECEPTION, &value); 1207 isdbTTransponder->partialReception = IsdbTtoPartialReception(value); 1208 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_SOUND_BROADCASTING, &value); 1209 isdbTTransponder->soundBroadcasting = IsdbTtoSoundBroadcasting(value); 1210 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_SB_SUBCHANNEL_ID, &value); 1211 isdbTTransponder->subChannelId = (int)value; 1212 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_SB_SEGMENT_IDX, &value); 1213 isdbTTransponder->sbSegmentIdx = (int)value; 1214 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_SB_SEGMENT_COUNT, &value); 1215 isdbTTransponder->sbSegmentCount = (int)value; 1216 1217 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYER_ENABLED, &value); 1218 layers = (int)value; 1219 for (i = 0; i < 3; ++i) { 1220 if (isdbTTransponder->layerEnabled[i]) 1221 layers |= 1 << i; 1222 } 1223 1224 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERA_FEC, &value); 1225 isdbTTransponder->fecRate[0] = DvbtoFecRate(value); 1226 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERA_MODULATION, &value); 1227 isdbTTransponder->modulation[0] = IsdbTtoModulation(value); 1228 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERA_SEGMENT_COUNT, &value); 1229 isdbTTransponder->segmentCount[0] = (int)value; 1230 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERA_TIME_INTERLEAVING, &value); 1231 isdbTTransponder->interleaving[0] = IsdbTtoInterleaving(value); 1232 1233 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERB_FEC, &value); 1234 isdbTTransponder->fecRate[1] = DvbtoFecRate(value); 1235 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERB_MODULATION, &value); 1236 isdbTTransponder->modulation[1] = IsdbTtoModulation(value); 1237 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERB_SEGMENT_COUNT, &value); 1238 isdbTTransponder->segmentCount[1] = (int)value; 1239 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERB_TIME_INTERLEAVING, &value); 1240 isdbTTransponder->interleaving[1] = IsdbTtoInterleaving(value); 1241 1242 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERC_FEC, &value); 1243 isdbTTransponder->fecRate[2] = DvbtoFecRate(value); 1244 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERC_MODULATION, &value); 1245 isdbTTransponder->modulation[2] = IsdbTtoModulation(value); 1246 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERC_SEGMENT_COUNT, &value); 1247 isdbTTransponder->segmentCount[2] = (int)value; 1248 dvb_fe_retrieve_parm(dvbv5_parms, DTV_ISDBT_LAYERC_TIME_INTERLEAVING, &value); 1249 isdbTTransponder->interleaving[2] = IsdbTtoInterleaving(value); 1250 1251 break; 1252 } 1253 case DvbTransponderBase::Invalid: 1254 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1255 qCWarning(logDev, "Invalid transmission type when get props from %.2f MHz", 1256 value / 1000000.); 1257 return false; 1258 default: 1259 dvb_fe_retrieve_parm(dvbv5_parms, DTV_FREQUENCY, &value); 1260 qCWarning(logDev, "Unknown transmission type %d when get props from %.2f MHz", 1261 transponder.getTransmissionType(), 1262 value / 1000000.); 1263 return false; 1264 } 1265 return true; 1266 } 1267 1268 float DvbLinuxDevice::getFrqMHz() 1269 { 1270 return freqMHz; 1271 } 1272 1273 void DvbLinuxDevice::enableDvbDump() 1274 { 1275 verbose = 1; 1276 1277 if (dvbv5_parms) 1278 dvbv5_parms->verbose = 1; 1279 } 1280 1281 bool DvbLinuxDevice::isTuned() 1282 { 1283 Q_ASSERT(dvbv5_parms); 1284 uint32_t status = 0; 1285 1286 if (dvb_fe_get_stats(dvbv5_parms) != 0) { 1287 qCWarning(logDev, "ioctl FE_READ_STATUS failed for frontend %s", qPrintable(frontendPath)); 1288 return false; 1289 } 1290 1291 if (dvb_fe_retrieve_stats(dvbv5_parms, DTV_STATUS, &status) != 0) { 1292 qCWarning(logDev, "ioctl FE_READ_STATUS failed for frontend %s", qPrintable(frontendPath)); 1293 return false; 1294 } 1295 1296 return ((status & FE_HAS_LOCK) != 0); 1297 } 1298 1299 float DvbLinuxDevice::getSignal(Scale &scale) 1300 { 1301 Q_ASSERT(dvbv5_parms); 1302 struct dtv_stats *stat; 1303 float signal; 1304 1305 scale = DvbBackendDevice::NotSupported; 1306 1307 if (dvb_fe_get_stats(dvbv5_parms) != 0) { 1308 qCWarning(logDev, "ioctl FE_READ_STATUS failed for frontend %s", qPrintable(frontendPath)); 1309 return false; 1310 } 1311 1312 stat = dvb_fe_retrieve_stats_layer(dvbv5_parms, DTV_STAT_SIGNAL_STRENGTH, 0); 1313 if (!stat) 1314 return -1; 1315 1316 switch (stat->scale) { 1317 case FE_SCALE_RELATIVE: 1318 signal = (100. * stat->uvalue) / 65535; 1319 1320 scale = DvbBackendDevice::Percentage; 1321 1322 // Assert that signal will be within the expected range 1323 if (signal > 100.) 1324 signal = 100.; 1325 else if (signal < 0) 1326 signal = 0; 1327 1328 break; 1329 case FE_SCALE_DECIBEL: 1330 // Convert to dBuV @ 75 ohms, to be positive and typically smaller than 100 1331 signal = (108800. + stat->svalue) / 1000; 1332 1333 scale = DvbBackendDevice::dBuV; 1334 1335 break; 1336 default: 1337 return -1; 1338 } 1339 1340 return signal; 1341 } 1342 1343 float DvbLinuxDevice::getSnr(Scale &scale) 1344 { 1345 Q_ASSERT(dvbv5_parms); 1346 struct dtv_stats *stat; 1347 float cnr; 1348 1349 scale = DvbBackendDevice::NotSupported; 1350 if (dvb_fe_get_stats(dvbv5_parms) != 0) { 1351 qCWarning(logDev, "ioctl FE_READ_STATUS failed for frontend %s", qPrintable(frontendPath)); 1352 return false; 1353 } 1354 1355 stat = dvb_fe_retrieve_stats_layer(dvbv5_parms, DTV_STAT_CNR, 0); 1356 if (!stat) 1357 return -1; 1358 1359 switch (stat->scale) { 1360 case FE_SCALE_RELATIVE: 1361 cnr = (100. * stat->uvalue) / 65535; 1362 1363 // Assert that CNR will be within the expected range 1364 if (cnr > 100.) 1365 cnr = 100.; 1366 else if (cnr < 0.) 1367 cnr = 0.; 1368 1369 scale = DvbBackendDevice::Percentage; 1370 1371 break; 1372 case FE_SCALE_DECIBEL: 1373 cnr = (stat->svalue / 1000.); 1374 1375 scale = DvbBackendDevice::Decibel; 1376 1377 break; 1378 default: 1379 return -1; 1380 } 1381 1382 return cnr; 1383 } 1384 1385 bool DvbLinuxDevice::addPidFilter(int pid) 1386 { 1387 if (dmxFds.contains(pid)) { 1388 qCWarning(logDev, "PID filter already set up for pid %d", pid); 1389 return false; 1390 } 1391 1392 int dmxFd = open(QFile::encodeName(demuxPath).constData(), O_RDONLY | O_NONBLOCK | O_CLOEXEC); 1393 1394 if (dmxFd < 0) { 1395 qCWarning(logDev, "Cannot open demux %s", qPrintable(demuxPath)); 1396 return false; 1397 } 1398 1399 dmx_pes_filter_params pes_filter; 1400 memset(&pes_filter, 0, sizeof(pes_filter)); 1401 pes_filter.pid = ushort(pid); 1402 pes_filter.input = DMX_IN_FRONTEND; 1403 pes_filter.output = DMX_OUT_TS_TAP; 1404 pes_filter.pes_type = DMX_PES_OTHER; 1405 pes_filter.flags = DMX_IMMEDIATE_START; 1406 1407 if (ioctl(dmxFd, DMX_SET_PES_FILTER, &pes_filter) != 0) { 1408 qCWarning(logDev, "Cannot set up PID filter for demux %s", qPrintable(demuxPath)); 1409 close(dmxFd); 1410 return false; 1411 } 1412 1413 dmxFds.insert(pid, dmxFd); 1414 return true; 1415 } 1416 1417 void DvbLinuxDevice::removePidFilter(int pid) 1418 { 1419 if (!dmxFds.contains(pid)) { 1420 qCWarning(logDev, "No PID filter set up for PID %i", pid); 1421 return; 1422 } 1423 1424 close(dmxFds.take(pid)); 1425 } 1426 1427 void DvbLinuxDevice::startDescrambling(const QByteArray &pmtSectionData) 1428 { 1429 cam.startDescrambling(pmtSectionData); 1430 } 1431 1432 void DvbLinuxDevice::stopDescrambling(int serviceId) 1433 { 1434 cam.stopDescrambling(serviceId); 1435 } 1436 1437 void DvbLinuxDevice::release() 1438 { 1439 stopDvr(); 1440 1441 if (dvrBuffer.data != NULL) { 1442 dvrBuffer.dataSize = 0; 1443 frontend->writeBuffer(dvrBuffer); 1444 dvrBuffer.data = NULL; 1445 } 1446 1447 if (dvrPipe[0] >= 0) { 1448 close(dvrPipe[0]); 1449 dvrPipe[0] = -1; 1450 } 1451 1452 if (dvrPipe[1] >= 0) { 1453 close(dvrPipe[1]); 1454 dvrPipe[1] = -1; 1455 } 1456 1457 if (dvrFd >= 0) { 1458 close(dvrFd); 1459 dvrFd = -1; 1460 } 1461 1462 foreach (int dmxFd, dmxFds) { 1463 close(dmxFd); 1464 } 1465 1466 dmxFds.clear(); 1467 1468 if (dvbv5_parms) { 1469 dvb_fe_close(dvbv5_parms); 1470 dvbv5_parms = NULL; 1471 } 1472 } 1473 1474 void DvbLinuxDevice::startDvr() 1475 { 1476 Q_ASSERT((dvrFd >= 0) && !isRunning()); 1477 1478 if ((dvrPipe[0] < 0) || (dvrPipe[1] < 0)) { 1479 if (pipe(dvrPipe) != 0) { 1480 dvrPipe[0] = -1; 1481 dvrPipe[1] = -1; 1482 } 1483 1484 if ((dvrPipe[0] < 0) || (dvrPipe[1] < 0)) { 1485 qCCritical(logDev, "Cannot create pipe"); 1486 return; 1487 } 1488 } 1489 1490 if (dvrBuffer.data == NULL) { 1491 dvrBuffer = frontend->getBuffer(); 1492 } 1493 1494 while (true) { 1495 int bufferSize = dvrBuffer.bufferSize; 1496 int dataSize = int(read(dvrFd, dvrBuffer.data, bufferSize)); 1497 1498 if (dataSize < 0) { 1499 if (IS_EAGAIN(errno)) { 1500 break; 1501 } 1502 1503 if (errno == EINTR) { 1504 continue; 1505 } 1506 1507 dataSize = int(read(dvrFd, dvrBuffer.data, bufferSize)); 1508 1509 if (dataSize < 0) { 1510 if (IS_EAGAIN(errno)) { 1511 break; 1512 } 1513 1514 if (errno == EINTR) { 1515 continue; 1516 } 1517 1518 qCWarning(logDev, "Cannot read from dvr %s: error: %d", qPrintable(dvrPath), errno); 1519 return; 1520 } 1521 } 1522 1523 if (dataSize != bufferSize) { 1524 break; 1525 } 1526 } 1527 1528 start(); 1529 } 1530 1531 void DvbLinuxDevice::stopDvr() 1532 { 1533 if (isRunning()) { 1534 Q_ASSERT((dvrPipe[0] >= 0) && (dvrPipe[1] >= 0)); 1535 1536 if (write(dvrPipe[1], " ", 1) != 1) { 1537 qCWarning(logDev, "Cannot write to pipe"); 1538 } 1539 1540 wait(); 1541 char data; 1542 1543 if (read(dvrPipe[0], &data, 1) != 1) { 1544 qCWarning(logDev, "Cannot read from pipe"); 1545 } 1546 } 1547 } 1548 1549 void DvbLinuxDevice::run() 1550 { 1551 Q_ASSERT((dvrFd >= 0) && (dvrPipe[0] >= 0) && (dvrBuffer.data != NULL)); 1552 pollfd pollFds[2]; 1553 memset(&pollFds, 0, sizeof(pollFds)); 1554 pollFds[0].fd = dvrPipe[0]; 1555 pollFds[0].events = POLLIN; 1556 pollFds[1].fd = dvrFd; 1557 pollFds[1].events = POLLIN; 1558 1559 while (true) { 1560 if (poll(pollFds, 2, -1) < 0) { 1561 if (errno == EINTR) { 1562 continue; 1563 } 1564 1565 qCWarning(logDev, "Poll failed with error: %d", errno); 1566 return; 1567 } 1568 1569 if ((pollFds[0].revents & POLLIN) != 0) { 1570 return; 1571 } 1572 1573 while (true) { 1574 int bufferSize = dvrBuffer.bufferSize; 1575 int dataSize = int(read(dvrFd, dvrBuffer.data, bufferSize)); 1576 1577 if (dataSize < 0) { 1578 if (IS_EAGAIN(errno)) { 1579 break; 1580 } 1581 1582 if (errno == EINTR) { 1583 continue; 1584 } 1585 1586 qCWarning(logDev, "Cannot read from dvr %s: error %d", qPrintable(dvrPath), errno); 1587 dataSize = int(read(dvrFd, dvrBuffer.data, bufferSize)); 1588 1589 if (dataSize < 0) { 1590 if (IS_EAGAIN(errno)) { 1591 break; 1592 } 1593 1594 if (errno == EINTR) { 1595 continue; 1596 } 1597 1598 qCWarning(logDev, "Cannot read from dvr %s: error %d", qPrintable(dvrPath), errno); 1599 return; 1600 } 1601 } 1602 1603 if (dataSize > 0) { 1604 dvrBuffer.dataSize = dataSize; 1605 frontend->writeBuffer(dvrBuffer); 1606 dvrBuffer = frontend->getBuffer(); 1607 } 1608 1609 if (dataSize != bufferSize) { 1610 break; 1611 } 1612 } 1613 1614 msleep(10); 1615 } 1616 } 1617 1618 DvbLinuxDeviceManager::DvbLinuxDeviceManager(QObject *parent) : QObject(parent) 1619 { 1620 QObject *notifier = Solid::DeviceNotifier::instance(); 1621 connect(notifier, SIGNAL(deviceAdded(QString)), this, SLOT(componentAdded(QString))); 1622 connect(notifier, SIGNAL(deviceRemoved(QString)), this, SLOT(componentRemoved(QString))); 1623 } 1624 1625 DvbLinuxDeviceManager::~DvbLinuxDeviceManager() 1626 { 1627 } 1628 1629 void DvbLinuxDeviceManager::doColdPlug() 1630 { 1631 foreach (const Solid::Device &device, Solid::Device::allDevices()) { 1632 componentAdded(device.udi()); 1633 } 1634 } 1635 1636 void DvbLinuxDeviceManager::componentAdded(const QString &udi) 1637 { 1638 QRegularExpressionMatch match; 1639 bool ok; 1640 1641 QRegularExpression rejex = QRegularExpression("/dvb/dvb(\\d+).(\\w+)(\\d+)"); 1642 if (!udi.contains(rejex, &match)) 1643 return; 1644 1645 int adapter = match.captured(1).toShort(&ok, 10); 1646 if (!ok) 1647 return; 1648 QString type = match.captured(2); 1649 int index = match.captured(3).toShort(&ok, 10); 1650 if (!ok) 1651 return; 1652 1653 QString devicePath = QString(QLatin1String("/dev/dvb/adapter%1/%2%3")).arg(adapter).arg(type).arg(index); 1654 1655 if ((adapter < 0) || (adapter > 0x7fff) || (index < 0) || (index > 0x7fff)) { 1656 qCWarning(logDev, "Cannot determine adapter or index for device %s", qPrintable(udi)); 1657 return; 1658 } 1659 1660 if (devicePath.isEmpty()) { 1661 qCWarning(logDev, "Cannot determine path for device %s", qPrintable(udi)); 1662 return; 1663 } 1664 1665 qCDebug(logDev, "New device detected: %s", qPrintable(udi)); 1666 1667 int deviceIndex = ((adapter << 16) | index); 1668 DvbLinuxDevice *device = devices.value(deviceIndex); 1669 1670 if (device == NULL) { 1671 device = new DvbLinuxDevice(this); 1672 devices.insert(deviceIndex, device); 1673 } 1674 1675 bool addDevice = false; 1676 1677 if (!type.compare("ca")) { 1678 if (device->caPath.isEmpty()) { 1679 device->caPath = devicePath; 1680 device->caUdi = udi; 1681 udis.insert(udi, device); 1682 1683 if (device->isReady()) 1684 device->startCa(); 1685 } 1686 } else if (!type.compare("demux")) { 1687 device->numDemux++; 1688 if (device->demuxPath.isEmpty()) { 1689 device->demuxPath = devicePath; 1690 device->demuxUdi = udi; 1691 udis.insert(udi, device); 1692 addDevice = true; 1693 } 1694 } else if (!type.compare("dvr")) { 1695 if (device->dvrPath.isEmpty()) { 1696 device->dvrPath = devicePath; 1697 device->dvrUdi = udi; 1698 udis.insert(udi, device); 1699 addDevice = true; 1700 } 1701 } else if (!type.compare("frontend")) { 1702 if (device->frontendPath.isEmpty()) { 1703 device->frontendPath = devicePath; 1704 device->frontendUdi = udi; 1705 udis.insert(udi, device); 1706 addDevice = true; 1707 } 1708 } 1709 1710 // Special case: one demux, multiple frontends 1711 if (index && device->numDemux < 2) { 1712 int parentDeviceIndex = (adapter << 16); 1713 DvbLinuxDevice *parentDevice = devices.value(parentDeviceIndex); 1714 1715 if (device->demuxPath.isEmpty() && !parentDevice->demuxPath.isEmpty()) 1716 device->demuxPath = parentDevice->demuxPath; 1717 if (device->dvrPath.isEmpty() && !parentDevice->dvrPath.isEmpty()) 1718 device->dvrPath = parentDevice->dvrPath; 1719 if (device->caPath.isEmpty() && !parentDevice->caPath.isEmpty()) 1720 device->caPath = parentDevice->caPath; 1721 } 1722 1723 if (addDevice && !device->demuxPath.isEmpty() && !device->dvrPath.isEmpty() && 1724 !device->frontendPath.isEmpty()) { 1725 QString path = QString(QLatin1String("/sys/class/dvb/dvb%1.frontend%2/")).arg(adapter).arg(index); 1726 QString deviceId; 1727 device->adapter = adapter; 1728 device->index = index; 1729 device->dvbv5_parms = NULL; 1730 if (QFile::exists(path + QLatin1String("device/vendor"))) { 1731 // PCI device 1732 int vendor = readSysAttr(path + QLatin1String("device/vendor")); 1733 int pciDevice = readSysAttr(path + QLatin1String("device/device")); 1734 int subsystemVendor = readSysAttr(path + QLatin1String("device/subsystem_vendor")); 1735 int subsystemDevice = readSysAttr(path + QLatin1String("device/subsystem_device")); 1736 1737 if ((vendor >= 0) && (pciDevice >= 0) && (subsystemVendor >= 0) && (subsystemDevice >= 0)) { 1738 deviceId = QLatin1Char('P'); 1739 deviceId += QString(QLatin1String("%1")).arg(vendor, 4, 16, QLatin1Char('0')); 1740 deviceId += QString(QLatin1String("%1")).arg(pciDevice, 4, 16, QLatin1Char('0')); 1741 deviceId += QString(QLatin1String("%1")).arg(subsystemVendor, 4, 16, QLatin1Char('0')); 1742 deviceId += QString(QLatin1String("%1")).arg(subsystemDevice, 4, 16, QLatin1Char('0')); 1743 } 1744 } else if (QFile::exists(path + QLatin1String("device/idVendor"))) { 1745 // USB device 1746 int vendor = readSysAttr(path + QLatin1String("device/idVendor")); 1747 int product = readSysAttr(path + QLatin1String("device/idProduct")); 1748 1749 if ((vendor >= 0) && (product >= 0)) { 1750 deviceId = QLatin1Char('U'); 1751 deviceId += QString(QLatin1String("%1")).arg(vendor, 4, 16, QLatin1Char('0')); 1752 deviceId += QString(QLatin1String("%1")).arg(product, 4, 16, QLatin1Char('0')); 1753 } 1754 } 1755 1756 device->startDevice(deviceId); 1757 1758 if (device->isReady()) { 1759 emit deviceAdded(device); 1760 } 1761 } 1762 } 1763 1764 void DvbLinuxDeviceManager::componentRemoved(QString node, int adapter, int index) { 1765 int deviceIndex = (adapter << 16) | index; 1766 char adapterstring[10]; 1767 DvbLinuxDevice *device = devices.value(deviceIndex, NULL); 1768 if (device == NULL) { 1769 return; 1770 } 1771 sprintf(adapterstring, "adapter%d", adapter); 1772 1773 QRegularExpressionMatch match; 1774 QRegularExpression rejex = QRegularExpression("(frontend|dvr|demux|ca)\\d+"); 1775 if (node.contains(rejex)) 1776 return; 1777 QString type = match.captured(1); 1778 1779 if (type == "frontend") { 1780 device->frontendPath.clear(); 1781 } else if (type == "dvr") { 1782 device->dvrPath.clear(); 1783 } else if (type == "demux") { 1784 device->demuxPath.clear(); 1785 } else if (type == "ca") { 1786 device->caPath.clear(); 1787 } else { 1788 return; 1789 } 1790 1791 if (device->frontendPath.isEmpty() && device->dvrPath.isEmpty() && 1792 device->demuxPath.isEmpty() && device->isReady()) { 1793 emit deviceRemoved(device); 1794 device->stopDevice(); 1795 } 1796 } 1797 1798 void DvbLinuxDeviceManager::componentRemoved(const QString &udi) 1799 { 1800 QRegularExpression rejex = QRegularExpression("/dvb/dvb(\\d+).(\\w+)(\\d+)"); 1801 if (!udi.contains(rejex)) 1802 return; 1803 1804 DvbLinuxDevice *device = udis.take(udi); 1805 1806 // The device is not mapped. Just return 1807 if (!device) 1808 return; 1809 1810 bool removeDevice = false; 1811 1812 if (device->isReady()) 1813 qCInfo(logDev, "Digital TV device removed %s: %s", qPrintable(device->getDeviceId()), qPrintable(device->getFrontendName())); 1814 1815 if (udi == device->caUdi) { 1816 device->caPath.clear(); 1817 device->caUdi.clear(); 1818 1819 if (device->isReady()) { 1820 device->stopCa(); 1821 } 1822 } else if (udi == device->demuxUdi) { 1823 device->demuxPath.clear(); 1824 device->demuxUdi.clear(); 1825 removeDevice = true; 1826 } else if (udi == device->dvrUdi) { 1827 device->dvrPath.clear(); 1828 device->dvrUdi.clear(); 1829 removeDevice = true; 1830 } else if (udi == device->frontendUdi) { 1831 device->frontendPath.clear(); 1832 device->frontendUdi.clear(); 1833 removeDevice = true; 1834 } 1835 1836 if (removeDevice && device->isReady()) { 1837 emit deviceRemoved(device); 1838 device->stopDevice(); 1839 } 1840 } 1841 1842 int DvbLinuxDeviceManager::readSysAttr(const QString &path) 1843 { 1844 QFile file(path); 1845 1846 if (!file.open(QIODevice::ReadOnly)) { 1847 return -1; 1848 } 1849 1850 QByteArray data = file.read(8); 1851 1852 if ((data.size() == 0) || (data.size() == 8)) { 1853 return -1; 1854 } 1855 1856 bool ok = false; 1857 int value = data.simplified().toInt(&ok, 0); 1858 1859 if (!ok || (value < 0) || (value > 0xffff)) { 1860 return -1; 1861 } 1862 1863 return value; 1864 } 1865 1866 #include "moc_dvbdevice_linux.cpp"