+ case eSecCommand::SLEEP:
+ delay = m_sec_sequence.current()++->msec;
+ eDebug("[SEC] sleep %dms", delay);
+ break;
+ case eSecCommand::GOTO:
+ if ( !setSecSequencePos(m_sec_sequence.current()->steps) )
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SET_VOLTAGE:
+ {
+ int voltage = m_sec_sequence.current()++->voltage;
+ eDebug("[SEC] setVoltage %d", voltage);
+ sec_fe->setVoltage(voltage);
+ break;
+ }
+ case eSecCommand::IF_VOLTAGE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.voltage == sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_NOT_VOLTAGE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.voltage != sec_fe_data[CUR_VOLTAGE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_TONE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.tone == sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_NOT_TONE_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ if ( compare.tone != sec_fe_data[CUR_TONE] && setSecSequencePos(compare.steps) )
+ break;
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::SET_TONE:
+ eDebug("[SEC] setTone %d", m_sec_sequence.current()->tone);
+ sec_fe->setTone(m_sec_sequence.current()++->tone);
+ break;
+ case eSecCommand::SEND_DISEQC:
+ sec_fe->sendDiseqc(m_sec_sequence.current()->diseqc);
+ eDebugNoNewLine("[SEC] sendDiseqc: ");
+ for (int i=0; i < m_sec_sequence.current()->diseqc.len; ++i)
+ eDebugNoNewLine("%02x", m_sec_sequence.current()->diseqc.data[i]);
+ eDebug("");
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SEND_TONEBURST:
+ eDebug("[SEC] sendToneburst: %d", m_sec_sequence.current()->toneburst);
+ sec_fe->sendToneburst(m_sec_sequence.current()++->toneburst);
+ break;
+ case eSecCommand::SET_FRONTEND:
+ eDebug("[SEC] setFrontend");
+ setFrontend();
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::START_TUNE_TIMEOUT:
+ {
+ m_timeout->start(m_sec_sequence.current()->timeout, 1);
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::SET_TIMEOUT:
+ m_timeoutCount = m_sec_sequence.current()++->val;
+ eDebug("[SEC] set timeout %d", m_timeoutCount);
+ break;
+ case eSecCommand::IF_TIMEOUT_GOTO:
+ if (!m_timeoutCount)
+ {
+ eDebug("[SEC] rotor timout");
+ setSecSequencePos(m_sec_sequence.current()->steps);
+ }
+ else
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::MEASURE_IDLE_INPUTPOWER:
+ {
+ int idx = m_sec_sequence.current()++->val;
+ if ( idx == 0 || idx == 1 )
+ {
+ m_idleInputpower[idx] = sec_fe->readInputpower();
+ eDebug("[SEC] idleInputpower[%d] is %d", idx, m_idleInputpower[idx]);
+ }
+ else
+ eDebug("[SEC] idleInputpower measure index(%d) out of bound !!!", idx);
+ break;
+ }
+ case eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO:
+ {
+ eSecCommand::pair &compare = m_sec_sequence.current()->compare;
+ int idx = compare.val;
+ if ( idx == 0 || idx == 1 )
+ {
+ int idle = sec_fe->readInputpower();
+ int diff = abs(idle-m_idleInputpower[idx]);
+ if ( diff > 0)
+ {
+ eDebug("measure idle(%d) was not okay.. (%d - %d = %d) retry", idx, m_idleInputpower[idx], idle, diff);
+ setSecSequencePos(compare.steps);
+ break;
+ }
+ }
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_TUNER_LOCKED_GOTO:
+ {
+ int signal = 0;
+ int isLocked = readFrontendData(locked);
+ m_idleInputpower[0] = m_idleInputpower[1] = 0;
+ eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
+ if (isLocked && ((abs((signal = readFrontendData(signalQualitydB)) - cmd.lastSignal) < 50) || !cmd.lastSignal))
+ {
+ if (cmd.lastSignal)
+ eDebug("[SEC] locked step %d ok (%d %d)", cmd.okcount, signal, cmd.lastSignal);
+ else
+ {
+ eDebug("[SEC] locked step %d ok", cmd.okcount);
+ cmd.lastSignal = signal;
+ }
+ ++cmd.okcount;
+ if (cmd.okcount > 4)
+ {
+ eDebug("ok > 4 .. goto %d\n",cmd.steps);
+ setSecSequencePos(cmd.steps);
+ m_state = stateLock;
+ m_stateChanged(this);
+ feEvent(-1);
+ m_sn->start();
+ break;
+ }
+ }
+ else
+ {
+ if (isLocked)
+ eDebug("[SEC] rotor locked step %d failed (oldSignal %d, curSignal %d)", cmd.okcount, signal, cmd.lastSignal);
+ else
+ eDebug("[SEC] rotor locked step %d failed (not locked)", cmd.okcount);
+ --m_timeoutCount;
+ if (!m_timeoutCount && m_retryCount > 0)
+ --m_retryCount;
+ cmd.okcount=0;
+ cmd.lastSignal=0;
+ }
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::MEASURE_RUNNING_INPUTPOWER:
+ m_runningInputpower = sec_fe->readInputpower();
+ eDebug("[SEC] runningInputpower is %d", m_runningInputpower);
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SET_ROTOR_MOVING:
+ m_sec->setRotorMoving(true);
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SET_ROTOR_STOPPED:
+ m_sec->setRotorMoving(false);
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::IF_INPUTPOWER_DELTA_GOTO:
+ {
+ int idleInputpower = m_idleInputpower[ (sec_fe_data[CUR_VOLTAGE]&1) ? 0 : 1];
+ eSecCommand::rotor &cmd = m_sec_sequence.current()->measure;
+ const char *txt = cmd.direction ? "running" : "stopped";
+ eDebug("[SEC] waiting for rotor %s %d, idle %d, delta %d",
+ txt,
+ m_runningInputpower,
+ idleInputpower,
+ cmd.deltaA);
+ if ( (cmd.direction && abs(m_runningInputpower - idleInputpower) >= cmd.deltaA)
+ || (!cmd.direction && abs(m_runningInputpower - idleInputpower) <= cmd.deltaA) )
+ {
+ ++cmd.okcount;
+ eDebug("[SEC] rotor %s step %d ok", txt, cmd.okcount);
+ if ( cmd.okcount > 6 )
+ {
+ eDebug("[SEC] rotor is %s", txt);
+ if (setSecSequencePos(cmd.steps))
+ break;
+ }
+ }
+ else
+ {
+ eDebug("[SEC] rotor not %s... reset counter.. increase timeout", txt);
+ --m_timeoutCount;
+ if (!m_timeoutCount && m_retryCount > 0)
+ --m_retryCount;
+ cmd.okcount=0;
+ }
+ ++m_sec_sequence.current();
+ break;
+ }
+ case eSecCommand::IF_ROTORPOS_VALID_GOTO:
+ if (sec_fe_data[ROTOR_CMD] != -1 && sec_fe_data[ROTOR_POS] != -1)
+ setSecSequencePos(m_sec_sequence.current()->steps);
+ else
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS:
+ eDebug("[SEC] invalidate current switch params");
+ sec_fe_data[CSW] = -1;
+ sec_fe_data[UCSW] = -1;
+ sec_fe_data[TONEBURST] = -1;
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::UPDATE_CURRENT_SWITCHPARMS:
+ sec_fe_data[CSW] = sec_fe_data[NEW_CSW];
+ sec_fe_data[UCSW] = sec_fe_data[NEW_UCSW];
+ sec_fe_data[TONEBURST] = sec_fe_data[NEW_TONEBURST];
+ eDebug("[SEC] update current switch params");
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::INVALIDATE_CURRENT_ROTORPARMS:
+ eDebug("[SEC] invalidate current rotorparams");
+ sec_fe_data[ROTOR_CMD] = -1;
+ sec_fe_data[ROTOR_POS] = -1;
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::UPDATE_CURRENT_ROTORPARAMS:
+ sec_fe_data[ROTOR_CMD] = sec_fe_data[NEW_ROTOR_CMD];
+ sec_fe_data[ROTOR_POS] = sec_fe_data[NEW_ROTOR_POS];
+ eDebug("[SEC] update current rotorparams %d %04lx %ld", m_timeoutCount, sec_fe_data[ROTOR_CMD], sec_fe_data[ROTOR_POS]);
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SET_ROTOR_DISEQC_RETRYS:
+ m_retryCount = m_sec_sequence.current()++->val;
+ eDebug("[SEC] set rotor retries %d", m_retryCount);
+ break;
+ case eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO:
+ if (!m_retryCount)
+ {
+ eDebug("[SEC] no more rotor retrys");
+ setSecSequencePos(m_sec_sequence.current()->steps);
+ }
+ else
+ ++m_sec_sequence.current();
+ break;
+ case eSecCommand::SET_POWER_LIMITING_MODE:
+ {
+ char proc_name[64];
+ sprintf(proc_name, "/proc/stb/frontend/%d/static_current_limiting", sec_fe->m_dvbid);
+ FILE *f=fopen(proc_name, "w");
+ if (f) // new interface exist?
+ {
+ bool slimiting = m_sec_sequence.current()->mode == eSecCommand::modeStatic;
+ if (fprintf(f, "%s", slimiting ? "on" : "off") <= 0)
+ eDebug("write %s failed!! (%m)", proc_name);
+ else
+ eDebug("[SEC] set %s current limiting", slimiting ? "static" : "dynamic");
+ fclose(f);
+ }
+ else if (sec_fe->m_need_rotor_workaround)
+ {
+ char dev[16];
+ int slotid = sec_fe->m_slotid;
+ // FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
+ if (slotid < 2)
+ sprintf(dev, "/dev/i2c/%d", slotid);
+ else if (slotid == 2)
+ sprintf(dev, "/dev/i2c/2"); // first nim socket on DM8000 use /dev/i2c/2
+ else if (slotid == 3)
+ sprintf(dev, "/dev/i2c/4"); // second nim socket on DM8000 use /dev/i2c/4
+ int fd = ::open(dev, O_RDWR);
+
+ unsigned char data[2];
+ ::ioctl(fd, I2C_SLAVE_FORCE, 0x10 >> 1);
+ if(::read(fd, data, 1) != 1)
+ eDebug("[SEC] error read lnbp (%m)");
+ if ( m_sec_sequence.current()->mode == eSecCommand::modeStatic )
+ {
+ data[0] |= 0x80; // enable static current limiting
+ eDebug("[SEC] set static current limiting");
+ }
+ else
+ {
+ data[0] &= ~0x80; // enable dynamic current limiting
+ eDebug("[SEC] set dynamic current limiting");
+ }
+ if(::write(fd, data, 1) != 1)
+ eDebug("[SEC] error write lnbp (%m)");
+ ::close(fd);
+ }
+ ++m_sec_sequence.current();
+ break;
+ }
+ default:
+ eDebug("[SEC] unhandled sec command %d",
+ ++m_sec_sequence.current()->cmd);
+ ++m_sec_sequence.current();
+ }
+ m_tuneTimer->start(delay,true);
+ }
+ if (regFE)
+ regFE->dec_use();
+}
+
+void eDVBFrontend::setFrontend()
+{
+ eDebug("setting frontend %d", m_dvbid);
+ m_sn->start();
+ feEvent(-1);
+ if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
+ {
+ perror("FE_SET_FRONTEND failed");
+ return;
+ }
+}
+
+RESULT eDVBFrontend::getFrontendType(int &t)
+{
+ if (m_type == -1)
+ return -ENODEV;
+ t = m_type;
+ return 0;
+}
+
+RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm, unsigned int tunetimeout)
+{
+ int res;
+ if (!m_sec)
+ {
+ eWarning("no SEC module active!");
+ return -ENOENT;
+ }
+ res = m_sec->prepare(*this, parm, feparm, 1 << m_slotid, tunetimeout);
+ if (!res)
+ {
+ eDebug("prepare_sat System %d Freq %d Pol %d SR %d INV %d FEC %d orbpos %d",
+ feparm.system,
+ feparm.frequency,
+ feparm.polarisation,
+ feparm.symbol_rate,
+ feparm.inversion,
+ feparm.fec,
+ feparm.orbital_position);
+ parm_u_qpsk_symbol_rate = feparm.symbol_rate;
+ switch (feparm.inversion)
+ {
+ case eDVBFrontendParametersSatellite::Inversion::On:
+ parm_inversion = INVERSION_ON;
+ break;
+ case eDVBFrontendParametersSatellite::Inversion::Off:
+ parm_inversion = INVERSION_OFF;
+ break;
+ default:
+ case eDVBFrontendParametersSatellite::Inversion::Unknown:
+ parm_inversion = INVERSION_AUTO;
+ break;
+ }
+ if (feparm.system == eDVBFrontendParametersSatellite::System::DVB_S)
+ switch (feparm.fec)
+ {
+ case eDVBFrontendParametersSatellite::FEC::fNone:
+ parm_u_qpsk_fec_inner = FEC_NONE;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f1_2:
+ parm_u_qpsk_fec_inner = FEC_1_2;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f2_3:
+ parm_u_qpsk_fec_inner = FEC_2_3;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f3_4:
+ parm_u_qpsk_fec_inner = FEC_3_4;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f5_6:
+ parm_u_qpsk_fec_inner = FEC_5_6;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f7_8:
+ parm_u_qpsk_fec_inner = FEC_7_8;
+ break;
+ default:
+ eDebug("no valid fec for DVB-S set.. assume auto");
+ case eDVBFrontendParametersSatellite::FEC::fAuto:
+ parm_u_qpsk_fec_inner = FEC_AUTO;
+ break;
+ }
+#if HAVE_DVB_API_VERSION >= 3
+ else // DVB_S2
+ {
+ switch (feparm.fec)
+ {
+ case eDVBFrontendParametersSatellite::FEC::f1_2:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_1_2;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f2_3:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_2_3;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f3_4:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_4;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f3_5:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_3_5;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f4_5:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_4_5;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f5_6:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_5_6;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f7_8:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_7_8;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f8_9:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_8_9;
+ break;
+ case eDVBFrontendParametersSatellite::FEC::f9_10:
+ parm_u_qpsk_fec_inner = FEC_S2_QPSK_9_10;
+ break;
+ default:
+ eDebug("no valid fec for DVB-S2 set.. abort !!");
+ return -EINVAL;
+ }
+ parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
+ if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
+ parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
+ // 8PSK fec driver values are decimal 9 bigger
+ parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
+ }
+ }