Support turbo2.
[vuplus_dvbapp] / lib / dvb / sec.cpp
1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/sec.h>
3 #include <lib/dvb/rotor_calc.h>
4 #include <lib/dvb/dvbtime.h>
5 #include <lib/base/eerror.h>
6 #include <set>
7
8 //#define SEC_DEBUG
9
10 #ifdef SEC_DEBUG
11 #define eSecDebug(arg...) eDebug(arg)
12 #else
13 #define eSecDebug(arg...)
14 #endif
15
16 DEFINE_REF(eDVBSatelliteEquipmentControl);
17
18 eDVBSatelliteEquipmentControl *eDVBSatelliteEquipmentControl::instance;
19
20 int eDVBSatelliteEquipmentControl::m_params[MAX_PARAMS];
21 /*
22    defaults are set in python lib/python/Components/NimManager.py
23    in InitSecParams function via setParam call
24 */
25
26 void eDVBSatelliteEquipmentControl::setParam(int param, int value)
27 {
28         if (param >= 0 && param < MAX_PARAMS)
29                 m_params[param]=value;
30 }
31
32 eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl(eSmartPtrList<eDVBRegisteredFrontend> &avail_frontends, eSmartPtrList<eDVBRegisteredFrontend> &avail_simulate_frontends)
33         :m_lnbidx((sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters))-1), m_curSat(m_lnbs[0].m_satellites.end()), m_avail_frontends(avail_frontends), m_avail_simulate_frontends(avail_simulate_frontends), m_rotorMoving(0)
34 {
35         if (!instance)
36                 instance = this;
37         clear();
38 }
39
40 #define eSecDebugNoSimulate(x...) \
41         do { \
42                 if (!simulate) \
43                         eSecDebug(x); \
44         } while(0)
45
46 int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite &sat, iDVBFrontend *fe, int slot_id, int *highest_score_lnb)
47 {
48         bool simulate = ((eDVBFrontend*)fe)->is_simulate();
49         bool direct_connected = m_not_linked_slot_mask & slot_id;
50         int score=0, satcount=0;
51         long linked_prev_ptr=-1, linked_next_ptr=-1, linkable_csw=-1, linkable_ucsw=-1, linkable_toneburst=-1,
52                 fe_satpos_depends_ptr=-1, fe_rotor_pos=-1;
53         bool linked_in_use = false;
54
55         eSecDebugNoSimulate("direct_connected %d", !!direct_connected);
56
57         fe->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
58         fe->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
59         fe->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, fe_satpos_depends_ptr);
60
61         // first we search the linkage base frontend and check if any tuner in prev direction is used
62         while (linked_prev_ptr != -1)
63         {
64                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
65                 if (linked_fe->m_inuse)
66                         linked_in_use = true;
67                 fe = linked_fe->m_frontend;
68                 linked_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
69         }
70
71         fe->getData(eDVBFrontend::ROTOR_POS, fe_rotor_pos);
72
73         // now check also the linked tuners  is in use
74         while (!linked_in_use && linked_next_ptr != -1)
75         {
76                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
77                 if (linked_fe->m_inuse)
78                         linked_in_use = true;
79                 linked_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
80         }
81
82         // when a linked in use tuner is found we get the tuner data...
83         if (linked_in_use)
84         {
85                 fe->getData(eDVBFrontend::LINKABLE_CSW, linkable_csw);
86                 fe->getData(eDVBFrontend::LINKABLE_UCSW, linkable_ucsw);
87                 fe->getData(eDVBFrontend::LINKABLE_TONEBURST, linkable_toneburst);
88         }
89
90         if (highest_score_lnb)
91                 *highest_score_lnb = -1;
92
93         eSecDebugNoSimulate("canTune %d", slot_id);
94
95         for (int idx=0; idx <= m_lnbidx; ++idx )
96         {
97                 bool rotor=false;
98                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
99                 bool is_unicable = lnb_param.SatCR_idx != -1;
100                 bool is_unicable_position_switch = lnb_param.SatCR_positions > 1;
101
102                 if ( lnb_param.m_slot_mask & slot_id ) // lnb for correct tuner?
103                 {
104                         int ret = 0;
105                         eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
106
107                         eSecDebugNoSimulate("lnb %d found", idx);
108
109                         satcount += lnb_param.m_satellites.size();
110
111                         std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
112                                 lnb_param.m_satellites.find(sat.orbital_position);
113                         if ( sit != lnb_param.m_satellites.end())
114                         {
115                                 bool diseqc=false;
116                                 long band=0,
117                                         satpos_depends_ptr=fe_satpos_depends_ptr,
118                                         csw = di_param.m_committed_cmd,
119                                         ucsw = di_param.m_uncommitted_cmd,
120                                         toneburst = di_param.m_toneburst_param,
121                                         rotor_pos = fe_rotor_pos;
122
123                                 eSecDebugNoSimulate("sat %d found", sat.orbital_position);
124
125                                 if ( sat.frequency > lnb_param.m_lof_threshold )
126                                         band |= 1;
127                                 if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical))
128                                         band |= 2;
129
130                                 if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
131                                 {
132                                         diseqc=true;
133                                         if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
134                                                 csw = 0xF0 | (csw << 2);
135
136                                         if (di_param.m_committed_cmd <= eDVBSatelliteDiseqcParameters::SENDNO)
137                                                 csw |= band;
138
139                                         if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2 )  // ROTOR
140                                                 rotor = true;
141
142                                         ret = 10000;
143                                 }
144                                 else
145                                 {
146                                         csw = band;
147                                         ret = 15000;
148                                 }
149
150                                 if (sat.no_rotor_command_on_tune && !rotor) {
151                                         eSecDebugNoSimulate("no rotor but no_rotor_command_on_tune is set.. ignore lnb %d", idx);
152                                         continue;
153                                 }
154
155                                 eSecDebugNoSimulate("ret1 %d", ret);
156
157                                 if (linked_in_use && !is_unicable)
158                                 {
159                                         // compare tuner data
160                                         if ( (csw != linkable_csw) ||
161                                                 ( diseqc && (ucsw != linkable_ucsw || toneburst != linkable_toneburst) ) ||
162                                                 ( rotor && rotor_pos != sat.orbital_position ) )
163                                         {
164                                                 ret = 0;
165                                         }
166                                         else
167                                                 ret += 15;
168                                         eSecDebugNoSimulate("ret2 %d", ret);
169                                 }
170                                 else if ((satpos_depends_ptr != -1) && !(is_unicable && is_unicable_position_switch))
171                                 {
172                                         eSecDebugNoSimulate("satpos depends");
173                                         eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) satpos_depends_ptr;
174                                         if (direct_connected) // current fe is direct connected.. (can turn the rotor)
175                                         {
176                                                 if (satpos_depends_to_fe->m_inuse) // if the dependent frontend is in use?
177                                                 {
178                                                         if (!rotor || rotor_pos != sat.orbital_position) // new orbital position not equal to current orbital pos?
179                                                                 ret = 0;
180                                                         else
181                                                                 ret += 10;
182                                                 }
183                                                 eSecDebugNoSimulate("ret3 %d", ret);
184                                         }
185                                         else // current fe is dependent of another tuner ... (so this fe can't turn the rotor!)
186                                         {
187                                                 // get current orb pos of the tuner with rotor connection
188                                                 satpos_depends_to_fe->m_frontend->getData(eDVBFrontend::ROTOR_POS, rotor_pos);
189                                                 if (!rotor || rotor_pos == -1 /* we dont know the rotor position yet */
190                                                         || rotor_pos != sat.orbital_position ) // not the same orbital position?
191                                                 {
192                                                         ret = 0;
193                                                 }
194                                         }
195                                         eSecDebugNoSimulate("ret4 %d", ret);
196                                 }
197
198                                 if (ret && rotor && rotor_pos != -1)
199                                         ret -= abs(rotor_pos-sat.orbital_position);
200
201                                 eSecDebugNoSimulate("ret5 %d", ret);
202
203                                 if (ret && !is_unicable)
204                                 {
205                                         int lof = sat.frequency > lnb_param.m_lof_threshold ?
206                                                 lnb_param.m_lof_hi : lnb_param.m_lof_lo;
207                                         int tuner_freq = abs(sat.frequency - lof);
208                                         if (tuner_freq < 900000 || tuner_freq > 2200000)
209                                                 ret = 0;
210                                 }
211
212                                 if (ret && lnb_param.m_prio != -1)
213                                         ret = lnb_param.m_prio;
214
215                                 eSecDebugNoSimulate("ret %d, score old %d", ret, score);
216                                 if (ret > score)
217                                 {
218                                         score = ret;
219                                         if (highest_score_lnb)
220                                                 *highest_score_lnb = idx;
221                                 }
222                                 eSecDebugNoSimulate("score new %d", score);
223                         }
224                 }
225         }
226         if (score && satcount)
227         {
228                 if (score > (satcount-1))
229                         score -= (satcount-1);
230                 else
231                         score = 1; // min score
232         }
233         if (score && direct_connected)
234                 score += 5; // increase score for tuners with direct sat connection
235         eSecDebugNoSimulate("final score %d", score);
236         return score;
237 }
238
239 bool need_turn_fast(int turn_speed)
240 {
241         if (turn_speed == eDVBSatelliteRotorParameters::FAST)
242                 return true;
243         else if (turn_speed != eDVBSatelliteRotorParameters::SLOW)
244         {
245                 int begin = turn_speed >> 16; // high word is start time
246                 int end = turn_speed&0xFFFF; // low word is end time
247                 time_t now_time = ::time(0);
248                 tm nowTime;
249                 localtime_r(&now_time, &nowTime);
250                 int now = (nowTime.tm_hour + 1) * 60 + nowTime.tm_min + 1;
251                 bool neg = end <= begin;
252                 if (neg) {
253                         int tmp = begin;
254                         begin = end;
255                         end = tmp;
256                 }
257                 if ((now >= begin && now < end) ^ neg)
258                         return true;
259         }
260         return false;
261 }
262
263 #define VOLTAGE(x) (lnb_param.m_increased_voltage ? iDVBFrontend::voltage##x##_5 : iDVBFrontend::voltage##x)
264
265 #define eDebugNoSimulate(x...) \
266         do { \
267                 if (!simulate) \
268                         eDebug(x); \
269         } while(0)
270
271 RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPARAMETERS &parm, const eDVBFrontendParametersSatellite &sat, int slot_id, unsigned int tunetimeout)
272 {
273         bool simulate = ((eDVBFrontend*)&frontend)->is_simulate();
274         int lnb_idx = -1;
275         if (canTune(sat, &frontend, slot_id, &lnb_idx))
276         {
277                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[lnb_idx];
278                 eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
279                 eDVBSatelliteRotorParameters &rotor_param = lnb_param.m_rotor_parameters;
280
281                 std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
282                         lnb_param.m_satellites.find(sat.orbital_position);
283                 if ( sit != lnb_param.m_satellites.end())
284                 {
285                         eSecCommandList sec_sequence;
286                         eDVBSatelliteSwitchParameters &sw_param = sit->second;
287                         bool doSetFrontend = true;
288                         bool doSetVoltageToneFrontend = true;
289                         bool forceChanged = false;
290                         bool needDiSEqCReset = false;
291                         long band=0,
292                                 voltage = iDVBFrontend::voltageOff,
293                                 tone = iDVBFrontend::toneOff,
294                                 csw = di_param.m_committed_cmd,
295                                 ucsw = di_param.m_uncommitted_cmd,
296                                 toneburst = di_param.m_toneburst_param,
297                                 lastcsw = -1,
298                                 lastucsw = -1,
299                                 lastToneburst = -1,
300                                 lastRotorCmd = -1,
301                                 curRotorPos = -1,
302                                 satposDependPtr = -1;
303                         iDVBFrontend *sec_fe=&frontend;
304                         eDVBRegisteredFrontend *linked_fe = 0;
305                         eDVBSatelliteDiseqcParameters::t_diseqc_mode diseqc_mode = di_param.m_diseqc_mode;
306                         eDVBSatelliteSwitchParameters::t_voltage_mode voltage_mode = sw_param.m_voltage_mode;
307                         bool diseqc13V = voltage_mode == eDVBSatelliteSwitchParameters::HV_13;
308                         bool is_unicable = lnb_param.SatCR_idx != -1;
309
310                         bool useGotoXX = false;
311                         int RotorCmd=-1;
312                         int send_mask = 0;
313
314                         bool direct_connected = m_not_linked_slot_mask & slot_id;
315
316                         lnb_param.guard_offset = 0; //HACK
317
318
319                         if (diseqc13V)
320                                 voltage_mode = eDVBSatelliteSwitchParameters::HV;
321
322                         frontend.getData(eDVBFrontend::SATPOS_DEPENDS_PTR, satposDependPtr);
323
324                         if (!direct_connected)  // frontend with direct connection?
325                         {
326                                 long linked_prev_ptr;
327                                 frontend.getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
328                                 while (linked_prev_ptr != -1)
329                                 {
330                                         linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
331                                         sec_fe = linked_fe->m_frontend;
332                                         sec_fe->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
333                                 }
334                                 if (satposDependPtr != -1)  // we dont need uncommitted switch and rotor cmds on second output of a rotor lnb
335                                         diseqc_mode = eDVBSatelliteDiseqcParameters::V1_0;
336 #if 0 // Since following code causes lock fail for linked tuners in certain conditions, it does not apply.
337                                 else {
338                                         // in eDVBFrontend::tuneLoop we call closeFrontend and ->inc_use() in this this condition (to put the kernel frontend thread into idle state)
339                                         // so we must resend all diseqc stuff (voltage is disabled when the frontend is closed)
340                                         int state;
341                                         sec_fe->getState(state);
342                                         if (!linked_fe->m_inuse && state != eDVBFrontend::stateIdle)
343                                                 forceChanged = true;
344                                 }
345 #endif
346                         }
347
348                         sec_fe->getData(eDVBFrontend::CSW, lastcsw);
349                         sec_fe->getData(eDVBFrontend::UCSW, lastucsw);
350                         sec_fe->getData(eDVBFrontend::TONEBURST, lastToneburst);
351                         sec_fe->getData(eDVBFrontend::ROTOR_CMD, lastRotorCmd);
352                         sec_fe->getData(eDVBFrontend::ROTOR_POS, curRotorPos);
353
354                         if (lastcsw == lastucsw && lastToneburst == lastucsw && lastucsw == -1)
355                                 needDiSEqCReset = true;
356
357                         if ( sat.frequency > lnb_param.m_lof_threshold )
358                                 band |= 1;
359                         if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical))
360                                 band |= 2;
361
362                         int lof = (band&1)?lnb_param.m_lof_hi:lnb_param.m_lof_lo;
363
364                         if(!is_unicable)
365                         {
366                                 // calc Frequency
367                                 int local= abs(sat.frequency
368                                         - lof);
369                                 parm.frequency = ((((local * 2) / 125) + 1) / 2) * 125;
370                                 frontend.setData(eDVBFrontend::FREQ_OFFSET, sat.frequency - parm.frequency);
371
372                                 if ( voltage_mode == eDVBSatelliteSwitchParameters::_14V
373                                         || ( sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical
374                                                 && voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
375                                         voltage = VOLTAGE(13);
376                                 else if ( voltage_mode == eDVBSatelliteSwitchParameters::_18V
377                                         || ( !(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation_Vertical)
378                                                 && voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
379                                         voltage = VOLTAGE(18);
380                                 if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::ON)
381                                         || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && (band&1) ) )
382                                         tone = iDVBFrontend::toneOn;
383                                 else if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::OFF)
384                                         || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && !(band&1) ) )
385                                         tone = iDVBFrontend::toneOff;
386                         }
387                         else
388                         {
389                                 switch(lnb_param.SatCR_format)
390                                 {
391                                         case 1:
392                                                 {
393                                                         eDebug("[prepare] JESS");
394
395                                                         int tmp1 = abs(sat.frequency
396                                                                 -lof)
397                                                                 - 100000;
398                                                         volatile unsigned int tmp2 = (1000 + 2 * tmp1) / (2 *1000); //round to multiple of 1000
399                                                         parm.frequency = lnb_param.SatCRvco - (tmp1 - (1000 * tmp2));
400                                                         frontend.setData(eDVBFrontend::FREQ_OFFSET, sat.frequency - lof -(lnb_param.SatCRvco - parm.frequency));
401
402                                                         lnb_param.UnicableTuningWord =
403                                                                   (band & 0x3)                                          //Bit0:HighLow  Bit1:VertHor
404                                                                 | (((lnb_param.LNBNum - 1) & 0x3F) << 2)                        //position number (max. 63)
405                                                                 | ((tmp2 & 0x7FF)<< 8)                                  //frequency (-100MHz Offset)
406                                                                 | ((lnb_param.SatCR_idx & 0x1F) << 19);                 //adresse of SatCR (max. 32)
407
408                                                         eDebug("[prepare] UnicableTuningWord %#06x",lnb_param.UnicableTuningWord);
409                                                 }
410                                                 break;
411                                         case 0:
412                                         default:
413                                                 {
414                                                         eDebug("[prepare] Unicable");
415                                                         int tmp1 = abs(sat.frequency
416                                                                 -lof)
417                                                                 + lnb_param.SatCRvco
418                                                                 - 1400000
419                                                                 + lnb_param.guard_offset;
420                                                         volatile unsigned int tmp2 = (4000 + 2 * tmp1) / (2 *4000); //round to multiple of 4000
421
422                                                         parm.frequency = lnb_param.SatCRvco - (tmp1 - (4000 * tmp2)) + lnb_param.guard_offset;
423                                                         lnb_param.UnicableTuningWord = tmp2
424                                                                 | ((band & 1) ? 0x400 : 0)                      //HighLow
425                                                                 | ((band & 2) ? 0x800 : 0)                      //VertHor
426                                                                 | ((lnb_param.LNBNum & 1) ? 0 : 0x1000)                 //Umschaltung LNB1 LNB2
427                                                                 | (lnb_param.SatCR_idx << 13);          //Adresse des SatCR
428
429                                                         eDebug("[prepare] UnicableTuningWord %#04x",lnb_param.UnicableTuningWord);
430                                                         eDebug("[prepare] guard_offset %d",lnb_param.guard_offset);
431
432                                                         frontend.setData(eDVBFrontend::FREQ_OFFSET, (lnb_param.UnicableTuningWord & 0x3FF) *4000 + 1400000 + lof - (2 * (lnb_param.SatCRvco - (tmp1 - (4000 * tmp2)))) );
433                                                 }
434                                 }
435                                 voltage = VOLTAGE(13);
436                         }
437
438                         if (diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
439                         {
440                                 if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
441                                         csw = 0xF0 | (csw << 2);
442
443                                 if (di_param.m_committed_cmd <= eDVBSatelliteDiseqcParameters::SENDNO)
444                                         csw |= band;
445
446                                 bool send_csw =
447                                         (di_param.m_committed_cmd != eDVBSatelliteDiseqcParameters::SENDNO);
448
449                                 bool send_ucsw =
450                                         (di_param.m_uncommitted_cmd && diseqc_mode > eDVBSatelliteDiseqcParameters::V1_0);
451
452                                 bool send_burst =
453                                         (di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO);
454
455                                 bool changed_csw = false;
456                                 bool changed_ucsw = false;
457                                 bool changed_burst = false;
458                                 if (direct_connected || (linked_fe && (!linked_fe->m_frontend->isLoopTimerActive() || !linked_fe->m_frontend->isScheduledSendDiseqc())))
459                                 {
460                                         changed_csw = send_csw && (forceChanged || csw != lastcsw);
461                                         changed_ucsw = send_ucsw && (forceChanged || ucsw != lastucsw);
462                                         changed_burst = send_burst && (forceChanged || toneburst != lastToneburst);
463                                 }
464
465                                 /* send_mask
466                                         1 must send csw
467                                         2 must send ucsw
468                                         4 send toneburst first
469                                         8 send toneburst at end */
470                                 if (changed_burst) // toneburst first and toneburst changed
471                                 {
472                                         if (di_param.m_command_order&1)
473                                         {
474                                                 send_mask |= 4;
475                                                 if ( send_csw )
476                                                         send_mask |= 1;
477                                                 if ( send_ucsw )
478                                                         send_mask |= 2;
479                                         }
480                                         else
481                                                 send_mask |= 8;
482                                 }
483                                 if (changed_ucsw)
484                                 {
485                                         send_mask |= 2;
486                                         if ((di_param.m_command_order&4) && send_csw)
487                                                 send_mask |= 1;
488                                         if (di_param.m_command_order==4 && send_burst)
489                                                 send_mask |= 8;
490                                 }
491                                 if (changed_csw)
492                                 {
493                                         if ( di_param.m_use_fast
494                                                 && di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO
495                                                 && (lastcsw & 0xF0)
496                                                 && ((csw / 4) == (lastcsw / 4)) )
497                                                 eDebugNoSimulate("dont send committed cmd (fast diseqc)");
498                                         else
499                                         {
500                                                 send_mask |= 1;
501                                                 if (!(di_param.m_command_order&4) && send_ucsw)
502                                                         send_mask |= 2;
503                                                 if (!(di_param.m_command_order&1) && send_burst)
504                                                         send_mask |= 8;
505                                         }
506                                 }
507
508 #if 0
509                                 eDebugNoNewLine("sendmask: ");
510                                 for (int i=3; i >= 0; --i)
511                                         if ( send_mask & (1<<i) )
512                                                 eDebugNoNewLine("1");
513                                         else
514                                                 eDebugNoNewLine("0");
515                                 eDebug("");
516 #endif
517                                 if ( diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2
518                                         && !sat.no_rotor_command_on_tune )
519                                 {
520                                         if (sw_param.m_rotorPosNum) // we have stored rotor pos?
521                                                 RotorCmd=sw_param.m_rotorPosNum;
522                                         else  // we must calc gotoxx cmd
523                                         {
524                                                 eDebugNoSimulate("Entry for %d,%d? not in Rotor Table found... i try gotoXX?", sat.orbital_position / 10, sat.orbital_position % 10 );
525                                                 useGotoXX = true;
526
527                                                 double  SatLon = abs(sat.orbital_position)/10.00,
528                                                                 SiteLat = rotor_param.m_gotoxx_parameters.m_latitude,
529                                                                 SiteLon = rotor_param.m_gotoxx_parameters.m_longitude;
530
531                                                 if ( rotor_param.m_gotoxx_parameters.m_la_direction == eDVBSatelliteRotorParameters::SOUTH )
532                                                         SiteLat = -SiteLat;
533
534                                                 if ( rotor_param.m_gotoxx_parameters.m_lo_direction == eDVBSatelliteRotorParameters::WEST )
535                                                         SiteLon = 360 - SiteLon;
536
537                                                 eDebugNoSimulate("siteLatitude = %lf, siteLongitude = %lf, %lf degrees", SiteLat, SiteLon, SatLon );
538                                                 double satHourAngle =
539                                                         calcSatHourangle( SatLon, SiteLat, SiteLon );
540                                                 eDebugNoSimulate("PolarmountHourAngle=%lf", satHourAngle );
541
542                                                 static int gotoXTable[10] =
543                                                         { 0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E };
544
545                                                 if (SiteLat >= 0) // Northern Hemisphere
546                                                 {
547                                                         int tmp=(int)round( fabs( 180 - satHourAngle ) * 10.0 );
548                                                         RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
549
550                                                         if (satHourAngle < 180) // the east
551                                                                 RotorCmd |= 0xE000;
552                                                         else                                    // west
553                                                                 RotorCmd |= 0xD000;
554                                                 }
555                                                 else // Southern Hemisphere
556                                                 {
557                                                         if (satHourAngle < 180) // the east
558                                                         {
559                                                                 int tmp=(int)round( fabs( satHourAngle ) * 10.0 );
560                                                                 RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
561                                                                 RotorCmd |= 0xD000;
562                                                         }
563                                                         else // west
564                                                         {
565                                                                 int tmp=(int)round( fabs( 360 - satHourAngle ) * 10.0 );
566                                                                 RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
567                                                                 RotorCmd |= 0xE000;
568                                                         }
569                                                 }
570                                                 eDebugNoSimulate("RotorCmd = %04x", RotorCmd);
571                                         }
572                                 }
573
574                                 if ( send_mask )
575                                 {
576                                         int diseqc_repeats = diseqc_mode > eDVBSatelliteDiseqcParameters::V1_0 ? di_param.m_repeats : 0;
577                                         int vlt = iDVBFrontend::voltageOff;
578                                         eSecCommand::pair compare;
579                                         compare.steps = +3;
580                                         compare.tone = iDVBFrontend::toneOff;
581                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
582                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
583                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) );
584
585                                         if (diseqc13V)
586                                                 vlt = iDVBFrontend::voltage13;
587                                         else if ( RotorCmd != -1 && RotorCmd != lastRotorCmd )
588                                         {
589                                                 if (rotor_param.m_inputpower_parameters.m_use && !is_unicable)
590                                                         vlt = VOLTAGE(18);  // in input power mode set 18V for measure input power
591                                                 else
592                                                         vlt = VOLTAGE(13);  // in normal mode start turning with 13V
593                                         }
594                                         else
595                                                 vlt = voltage;
596
597                                         // check if voltage is already correct..
598                                         compare.voltage = vlt;
599                                         compare.steps = +7;
600                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
601
602                                         // check if voltage is disabled
603                                         compare.voltage = iDVBFrontend::voltageOff;
604                                         compare.steps = +4;
605                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
606
607                                         // voltage is changed... use DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS
608                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, vlt) );
609                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );
610                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +3) );
611
612                                         // voltage was disabled.. use DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS
613                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, vlt) );
614                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) );
615
616                                         sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS) );
617                                         if (needDiSEqCReset)
618                                         {
619                                                 eDVBDiseqcCommand diseqc;
620                                                 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
621                                                 diseqc.len = 3;
622                                                 diseqc.data[0] = 0xE0;
623                                                 diseqc.data[1] = 0;
624                                                 diseqc.data[2] = 0;
625                                                 // diseqc reset
626                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
627                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_DISEQC_RESET_CMD]) );
628                                                 diseqc.data[2] = 3;
629                                                 // diseqc peripherial powersupply on
630                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
631                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD]) );
632                                         }
633
634                                         for (int seq_repeat = 0; seq_repeat < (di_param.m_seq_repeat?2:1); ++seq_repeat)
635                                         {
636                                                 if ( send_mask & 4 )
637                                                 {
638                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
639                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_TONEBURST]) );
640                                                 }
641
642                                                 int loops=0;
643
644                                                 if ( send_mask & 1 )
645                                                         ++loops;
646                                                 if ( send_mask & 2 )
647                                                         ++loops;
648
649                                                 loops <<= diseqc_repeats;
650
651                                                 for ( int i = 0; i < loops;)  // fill commands...
652                                                 {
653                                                         eDVBDiseqcCommand diseqc;
654                                                         memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
655                                                         diseqc.len = 4;
656                                                         diseqc.data[0] = i ? 0xE1 : 0xE0;
657                                                         diseqc.data[1] = 0x10;
658                                                         if ( (send_mask & 2) && (di_param.m_command_order & 4) )
659                                                         {
660                                                                 diseqc.data[2] = 0x39;
661                                                                 diseqc.data[3] = ucsw;
662                                                         }
663                                                         else if ( send_mask & 1 )
664                                                         {
665                                                                 diseqc.data[2] = 0x38;
666                                                                 diseqc.data[3] = csw;
667                                                         }
668                                                         else  // no committed command confed.. so send uncommitted..
669                                                         {
670                                                                 diseqc.data[2] = 0x39;
671                                                                 diseqc.data[3] = ucsw;
672                                                         }
673                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
674
675                                                         i++;
676                                                         if ( i < loops )
677                                                         {
678                                                                 int cmd=0;
679                                                                 if (diseqc.data[2] == 0x38 && (send_mask & 2))
680                                                                         cmd=0x39;
681                                                                 else if (diseqc.data[2] == 0x39 && (send_mask & 1))
682                                                                         cmd=0x38;
683                                                                 int tmp = m_params[DELAY_BETWEEN_DISEQC_REPEATS];
684                                                                 if (cmd)
685                                                                 {
686                                                                         int delay = diseqc_repeats ? (tmp - 54) / 2 : tmp;  // standard says 100msek between two repeated commands
687                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay) );
688                                                                         diseqc.data[2]=cmd;
689                                                                         diseqc.data[3]=(cmd==0x38) ? csw : ucsw;
690                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
691                                                                         ++i;
692                                                                         if ( i < loops )
693                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay ) );
694                                                                         else
695                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
696                                                                 }
697                                                                 else  // delay 120msek when no command is in repeat gap
698                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, tmp) );
699                                                         }
700                                                         else
701                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
702                                                 }
703
704                                                 if ( send_mask & 8 )  // toneburst at end of sequence
705                                                 {
706                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
707                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_TONEBURST]) );
708                                                 }
709
710                                                 if (di_param.m_seq_repeat && seq_repeat == 0)
711                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_BEFORE_SEQUENCE_REPEAT]) );
712                                         }
713                                 }
714                         }
715                         else
716                         {
717                                 sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_SWITCHPARMS) );
718                                 csw = band;
719                         }
720
721                         sec_fe->setData(eDVBFrontend::NEW_CSW, csw);
722                         sec_fe->setData(eDVBFrontend::NEW_UCSW, ucsw);
723                         sec_fe->setData(eDVBFrontend::NEW_TONEBURST, di_param.m_toneburst_param);
724                         sec_fe->setData(eDVBFrontend::LINKABLE_CSW, csw);
725                         sec_fe->setData(eDVBFrontend::LINKABLE_UCSW, ucsw);
726                         sec_fe->setData(eDVBFrontend::LINKABLE_TONEBURST, di_param.m_toneburst_param);
727
728                         if(is_unicable)
729                         {
730                                 // check if voltage is disabled
731                                 eSecCommand::pair compare;
732                                 compare.steps = +3;
733                                 compare.voltage = iDVBFrontend::voltageOff;
734                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
735                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) );
736                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS] ) );
737
738                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) );
739                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
740                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );  // wait 20 ms after voltage change
741
742                                 eDVBDiseqcCommand diseqc;
743                                 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
744
745                                 long oldSatcr, oldPin, oldDiction;
746                                 frontend.getData(eDVBFrontend::SATCR, oldSatcr);
747                                 frontend.getData(eDVBFrontend::PIN, oldPin);
748                                 frontend.getData(eDVBFrontend::DICTION, oldDiction);
749
750                                 if((oldSatcr != -1) && (oldSatcr != lnb_param.SatCR_idx))
751                                 {
752                                         switch (oldDiction)
753                                         {
754                                                 case 1:
755                                                         if(oldPin < 1)
756                                                         {
757                                                                 diseqc.len = 4;
758                                                                 diseqc.data[0] = 0x70;
759                                                         }
760                                                         else
761                                                         {
762                                                                 diseqc.len = 5;
763                                                                 diseqc.data[0] = 0x71;
764                                                                 diseqc.data[4] = oldPin;
765                                                         }
766                                                         diseqc.data[1] = oldSatcr << 3;
767                                                         diseqc.data[2] = 0x00;
768                                                         diseqc.data[3] = 0x00;
769                                                         break;
770                                                 case 0:
771                                                 default:
772                                                         if(oldPin < 1)
773                                                         {
774                                                                 diseqc.len = 5;
775                                                                 diseqc.data[2] = 0x5A;
776                                                         }
777                                                         else
778                                                         {
779                                                                 diseqc.len = 6;
780                                                                 diseqc.data[2] = 0x5C;
781                                                                 diseqc.data[5] = oldPin;
782                                                         }
783                                                         diseqc.data[0] = 0xE0;
784                                                         diseqc.data[1] = 0x10;
785                                                         diseqc.data[3] = oldSatcr << 5;
786                                                         diseqc.data[4] = 0x00;
787                                                         break;
788                                         }
789                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
790                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
791                                         frontend.setData(eDVBFrontend::SATCR, -1);
792                                 }
793
794                                 frontend.setData(eDVBFrontend::DICTION, lnb_param.SatCR_format);
795 //TODO                          frontend.setData(eDVBFrontend::PIN, lnb_param.SatCR_pin);
796
797                                 long pin = 0; // hack
798
799                                 switch(lnb_param.SatCR_format)
800                                 {
801                                         case 1: //JESS
802                                                 if(pin < 1)
803                                                 {
804                                                         diseqc.len = 4;
805                                                         diseqc.data[0] = 0x70;
806                                                         diseqc.data[1] = lnb_param.UnicableTuningWord >> 16;
807                                                         diseqc.data[2] = lnb_param.UnicableTuningWord >> 8;
808                                                         diseqc.data[3] = lnb_param.UnicableTuningWord;
809                                                 }
810                                                 else
811                                                 {
812                                                         diseqc.len = 5;
813                                                         diseqc.data[0] = 0x71;
814                                                         diseqc.data[4] = pin;
815                                                 }
816                                                 diseqc.data[1] = lnb_param.UnicableTuningWord >> 16;
817                                                 diseqc.data[2] = lnb_param.UnicableTuningWord >> 8;
818                                                 diseqc.data[3] = lnb_param.UnicableTuningWord;
819                                                 break;
820                                         case 0: //DiSEqC
821                                         default:
822                                                 if(pin < 1)
823                                                 {
824                                                         diseqc.len = 5;
825                                                         diseqc.data[2] = 0x5A;
826                                                 }
827                                                 else
828                                                 {
829                                                         diseqc.len = 6;
830                                                         diseqc.data[2] = 0x5C;
831                                                         diseqc.data[5] = pin;
832                                                 }
833                                                 diseqc.data[0] = 0xE0;
834                                                 diseqc.data[1] = 0x10;
835                                                 diseqc.data[3] = lnb_param.UnicableTuningWord >> 8;
836                                                 diseqc.data[4] = lnb_param.UnicableTuningWord;
837                                 }
838                                 frontend.setData(eDVBFrontend::SATCR, lnb_param.SatCR_idx);
839
840                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
841                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
842                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) );
843                                 if ( RotorCmd != -1 && RotorCmd != lastRotorCmd && !rotor_param.m_inputpower_parameters.m_use)
844                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD]) );  // wait 150msec after voltage change
845                         }
846
847                         eDebugNoSimulate("RotorCmd %02x, lastRotorCmd %02lx", RotorCmd, lastRotorCmd);
848                         if ( RotorCmd != -1 && RotorCmd != lastRotorCmd )
849                         {
850                                 int mrt = m_params[MOTOR_RUNNING_TIMEOUT]; // in seconds!
851                                 eSecCommand::pair compare;
852                                 if (!send_mask && !is_unicable)
853                                 {
854                                         compare.steps = +3;
855                                         compare.tone = iDVBFrontend::toneOff;
856                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
857                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
858                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE_DISABLE_BEFORE_DISEQC]) );
859
860                                         compare.voltage = iDVBFrontend::voltageOff;
861                                         compare.steps = +4;
862                                         // the next is a check if voltage is switched off.. then we first set a voltage :)
863                                         // else we set voltage after all diseqc stuff..
864                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
865
866                                         if (rotor_param.m_inputpower_parameters.m_use)
867                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) ); // set 18V for measure input power
868                                         else
869                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) ); // in normal mode start turning with 13V
870
871                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_MOTOR_CMD]) ); // wait 750ms when voltage was disabled
872                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +9) );  // no need to send stop rotor cmd and recheck voltage
873                                 }
874                                 else
875                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_BETWEEN_SWITCH_AND_MOTOR_CMD]) ); // wait 700ms when diseqc changed
876
877                                 eDVBDiseqcCommand diseqc;
878                                 memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
879                                 diseqc.len = 3;
880                                 diseqc.data[0] = 0xE0;
881                                 diseqc.data[1] = 0x31;  // positioner
882                                 diseqc.data[2] = 0x60;  // stop
883                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_ROTORPOS_VALID_GOTO, +5) );
884                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
885                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
886                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
887                                 // wait 150msec after send rotor stop cmd
888                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_MOTOR_STOP_CMD]) );
889
890                                 diseqc.data[0] = 0xE0;
891                                 diseqc.data[1] = 0x31;          // positioner
892                                 if ( useGotoXX )
893                                 {
894                                         diseqc.len = 5;
895                                         diseqc.data[2] = 0x6E;  // drive to angular position
896                                         diseqc.data[3] = ((RotorCmd & 0xFF00) / 0x100);
897                                         diseqc.data[4] = RotorCmd & 0xFF;
898                                 }
899                                 else
900                                 {
901                                         diseqc.len = 4;
902                                         diseqc.data[2] = 0x6B;  // goto stored sat position
903                                         diseqc.data[3] = RotorCmd;
904                                         diseqc.data[4] = 0x00;
905                                 }
906
907                         // use measure rotor input power to detect motor state
908                                 if ( rotor_param.m_inputpower_parameters.m_use)
909                                 {
910                                         bool turn_fast = need_turn_fast(rotor_param.m_inputpower_parameters.m_turning_speed) && !is_unicable;
911                                         eSecCommand::rotor cmd;
912                                         eSecCommand::pair compare;
913                                         if (turn_fast)
914                                                 compare.voltage = VOLTAGE(18);
915                                         else
916                                                 compare.voltage = VOLTAGE(13);
917                                         compare.steps = +3;
918                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
919                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, compare.voltage) );
920                         // measure idle power values
921                                         compare.steps = -2;
922                                         if (turn_fast) {
923                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER]) );  // wait 150msec after voltage change
924                                                 sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 1) );
925                                                 compare.val = 1;
926                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO, compare) );
927                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) );
928                                         }
929                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER]) );  // wait 150msec before measure
930                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 0) );
931                                         compare.val = 0;
932                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO, compare) );
933                         ////////////////////////////
934                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_DISEQC_RETRYS, m_params[MOTOR_COMMAND_RETRIES]) );  // 2 retries
935                                         sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_ROTORPARMS) );
936                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
937                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 40) );  // 2 seconds rotor start timout
938                         // rotor start loop
939                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // 50msec delay
940                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
941                                         cmd.direction=1;  // check for running rotor
942                                         cmd.deltaA=rotor_param.m_inputpower_parameters.m_delta;
943                                         cmd.steps=+5;
944                                         cmd.okcount=0;
945                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );  // check if rotor has started
946                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +2 ) );  // timeout .. we assume now the rotor is already at the correct position
947                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // goto loop start
948                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO, turn_fast ? 10 : 9 ) );  // timeout .. we assume now the rotor is already at the correct position 
949                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -8) );  // goto loop start
950                         ////////////////////
951                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_MOVING) );
952                                         if (turn_fast)
953                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) );
954                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, mrt*20) );  // mrt is in seconds... our SLEEP time is 50ms.. so * 20
955                         // rotor running loop
956                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
957                                         sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
958                                         cmd.direction=0;  // check for stopped rotor
959                                         cmd.steps=+3;
960                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );
961                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +2 ) );  // timeout ? this should never happen
962                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // running loop start
963                         /////////////////////
964                                         sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
965                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_STOPPED) );
966                                 }
967                         // use normal motor turning mode
968                                 else
969                                 {
970                                         if (curRotorPos != -1)
971                                         {
972                                                 mrt = abs(curRotorPos - sat.orbital_position);
973                                                 if (mrt > 1800)
974                                                         mrt = 3600 - mrt;
975                                                 if (mrt % 10)
976                                                         mrt += 10; // round a little bit
977                                                 mrt *= 2000;  // (we assume a very slow rotor with just 0.5 degree per second here)
978                                                 mrt /= 10000;
979                                                 mrt += 3; // a little bit overhead
980                                         }
981                                         doSetVoltageToneFrontend=false;
982                                         doSetFrontend=false;
983                                         eSecCommand::rotor cmd;
984                                         eSecCommand::pair compare;
985                                         compare.voltage = VOLTAGE(13);
986                                         compare.steps = +3;
987                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
988                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, compare.voltage) );
989                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD]) );  // wait 150msec after voltage change
990
991                                         sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_ROTORPARMS) );
992                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_MOVING) );
993                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
994                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 1000) ); // sleep one second before change voltage or tone
995
996                                         compare.voltage = voltage;
997                                         compare.steps = +3;
998                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // correct final voltage?
999                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 2000) );  // wait 2 second before set high voltage
1000                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
1001
1002                                         compare.tone = tone;
1003                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
1004                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
1005                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) );
1006                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 0) );
1007
1008                                         cmd.direction=1;  // check for running rotor
1009                                         cmd.deltaA=0;
1010                                         cmd.steps = +3;
1011                                         cmd.okcount=0;
1012                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, mrt*4) );  // mrt is in seconds... our SLEEP time is 250ms.. so * 4
1013                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );  // 250msec delay
1014                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TUNER_LOCKED_GOTO, cmd ) );
1015                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +5 ) );
1016                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -3) );  // goto loop start
1017                                         sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
1018                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_STOPPED) );
1019                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +4) );
1020                                         sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, tunetimeout) );
1021                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
1022                                         sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -5) );
1023                                         eDebug("set rotor timeout to %d seconds", mrt);
1024                                 }
1025                                 sec_fe->setData(eDVBFrontend::NEW_ROTOR_CMD, RotorCmd);
1026                                 sec_fe->setData(eDVBFrontend::NEW_ROTOR_POS, sat.orbital_position);
1027                         }
1028
1029                         if (doSetVoltageToneFrontend && !is_unicable)
1030                         {
1031                                 eSecCommand::pair compare;
1032                                 compare.voltage = voltage;
1033                                 compare.steps = +3;
1034                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
1035                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
1036                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_VOLTAGE_CHANGE]) );
1037                                 compare.tone = tone;
1038                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
1039                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
1040                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_CONT_TONE_CHANGE]) );
1041                         }
1042
1043                         sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_SWITCHPARMS) );
1044
1045                         if (doSetFrontend)
1046                         {
1047                                 sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT, tunetimeout) );
1048                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND, 1) );
1049                         }
1050
1051                         sec_sequence.push_front( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
1052                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 500) );
1053                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
1054
1055                         frontend.setSecSequence(sec_sequence);
1056
1057                         return 0;
1058                 }
1059         }
1060         eDebugNoSimulate("found no useable satellite configuration for %s freq %d%s %s on orbital position (%d)",
1061                 sat.system ? "DVB-S2" : "DVB-S",
1062                 sat.frequency,
1063                 sat.polarisation == eDVBFrontendParametersSatellite::Polarisation_Horizontal ? "H" :
1064                         eDVBFrontendParametersSatellite::Polarisation_Vertical ? "V" :
1065                         eDVBFrontendParametersSatellite::Polarisation_CircularLeft ? "CL" : "CR",
1066                 sat.modulation == eDVBFrontendParametersSatellite::Modulation_Auto ? "AUTO" :
1067                         eDVBFrontendParametersSatellite::Modulation_QPSK ? "QPSK" :
1068                         eDVBFrontendParametersSatellite::Modulation_8PSK ? "8PSK" : "QAM16",
1069                 sat.orbital_position );
1070         return -1;
1071 }
1072
1073 void eDVBSatelliteEquipmentControl::prepareTurnOffSatCR(iDVBFrontend &frontend)
1074 {
1075         long satcr, diction, pin;
1076         eSecCommandList sec_sequence;
1077
1078         // check if voltage is disabled
1079         eSecCommand::pair compare;
1080         compare.steps = +9;     //only close frontend
1081         compare.voltage = iDVBFrontend::voltageOff;
1082
1083         sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
1084         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
1085         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) );
1086
1087         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
1088         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
1089         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS]) );
1090
1091         eDVBDiseqcCommand diseqc;
1092         memset(diseqc.data, 0, MAX_DISEQC_LENGTH);
1093         frontend.getData(eDVBFrontend::SATCR, satcr);
1094         frontend.getData(eDVBFrontend::DICTION, diction);
1095         frontend.getData(eDVBFrontend::PIN, pin);
1096
1097         switch (diction)
1098         {
1099                 case 1:
1100                         if(pin < 1)
1101                         {
1102                                 diseqc.len = 4;
1103                                 diseqc.data[0] = 0x70;
1104                         }
1105                         else
1106                         {
1107                                 diseqc.len = 5;
1108                                 diseqc.data[0] = 0x71;
1109                                 diseqc.data[4] = pin;
1110                         }
1111                         diseqc.data[1] = satcr << 3;
1112                         diseqc.data[2] = 0x00;
1113                         diseqc.data[3] = 0x00;
1114                         break;
1115                 case 0:
1116                 default:
1117                         if(pin < 1)
1118                         {
1119                                 diseqc.len = 5;
1120                                 diseqc.data[2] = 0x5A;
1121                         }
1122                         else
1123                         {
1124                                 diseqc.len = 6;
1125                                 diseqc.data[2] = 0x5C;
1126                                 diseqc.data[5] = pin;
1127                         }
1128                         diseqc.data[0] = 0xE0;
1129                         diseqc.data[1] = 0x10;
1130                         diseqc.data[3] = satcr << 5;
1131                         diseqc.data[4] = 0x00;
1132                         break;
1133         }
1134         frontend.setData(eDVBFrontend::SATCR, -1);
1135
1136         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
1137         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
1138         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
1139         sec_sequence.push_back( eSecCommand(eSecCommand::DELAYED_CLOSE_FRONTEND) );
1140
1141         frontend.setSecSequence(sec_sequence);
1142 }
1143
1144 RESULT eDVBSatelliteEquipmentControl::clear()
1145 {
1146         eSecDebug("eDVBSatelliteEquipmentControl::clear()");
1147         for (int i=0; i <= m_lnbidx; ++i)
1148         {
1149                 m_lnbs[i].m_satellites.clear();
1150                 m_lnbs[i].m_slot_mask = 0;
1151                 m_lnbs[i].m_prio = -1; // auto
1152         }
1153         m_lnbidx=-1;
1154
1155         m_not_linked_slot_mask=0;
1156
1157         //reset some tuner configuration
1158         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
1159         {
1160                 it->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, -1);
1161                 it->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, -1);
1162                 it->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, -1);
1163                 it->m_frontend->setData(eDVBFrontend::ROTOR_POS, -1);
1164                 it->m_frontend->setData(eDVBFrontend::ROTOR_CMD, -1);
1165                 it->m_frontend->setData(eDVBFrontend::SATCR, -1);
1166
1167                 if (it->m_frontend->is_FBCTuner())
1168                 {
1169                         eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
1170                         if (fbcmng)
1171                                 fbcmng->setDefaultFBCID(*it);
1172                 }
1173         }
1174
1175         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_simulate_frontends.begin()); it != m_avail_simulate_frontends.end(); ++it)
1176         {
1177                 it->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, -1);
1178                 it->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, -1);
1179                 it->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, -1);
1180                 it->m_frontend->setData(eDVBFrontend::ROTOR_POS, -1);
1181                 it->m_frontend->setData(eDVBFrontend::ROTOR_CMD, -1);
1182                 it->m_frontend->setData(eDVBFrontend::SATCR, -1);
1183         }
1184
1185         return 0;
1186 }
1187
1188 /* LNB Specific Parameters */
1189 RESULT eDVBSatelliteEquipmentControl::addLNB()
1190 {
1191         if ( (m_lnbidx+1) < (int)(sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters)))
1192                 m_curSat=m_lnbs[++m_lnbidx].m_satellites.end();
1193         else
1194         {
1195                 eDebug("no more LNB free... cnt is %d", m_lnbidx);
1196                 return -ENOSPC;
1197         }
1198         eSecDebug("eDVBSatelliteEquipmentControl::addLNB(%d)", m_lnbidx);
1199         return 0;
1200 }
1201
1202 RESULT eDVBSatelliteEquipmentControl::setLNBSlotMask(int slotmask)
1203 {
1204         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSlotMask(%d)", slotmask);
1205         if ( currentLNBValid() )
1206                 m_lnbs[m_lnbidx].m_slot_mask = slotmask;
1207         else
1208                 return -ENOENT;
1209         return 0;
1210 }
1211
1212 RESULT eDVBSatelliteEquipmentControl::setLNBLOFL(int lofl)
1213 {
1214         eSecDebug("eDVBSatelliteEquipmentControl::setLNBLOFL(%d)", lofl);
1215         if ( currentLNBValid() )
1216                 m_lnbs[m_lnbidx].m_lof_lo = lofl;
1217         else
1218                 return -ENOENT;
1219         return 0;
1220 }
1221
1222 RESULT eDVBSatelliteEquipmentControl::setLNBLOFH(int lofh)
1223 {
1224         eSecDebug("eDVBSatelliteEquipmentControl::setLNBLOFH(%d)", lofh);
1225         if ( currentLNBValid() )
1226                 m_lnbs[m_lnbidx].m_lof_hi = lofh;
1227         else
1228                 return -ENOENT;
1229         return 0;
1230 }
1231
1232 RESULT eDVBSatelliteEquipmentControl::setLNBThreshold(int threshold)
1233 {
1234         eSecDebug("eDVBSatelliteEquipmentControl::setLNBThreshold(%d)", threshold);
1235         if ( currentLNBValid() )
1236                 m_lnbs[m_lnbidx].m_lof_threshold = threshold;
1237         else
1238                 return -ENOENT;
1239         return 0;
1240 }
1241
1242 RESULT eDVBSatelliteEquipmentControl::setLNBIncreasedVoltage(bool onoff)
1243 {
1244         eSecDebug("eDVBSatelliteEquipmentControl::setLNBIncreasedVoltage(%d)", onoff);
1245         if ( currentLNBValid() )
1246                 m_lnbs[m_lnbidx].m_increased_voltage = onoff;
1247         else
1248                 return -ENOENT;
1249         return 0;
1250 }
1251
1252 RESULT eDVBSatelliteEquipmentControl::setLNBPrio(int prio)
1253 {
1254         eSecDebug("eDVBSatelliteEquipmentControl::setLNBPrio(%d)", prio);
1255         if ( currentLNBValid() )
1256                 m_lnbs[m_lnbidx].m_prio = prio;
1257         else
1258                 return -ENOENT;
1259         return 0;
1260 }
1261
1262 RESULT eDVBSatelliteEquipmentControl::setLNBNum(int LNBNum)
1263 {
1264         eSecDebug("eDVBSatelliteEquipmentControl::setLNBNum(%d)", LNBNum);
1265         if(!((LNBNum >= 1) && (LNBNum <= MAX_LNBNUM)))
1266                 return -EPERM;
1267         if ( currentLNBValid() )
1268                 m_lnbs[m_lnbidx].LNBNum = LNBNum;
1269         else
1270                 return -ENOENT;
1271         return 0;
1272 }
1273
1274 /* DiSEqC Specific Parameters */
1275 RESULT eDVBSatelliteEquipmentControl::setDiSEqCMode(int diseqcmode)
1276 {
1277         eSecDebug("eDVBSatelliteEquipmentControl::setDiSEqcMode(%d)", diseqcmode);
1278         if ( currentLNBValid() )
1279                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_diseqc_mode = (eDVBSatelliteDiseqcParameters::t_diseqc_mode)diseqcmode;
1280         else
1281                 return -ENOENT;
1282         return 0;
1283 }
1284
1285 RESULT eDVBSatelliteEquipmentControl::setToneburst(int toneburst)
1286 {
1287         eSecDebug("eDVBSatelliteEquipmentControl::setToneburst(%d)", toneburst);
1288         if ( currentLNBValid() )
1289                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_toneburst_param = (eDVBSatelliteDiseqcParameters::t_toneburst_param)toneburst;
1290         else
1291                 return -ENOENT;
1292         return 0;
1293 }
1294
1295 RESULT eDVBSatelliteEquipmentControl::setRepeats(int repeats)
1296 {
1297         eSecDebug("eDVBSatelliteEquipmentControl::setRepeats(%d)", repeats);
1298         if ( currentLNBValid() )
1299                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_repeats=repeats;
1300         else
1301                 return -ENOENT;
1302         return 0;
1303 }
1304
1305 RESULT eDVBSatelliteEquipmentControl::setCommittedCommand(int command)
1306 {
1307         eSecDebug("eDVBSatelliteEquipmentControl::setCommittedCommand(%d)", command);
1308         if ( currentLNBValid() )
1309                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_committed_cmd=command;
1310         else
1311                 return -ENOENT;
1312         return 0;
1313 }
1314
1315 RESULT eDVBSatelliteEquipmentControl::setUncommittedCommand(int command)
1316 {
1317         eSecDebug("eDVBSatelliteEquipmentControl::setUncommittedCommand(%d)", command);
1318         if ( currentLNBValid() )
1319                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_uncommitted_cmd = command;
1320         else
1321                 return -ENOENT;
1322         return 0;
1323 }
1324
1325 RESULT eDVBSatelliteEquipmentControl::setCommandOrder(int order)
1326 {
1327         eSecDebug("eDVBSatelliteEquipmentControl::setCommandOrder(%d)", order);
1328         if ( currentLNBValid() )
1329                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_command_order=order;
1330         else
1331                 return -ENOENT;
1332         return 0;
1333 }
1334
1335 RESULT eDVBSatelliteEquipmentControl::setFastDiSEqC(bool onoff)
1336 {
1337         eSecDebug("eDVBSatelliteEquipmentControl::setFastDiSEqc(%d)", onoff);
1338         if ( currentLNBValid() )
1339                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_use_fast=onoff;
1340         else
1341                 return -ENOENT;
1342         return 0;
1343 }
1344
1345 RESULT eDVBSatelliteEquipmentControl::setSeqRepeat(bool onoff)
1346 {
1347         eSecDebug("eDVBSatelliteEquipmentControl::setSeqRepeat(%d)", onoff);
1348         if ( currentLNBValid() )
1349                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_seq_repeat = onoff;
1350         else
1351                 return -ENOENT;
1352         return 0;
1353 }
1354
1355 /* Rotor Specific Parameters */
1356 RESULT eDVBSatelliteEquipmentControl::setLongitude(float longitude)
1357 {
1358         eSecDebug("eDVBSatelliteEquipmentControl::setLongitude(%f)", longitude);
1359         if ( currentLNBValid() )
1360                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_longitude=longitude;
1361         else
1362                 return -ENOENT;
1363         return 0;
1364 }
1365
1366 RESULT eDVBSatelliteEquipmentControl::setLatitude(float latitude)
1367 {
1368         eSecDebug("eDVBSatelliteEquipmentControl::setLatitude(%f)", latitude);
1369         if ( currentLNBValid() )
1370                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_latitude=latitude;
1371         else
1372                 return -ENOENT;
1373         return 0;
1374 }
1375
1376 RESULT eDVBSatelliteEquipmentControl::setLoDirection(int direction)
1377 {
1378         eSecDebug("eDVBSatelliteEquipmentControl::setLoDirection(%d)", direction);
1379         if ( currentLNBValid() )
1380                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_lo_direction=direction;
1381         else
1382                 return -ENOENT;
1383         return 0;
1384 }
1385
1386 RESULT eDVBSatelliteEquipmentControl::setLaDirection(int direction)
1387 {
1388         eSecDebug("eDVBSatelliteEquipmentControl::setLaDirection(%d)", direction);
1389         if ( currentLNBValid() )
1390                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_la_direction=direction;
1391         else
1392                 return -ENOENT;
1393         return 0;
1394 }
1395
1396 RESULT eDVBSatelliteEquipmentControl::setUseInputpower(bool onoff)
1397 {
1398         eSecDebug("eDVBSatelliteEquipmentControl::setUseInputpower(%d)", onoff);
1399         if ( currentLNBValid() )
1400                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_use=onoff;
1401         else
1402                 return -ENOENT;
1403         return 0;
1404 }
1405
1406 RESULT eDVBSatelliteEquipmentControl::setInputpowerDelta(int delta)
1407 {
1408         eSecDebug("eDVBSatelliteEquipmentControl::setInputpowerDelta(%d)", delta);
1409         if ( currentLNBValid() )
1410                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_delta=delta;
1411         else
1412                 return -ENOENT;
1413         return 0;
1414 }
1415
1416 /* Unicable Specific Parameters */
1417 RESULT eDVBSatelliteEquipmentControl::setLNBSatCRformat(int SatCR_format)
1418 {
1419         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCRformat(%d)", SatCR_format);
1420         if(!((SatCR_format >-1) && (SatCR_format < 2)))
1421                 return -EPERM;
1422         if ( currentLNBValid() )
1423                 m_lnbs[m_lnbidx].SatCR_format = SatCR_format;
1424         else
1425                 return -ENOENT;
1426         return 0;
1427 }
1428
1429 RESULT eDVBSatelliteEquipmentControl::setLNBSatCR(int SatCR_idx)
1430 {
1431         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCR(%d)", SatCR_idx);
1432         if(!((SatCR_idx >=-1) && (SatCR_idx < MAX_SATCR)))
1433                 return -EPERM;
1434         if ( currentLNBValid() )
1435                 m_lnbs[m_lnbidx].SatCR_idx = SatCR_idx;
1436         else
1437                 return -ENOENT;
1438         return 0;
1439 }
1440
1441 RESULT eDVBSatelliteEquipmentControl::setLNBSatCRvco(int SatCRvco)
1442 {
1443         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCRvco(%d)", SatCRvco);
1444         if(!((SatCRvco >= 950*1000) && (SatCRvco <= 2150*1000)))
1445                 return -EPERM;
1446         if(!((m_lnbs[m_lnbidx].SatCR_idx >= 0) && (m_lnbs[m_lnbidx].SatCR_idx < MAX_SATCR)))
1447                 return -ENOENT;
1448         if ( currentLNBValid() )
1449                 m_lnbs[m_lnbidx].SatCRvco = SatCRvco;
1450         else
1451                 return -ENOENT;
1452         return 0;
1453 }
1454
1455 RESULT eDVBSatelliteEquipmentControl::setLNBSatCRpositions(int SatCR_positions)
1456 {
1457         eSecDebug("eDVBSatelliteEquipmentControl::setLNBSatCRpositions(%d)", SatCR_positions);
1458         if(SatCR_positions < 1 || SatCR_positions > 2)
1459                 return -EPERM;
1460         if ( currentLNBValid() )
1461                 m_lnbs[m_lnbidx].SatCR_positions = SatCR_positions;
1462         else
1463                 return -ENOENT;
1464         return 0;
1465 }
1466
1467 RESULT eDVBSatelliteEquipmentControl::getLNBSatCRpositions()
1468 {
1469         if ( currentLNBValid() )
1470                 return m_lnbs[m_lnbidx].SatCR_positions;
1471         return -ENOENT;
1472 }
1473
1474 RESULT eDVBSatelliteEquipmentControl::getLNBSatCRformat()
1475 {
1476         if ( currentLNBValid() )
1477                 return m_lnbs[m_lnbidx].SatCR_format;
1478         return -ENOENT;
1479 }
1480
1481 RESULT eDVBSatelliteEquipmentControl::getLNBSatCR()
1482 {
1483         if ( currentLNBValid() )
1484                 return m_lnbs[m_lnbidx].SatCR_idx;
1485         return -ENOENT;
1486 }
1487
1488 RESULT eDVBSatelliteEquipmentControl::getLNBSatCRvco()
1489 {
1490         if ( currentLNBValid() )
1491                 return m_lnbs[m_lnbidx].SatCRvco;
1492         return -ENOENT;
1493 }
1494
1495 /* Satellite Specific Parameters */
1496 RESULT eDVBSatelliteEquipmentControl::addSatellite(int orbital_position)
1497 {
1498         eSecDebug("eDVBSatelliteEquipmentControl::addSatellite(%d)", orbital_position);
1499         if ( currentLNBValid() )
1500         {
1501                 std::map<int, eDVBSatelliteSwitchParameters>::iterator it =
1502                         m_lnbs[m_lnbidx].m_satellites.find(orbital_position);
1503                 if ( it == m_lnbs[m_lnbidx].m_satellites.end() )
1504                 {
1505                         std::pair<std::map<int, eDVBSatelliteSwitchParameters>::iterator, bool > ret =
1506                                 m_lnbs[m_lnbidx].m_satellites.insert(
1507                                         std::pair<int, eDVBSatelliteSwitchParameters>(orbital_position, eDVBSatelliteSwitchParameters())
1508                                 );
1509                         if ( ret.second )
1510                                 m_curSat = ret.first;
1511                         else
1512                                 return -ENOMEM;
1513                 }
1514                 else
1515                         return -EEXIST;
1516         }
1517         else
1518                 return -ENOENT;
1519         return 0;
1520 }
1521
1522 RESULT eDVBSatelliteEquipmentControl::setVoltageMode(int mode)
1523 {
1524         eSecDebug("eDVBSatelliteEquipmentControl::setVoltageMode(%d)", mode);
1525         if ( currentLNBValid() && m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1526                 m_curSat->second.m_voltage_mode = (eDVBSatelliteSwitchParameters::t_voltage_mode)mode;
1527         else
1528                 return -ENOENT;
1529         return 0;
1530
1531 }
1532
1533 RESULT eDVBSatelliteEquipmentControl::setToneMode(int mode)
1534 {
1535         eSecDebug("eDVBSatelliteEquipmentControl::setToneMode(%d)", mode);
1536         if ( currentLNBValid() )
1537         {
1538                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1539                         m_curSat->second.m_22khz_signal = (eDVBSatelliteSwitchParameters::t_22khz_signal)mode;
1540                 else
1541                         return -EPERM;
1542         }
1543         else
1544                 return -ENOENT;
1545         return 0;
1546 }
1547
1548 RESULT eDVBSatelliteEquipmentControl::setRotorPosNum(int rotor_pos_num)
1549 {
1550         eSecDebug("eDVBSatelliteEquipmentControl::setRotorPosNum(%d)", rotor_pos_num);
1551         if ( currentLNBValid() )
1552         {
1553                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1554                         m_curSat->second.m_rotorPosNum=rotor_pos_num;
1555                 else
1556                         return -EPERM;
1557         }
1558         else
1559                 return -ENOENT;
1560         return 0;
1561 }
1562
1563 RESULT eDVBSatelliteEquipmentControl::setRotorTurningSpeed(int speed)
1564 {
1565         eSecDebug("eDVBSatelliteEquipmentControl::setRotorTurningSpeed(%d)", speed);
1566         if ( currentLNBValid() )
1567                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_turning_speed = speed;
1568         else
1569                 return -ENOENT;
1570         return 0;
1571 }
1572
1573 struct sat_compare
1574 {
1575         int orb_pos, lofl, lofh;
1576         sat_compare(int o, int lofl, int lofh)
1577                 :orb_pos(o), lofl(lofl), lofh(lofh)
1578         {}
1579         sat_compare(const sat_compare &x)
1580                 :orb_pos(x.orb_pos), lofl(x.lofl), lofh(x.lofh)
1581         {}
1582         bool operator < (const sat_compare & cmp) const
1583         {
1584                 if (orb_pos == cmp.orb_pos)
1585                 {
1586                         if ( abs(lofl-cmp.lofl) < 200000 )
1587                         {
1588                                 if (abs(lofh-cmp.lofh) < 200000)
1589                                         return false;
1590                                 return lofh<cmp.lofh;
1591                         }
1592                         return lofl<cmp.lofl;
1593                 }
1594                 return orb_pos < cmp.orb_pos;
1595         }
1596 };
1597
1598 RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
1599 {
1600         eSecDebug("eDVBSatelliteEquipmentControl::setTunerLinked(%d, %d)", tu1, tu2);
1601         if (tu1 != tu2)
1602         {
1603                 eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
1604                 eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin());
1605                 for (; it != m_avail_frontends.end(); ++it)
1606                 {
1607                         if (it->m_frontend->getSlotID() == tu1)
1608                                 p1 = *it;
1609                         else if (it->m_frontend->getSlotID() == tu2)
1610                                 p2 = *it;
1611                 }
1612                 if (p1 && p2)
1613                 {
1614                         char c;
1615                         p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
1616                         p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
1617
1618                         eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
1619                         if (p1->m_frontend->is_FBCTuner() && fbcmng)
1620                         {
1621                                 fbcmng->updateFBCID(p1, p2);
1622                         }
1623                 }
1624
1625                 p1=p2=NULL;
1626                 it=m_avail_simulate_frontends.begin();
1627                 for (; it != m_avail_simulate_frontends.end(); ++it)
1628                 {
1629                         if (it->m_frontend->getSlotID() == tu1)
1630                                 p1 = *it;
1631                         else if (it->m_frontend->getSlotID() == tu2)
1632                                 p2 = *it;
1633                 }
1634                 if (p1 && p2)
1635                 {
1636                         p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
1637                         p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
1638                         return 0;
1639                 }
1640         }
1641         return -1;
1642 }
1643
1644 RESULT eDVBSatelliteEquipmentControl::setTunerDepends(int tu1, int tu2)
1645 {
1646         eSecDebug("eDVBSatelliteEquipmentControl::setTunerDepends(%d, %d)", tu1, tu2);
1647         if (tu1 == tu2)
1648                 return -1;
1649
1650         eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
1651
1652         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
1653         {
1654                 if (it->m_frontend->getSlotID() == tu1)
1655                         p1 = *it;
1656                 else if (it->m_frontend->getSlotID() == tu2)
1657                         p2 = *it;
1658         }
1659         if (p1 && p2)
1660         {
1661                 p1->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p2);
1662                 p2->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p1);
1663         }
1664
1665         p1=p2=NULL;
1666         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_simulate_frontends.begin()); it != m_avail_simulate_frontends.end(); ++it)
1667         {
1668                 if (it->m_frontend->getSlotID() == tu1)
1669                         p1 = *it;
1670                 else if (it->m_frontend->getSlotID() == tu2)
1671                         p2 = *it;
1672         }
1673         if (p1 && p2)
1674         {
1675                 p1->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p2);
1676                 p2->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (long)p1);
1677                 return 0;
1678         }
1679
1680         return -1;
1681 }
1682
1683 void eDVBSatelliteEquipmentControl::setSlotNotLinked(int slot_no)
1684 {
1685         eSecDebug("eDVBSatelliteEquipmentControl::setSlotNotLinked(%d)", slot_no);
1686         m_not_linked_slot_mask |= (1 << slot_no);
1687 }
1688
1689 bool eDVBSatelliteEquipmentControl::isRotorMoving()
1690 {
1691         return m_rotorMoving;
1692 }
1693
1694 void eDVBSatelliteEquipmentControl::setRotorMoving(int slot_no, bool b)
1695 {
1696         if (b)
1697                 m_rotorMoving |= (1 << slot_no);
1698         else
1699                 m_rotorMoving &= ~(1 << slot_no);
1700 }