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