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