add preroll to iTSMpegDecoder
[enigma2.git] / lib / dvb / sec.cpp
1 #include <lib/dvb/dvb.h>
2 #include <lib/dvb/sec.h>
3 #include <lib/dvb/rotor_calc.h>
4
5 #include <set>
6
7 #if HAVE_DVB_API_VERSION < 3
8 #define FREQUENCY Frequency
9 #else
10 #define FREQUENCY frequency
11 #endif
12 #include <lib/base/eerror.h>
13
14 DEFINE_REF(eDVBSatelliteEquipmentControl);
15
16 eDVBSatelliteEquipmentControl *eDVBSatelliteEquipmentControl::instance;
17
18 int eDVBSatelliteEquipmentControl::m_params[MAX_PARAMS];
19 /*
20    defaults are set in python lib/python/Components/NimManager.py
21    in InitSecParams function via setParam call
22 */
23
24 void eDVBSatelliteEquipmentControl::setParam(int param, int value)
25 {
26         if (param >= 0 && param < MAX_PARAMS)
27                 m_params[param]=value;
28 }
29
30 eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl(eSmartPtrList<eDVBRegisteredFrontend> &avail_frontends)
31         :m_lnbidx(-1), m_curSat(m_lnbs[0].m_satellites.end()), m_avail_frontends(avail_frontends), m_rotorMoving(false)
32 {
33         if (!instance)
34                 instance = this;
35
36         clear();
37
38 // ASTRA
39         addLNB();
40         setLNBTunerMask(3);
41         setLNBLOFL(9750000);
42         setLNBThreshold(11700000);
43         setLNBLOFH(10607000);
44         setDiSEqCMode(eDVBSatelliteDiseqcParameters::V1_0);
45         setToneburst(eDVBSatelliteDiseqcParameters::NO);
46         setRepeats(0);
47         setCommittedCommand(eDVBSatelliteDiseqcParameters::BB);
48         setCommandOrder(0); // committed, toneburst
49         setFastDiSEqC(true);
50         setSeqRepeat(false);
51         addSatellite(192);
52         setVoltageMode(eDVBSatelliteSwitchParameters::HV);
53         setToneMode(eDVBSatelliteSwitchParameters::HILO);
54
55 // Hotbird
56         addLNB();
57         setLNBTunerMask(3);
58         setLNBLOFL(9750000);
59         setLNBThreshold(11700000);
60         setLNBLOFH(10600000);
61         setDiSEqCMode(eDVBSatelliteDiseqcParameters::V1_0);
62         setToneburst(eDVBSatelliteDiseqcParameters::NO);
63         setRepeats(0);
64         setCommittedCommand(eDVBSatelliteDiseqcParameters::AB);
65         setCommandOrder(0); // committed, toneburst
66         setFastDiSEqC(true);
67         setSeqRepeat(false);
68         addSatellite(130);
69         setVoltageMode(eDVBSatelliteSwitchParameters::HV);
70         setToneMode(eDVBSatelliteSwitchParameters::HILO);
71
72 // Rotor
73         addLNB();
74         setLNBTunerMask(3);
75         setLNBLOFL(9750000);
76         setLNBThreshold(11700000);
77         setLNBLOFH(10600000);
78         setDiSEqCMode(eDVBSatelliteDiseqcParameters::V1_2);
79         setToneburst(eDVBSatelliteDiseqcParameters::NO);
80         setRepeats(0);
81         setCommittedCommand(eDVBSatelliteDiseqcParameters::AA);
82         setCommandOrder(0); // committed, toneburst
83         setFastDiSEqC(true);
84         setSeqRepeat(false);
85         setLaDirection(eDVBSatelliteRotorParameters::NORTH);
86         setLoDirection(eDVBSatelliteRotorParameters::EAST);
87         setLatitude(51.017);
88         setLongitude(8.683);
89         setUseInputpower(true);
90         setInputpowerDelta(50);
91
92         addSatellite(235);
93         setVoltageMode(eDVBSatelliteSwitchParameters::HV);
94         setToneMode(eDVBSatelliteSwitchParameters::HILO);
95         setRotorPosNum(0);
96
97         addSatellite(284);
98         setVoltageMode(eDVBSatelliteSwitchParameters::HV);
99         setToneMode(eDVBSatelliteSwitchParameters::HILO);
100         setRotorPosNum(0);
101
102         addSatellite(420);
103         setVoltageMode(eDVBSatelliteSwitchParameters::HV);
104         setToneMode(eDVBSatelliteSwitchParameters::HILO);
105         setRotorPosNum(1); // stored pos 1
106 }
107
108 static void checkLinkedParams(int direction, int &linked_ptr, int &ret, const eDVBFrontendParametersSatellite &sat, int csw, int ucsw, int toneburst, bool diseqc, bool rotor)
109 {
110         eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_ptr;
111         int oRotorPos = -1;
112         linked_fe->m_frontend->getData(eDVBFrontend::ROTOR_POS, oRotorPos);
113         if (linked_fe->m_inuse)
114         {
115                 int ocsw = -1,
116                         oucsw = -1,
117                         oToneburst = -1;
118                 linked_fe->m_frontend->getData(eDVBFrontend::CSW, ocsw);
119                 linked_fe->m_frontend->getData(eDVBFrontend::UCSW, oucsw);
120                 linked_fe->m_frontend->getData(eDVBFrontend::TONEBURST, oToneburst);
121 #if 0
122                 eDebug("compare csw %02x == lcsw %02x",
123                         csw, ocsw);
124                 if ( diseqc )
125                         eDebug("compare ucsw %02x == lucsw %02x\ncompare toneburst %02x == oToneburst %02x",
126                                 ucsw, oucsw, toneburst, oToneburst);
127                 if ( rotor )
128                         eDebug("compare pos %d == current pos %d",
129                                 sat.orbital_position, oRotorPos);
130 #endif
131                 if ( (csw != ocsw) ||
132                         ( diseqc && (ucsw != oucsw || toneburst != oToneburst) ) ||
133                         ( rotor && oRotorPos != sat.orbital_position ) )
134                 {
135 //                      eDebug("can not tune this transponder with linked tuner in use!!");
136                         ret=0;
137                 }
138 //              else
139 //                      eDebug("OK .. can tune this transponder with linked tuner in use :)");
140         }
141         else if (rotor && oRotorPos != -1)
142         {
143                 ret -= abs(oRotorPos-sat.orbital_position);
144 //              eDebug("decrement rotor pos for linked tuner!!");
145         }
146         linked_fe->m_frontend->getData(direction, linked_ptr);
147 }
148
149 int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite &sat, iDVBFrontend *fe, int frontend_id )
150 {
151         int ret=0, satcount=0;
152
153         for (int idx=0; idx <= m_lnbidx; ++idx )
154         {
155                 bool rotor=false;
156                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
157                 if ( lnb_param.tuner_mask & frontend_id ) // lnb for correct tuner?
158                 {
159                         eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
160
161                         satcount += lnb_param.m_satellites.size();
162
163                         std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
164                                 lnb_param.m_satellites.find(sat.orbital_position);
165                         if ( sit != lnb_param.m_satellites.end())
166                         {
167                                 int band=0,
168                                         linked_prev_ptr=-1,
169                                         linked_next_ptr=-1,
170                                         satpos_depends_ptr=-1,
171                                         csw = di_param.m_committed_cmd,
172                                         ucsw = di_param.m_uncommitted_cmd,
173                                         toneburst = di_param.m_toneburst_param,
174                                         curRotorPos;
175
176                                 fe->getData(eDVBFrontend::ROTOR_POS, curRotorPos);
177                                 fe->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
178                                 fe->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
179                                 fe->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, satpos_depends_ptr);
180
181                                 if ( sat.frequency > lnb_param.m_lof_threshold )
182                                         band |= 1;
183                                 if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation::Vertical))
184                                         band |= 2;
185
186                                 bool diseqc=false;
187
188                                 if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
189                                 {
190                                         diseqc=true;
191                                         if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
192                                                 csw = 0xF0 | (csw << 2);
193
194                                         if (di_param.m_committed_cmd <= eDVBSatelliteDiseqcParameters::SENDNO)
195                                                 csw |= band;
196
197                                         if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2 )  // ROTOR
198                                                 rotor = true;
199
200                                         ret=10000;
201                                         if (rotor && curRotorPos != -1)
202                                                 ret -= abs(curRotorPos-sat.orbital_position);
203                                 }
204                                 else
205                                 {
206                                         csw = band;
207                                         ret = 15000;
208                                 }
209
210                                 while (ret && linked_prev_ptr != -1)  // check for linked tuners..
211                                         checkLinkedParams(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr, ret, sat, csw, ucsw, toneburst, diseqc, rotor);
212
213                                 while (ret && linked_next_ptr != -1)  // check for linked tuners..
214                                         checkLinkedParams(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr, ret, sat, csw, ucsw, toneburst, diseqc, rotor);
215
216                                 if (ret)
217                                         if (satpos_depends_ptr != -1)
218                                         {
219                                                 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend*) satpos_depends_ptr;
220                                                 if ( satpos_depends_to_fe->m_inuse )
221                                                 {
222                                                         int oRotorPos = -1;
223                                                         satpos_depends_to_fe->m_frontend->getData(eDVBFrontend::ROTOR_POS, oRotorPos);
224                                                         if (!rotor || oRotorPos != sat.orbital_position)
225                                                         {
226 //                                                              eDebug("can not tune this transponder ... rotor on other tuner is positioned to %d", oRotorPos);
227                                                                 ret=0;
228                                                         }
229                                                 }
230 //                                              else
231 //                                                      eDebug("OK .. can tune this transponder satpos is correct :)");
232                                         }
233
234                                 if (ret)
235                                 {
236                                         int lof = sat.frequency > lnb_param.m_lof_threshold ?
237                                                 lnb_param.m_lof_hi : lnb_param.m_lof_lo;
238                                         int tuner_freq = abs(sat.frequency - lof);
239 //                                      eDebug("tuner freq %d", tuner_freq);
240                                         if (tuner_freq < 900000 || tuner_freq > 2200000)
241                                         {
242                                                 ret=0;
243 //                                              eDebug("Transponder not tuneable with this lnb... %d Khz out of tuner range",
244 //                                                      tuner_freq);
245                                         }
246                                 }
247                         }
248                 }
249         }
250         if (ret && satcount)
251                 ret -= (satcount-1);
252         return ret;
253 }
254
255 #define VOLTAGE(x) (lnb_param.m_increased_voltage ? iDVBFrontend::voltage##x##_5 : iDVBFrontend::voltage##x)
256
257 RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPARAMETERS &parm, const eDVBFrontendParametersSatellite &sat, int frontend_id)
258 {
259         bool linked=false;
260         bool depend_satpos_mode=false;
261
262         for (int idx=0; idx <= m_lnbidx; ++idx )
263         {
264                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
265                 if (!(lnb_param.tuner_mask & frontend_id)) // lnb for correct tuner?
266                         continue;
267                 eDVBSatelliteDiseqcParameters &di_param = lnb_param.m_diseqc_parameters;
268                 eDVBSatelliteRotorParameters &rotor_param = lnb_param.m_rotor_parameters;
269
270                 std::map<int, eDVBSatelliteSwitchParameters>::iterator sit =
271                         lnb_param.m_satellites.find(sat.orbital_position);
272                 if ( sit != lnb_param.m_satellites.end())
273                 {
274                         eDVBSatelliteSwitchParameters &sw_param = sit->second;
275                         bool doSetVoltageToneFrontend = true;
276                         bool doSetFrontend = true;
277                         int band=0,
278                                 linked_prev_ptr=-1, // linked tuner
279                                 linked_next_ptr=-1, // linked tuner
280                                 satpos_depends_ptr=-1,
281                                 voltage = iDVBFrontend::voltageOff,
282                                 tone = iDVBFrontend::toneOff,
283                                 csw = di_param.m_committed_cmd,
284                                 ucsw = di_param.m_uncommitted_cmd,
285                                 toneburst = di_param.m_toneburst_param,
286                                 lastcsw = -1,
287                                 lastucsw = -1,
288                                 lastToneburst = -1,
289                                 lastRotorCmd = -1,
290                                 curRotorPos = -1;
291
292                         frontend.getData(eDVBFrontend::CSW, lastcsw);
293                         frontend.getData(eDVBFrontend::UCSW, lastucsw);
294                         frontend.getData(eDVBFrontend::TONEBURST, lastToneburst);
295                         frontend.getData(eDVBFrontend::ROTOR_CMD, lastRotorCmd);
296                         frontend.getData(eDVBFrontend::ROTOR_POS, curRotorPos);
297                         frontend.getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
298                         frontend.getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
299                         frontend.getData(eDVBFrontend::SATPOS_DEPENDS_PTR, satpos_depends_ptr);
300
301                         while (linked_prev_ptr != -1)  // check for linked tuners..
302                         {
303                                 eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
304                                 if (linked_fe->m_inuse)
305                                 {
306                                         eDebug("[SEC] frontend is linked with another and the other one is in use.. so we dont do SEC!!");
307                                         linked=true;
308                                         break;
309                                 }
310                                 linked_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
311                         }
312
313                         if (!linked)
314                                 while (linked_next_ptr != -1)  // check for linked tuners..
315                                 {
316                                         eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
317                                         if (linked_fe->m_inuse)
318                                         {
319                                                 eDebug("[SEC] frontend is linked with another and the other one is in use.. so we dont do SEC!!");
320                                                 linked=true;
321                                                 break;
322                                         }
323                                         linked_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
324                                 }
325
326                         if (satpos_depends_ptr != -1)
327                         {
328                                 eDVBRegisteredFrontend *satpos_fe = (eDVBRegisteredFrontend*) satpos_depends_ptr;
329                                 if (satpos_fe->m_inuse)
330                                 {
331                                         if ( di_param.m_diseqc_mode != eDVBSatelliteDiseqcParameters::V1_2 )
332                                                 continue;
333                                         eDebug("[SEC] frontend is depending on satpos of other one.. so we dont turn rotor!!");
334                                         depend_satpos_mode=true;
335                                 }
336                         }
337
338                         if ( sat.frequency > lnb_param.m_lof_threshold )
339                                 band |= 1;
340
341                         if (band&1)
342                                 parm.FREQUENCY = sat.frequency - lnb_param.m_lof_hi;
343                         else
344                                 parm.FREQUENCY = sat.frequency - lnb_param.m_lof_lo;
345
346                         parm.FREQUENCY = abs(parm.FREQUENCY);
347
348                         frontend.setData(eDVBFrontend::FREQ_OFFSET, sat.frequency - parm.FREQUENCY);
349
350                         if (!(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation::Vertical))
351                                 band |= 2;
352
353                         if ( sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::_14V
354                                 || ( sat.polarisation & eDVBFrontendParametersSatellite::Polarisation::Vertical
355                                         && sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
356                                 voltage = VOLTAGE(13);
357                         else if ( sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::_18V
358                                 || ( !(sat.polarisation & eDVBFrontendParametersSatellite::Polarisation::Vertical)
359                                         && sw_param.m_voltage_mode == eDVBSatelliteSwitchParameters::HV )  )
360                                 voltage = VOLTAGE(18);
361                         if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::ON)
362                                 || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && (band&1) ) )
363                                 tone = iDVBFrontend::toneOn;
364                         else if ( (sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::OFF)
365                                 || ( sw_param.m_22khz_signal == eDVBSatelliteSwitchParameters::HILO && !(band&1) ) )
366                                 tone = iDVBFrontend::toneOff;
367
368                         eSecCommandList sec_sequence;
369
370                         if (di_param.m_diseqc_mode >= eDVBSatelliteDiseqcParameters::V1_0)
371                         {
372                                 if ( di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO )
373                                         csw = 0xF0 | (csw << 2);
374
375                                 if (di_param.m_committed_cmd <= eDVBSatelliteDiseqcParameters::SENDNO)
376                                         csw |= band;
377
378                                 bool send_csw =
379                                         (di_param.m_committed_cmd != eDVBSatelliteDiseqcParameters::SENDNO);
380                                 bool changed_csw = send_csw && csw != lastcsw;
381
382                                 bool send_ucsw =
383                                         (di_param.m_uncommitted_cmd && di_param.m_diseqc_mode > eDVBSatelliteDiseqcParameters::V1_0);
384                                 bool changed_ucsw = send_ucsw && ucsw != lastucsw;
385
386                                 bool send_burst =
387                                         (di_param.m_toneburst_param != eDVBSatelliteDiseqcParameters::NO);
388                                 bool changed_burst = send_burst && toneburst != lastToneburst;
389
390                                 int send_mask = 0; /*
391                                         1 must send csw
392                                         2 must send ucsw
393                                         4 send toneburst first
394                                         8 send toneburst at end */
395                                 if (changed_burst) // toneburst first and toneburst changed
396                                 {
397                                         if (di_param.m_command_order&1)
398                                         {
399                                                 send_mask |= 4;
400                                                 if ( send_csw )
401                                                         send_mask |= 1;
402                                                 if ( send_ucsw )
403                                                         send_mask |= 2;
404                                         }
405                                         else
406                                                 send_mask |= 8;
407                                 }
408                                 if (changed_ucsw)
409                                 {
410                                         send_mask |= 2;
411                                         if ((di_param.m_command_order&4) && send_csw)
412                                                 send_mask |= 1;
413                                         if (di_param.m_command_order==4 && send_burst)
414                                                 send_mask |= 8;
415                                 }
416                                 if (changed_csw) 
417                                 {
418                                         if ( di_param.m_use_fast
419                                                 && di_param.m_committed_cmd < eDVBSatelliteDiseqcParameters::SENDNO
420                                                 && (lastcsw & 0xF0)
421                                                 && ((csw / 4) == (lastcsw / 4)) )
422                                                 eDebug("dont send committed cmd (fast diseqc)");
423                                         else
424                                         {
425                                                 send_mask |= 1;
426                                                 if (!(di_param.m_command_order&4) && send_ucsw)
427                                                         send_mask |= 2;
428                                                 if (!(di_param.m_command_order&1) && send_burst)
429                                                         send_mask |= 8;
430                                         }
431                                 }
432
433 #if 0
434                                 eDebugNoNewLine("sendmask: ");
435                                 for (int i=3; i >= 0; --i)
436                                         if ( send_mask & (1<<i) )
437                                                 eDebugNoNewLine("1");
438                                         else
439                                                 eDebugNoNewLine("0");
440                                 eDebug("");
441 #endif
442
443                                 int RotorCmd=-1;
444                                 bool useGotoXX = false;
445                                 if ( di_param.m_diseqc_mode == eDVBSatelliteDiseqcParameters::V1_2
446                                         && !sat.no_rotor_command_on_tune )
447                                 {
448                                         if (depend_satpos_mode || linked)
449                                                 // in this both modes we dont really turn the rotor.... but in canTune we need the satpos
450                                                 frontend.setData(eDVBFrontend::ROTOR_POS, sat.orbital_position);
451                                         else
452                                         {
453                                                 if (sw_param.m_rotorPosNum) // we have stored rotor pos?
454                                                         RotorCmd=sw_param.m_rotorPosNum;
455                                                 else  // we must calc gotoxx cmd
456                                                 {
457                                                         eDebug("Entry for %d,%d? not in Rotor Table found... i try gotoXX?", sat.orbital_position / 10, sat.orbital_position % 10 );
458                                                         useGotoXX = true;
459
460                                                         double  SatLon = abs(sat.orbital_position)/10.00,
461                                                                         SiteLat = rotor_param.m_gotoxx_parameters.m_latitude,
462                                                                         SiteLon = rotor_param.m_gotoxx_parameters.m_longitude;
463
464                                                         if ( rotor_param.m_gotoxx_parameters.m_la_direction == eDVBSatelliteRotorParameters::SOUTH )
465                                                                 SiteLat = -SiteLat;
466
467                                                         if ( rotor_param.m_gotoxx_parameters.m_lo_direction == eDVBSatelliteRotorParameters::WEST )
468                                                                 SiteLon = 360 - SiteLon;
469
470                                                         eDebug("siteLatitude = %lf, siteLongitude = %lf, %lf degrees", SiteLat, SiteLon, SatLon );
471                                                         double satHourAngle =
472                                                                 calcSatHourangle( SatLon, SiteLat, SiteLon );
473                                                         eDebug("PolarmountHourAngle=%lf", satHourAngle );
474
475                                                         static int gotoXTable[10] =
476                                                                 { 0x00, 0x02, 0x03, 0x05, 0x06, 0x08, 0x0A, 0x0B, 0x0D, 0x0E };
477
478                                                         if (SiteLat >= 0) // Northern Hemisphere
479                                                         {
480                                                                 int tmp=(int)round( fabs( 180 - satHourAngle ) * 10.0 );
481                                                                 RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
482
483                                                                 if (satHourAngle < 180) // the east
484                                                                         RotorCmd |= 0xE000;
485                                                                 else                                    // west
486                                                                         RotorCmd |= 0xD000;
487                                                         }
488                                                         else // Southern Hemisphere
489                                                         {
490                                                                 if (satHourAngle < 180) // the east
491                                                                 {
492                                                                         int tmp=(int)round( fabs( satHourAngle ) * 10.0 );
493                                                                         RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
494                                                                         RotorCmd |= 0xD000;
495                                                                 }
496                                                                 else // west
497                                                                 {
498                                                                         int tmp=(int)round( fabs( 360 - satHourAngle ) * 10.0 );
499                                                                         RotorCmd = (tmp/10)*0x10 + gotoXTable[ tmp % 10 ];
500                                                                         RotorCmd |= 0xE000;
501                                                                 }
502                                                         }
503                                                         eDebug("RotorCmd = %04x", RotorCmd);
504                                                 }
505                                         }
506                                 }
507
508                                 if ( send_mask )
509                                 {
510                                         eSecCommand::pair compare;
511                                         compare.steps = +3;
512                                         compare.tone = iDVBFrontend::toneOff;
513                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
514                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
515                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
516                                         compare.voltage = iDVBFrontend::voltageOff;
517                                         compare.steps = +3;
518                                         // the next is a check if voltage is switched off.. then we first set a voltage :)
519                                         // else we set voltage after all diseqc stuff..
520                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
521
522                                         if ( RotorCmd != -1 && RotorCmd != lastRotorCmd )
523                                         {
524                                                 if (rotor_param.m_inputpower_parameters.m_use)
525                                                         compare.voltage = VOLTAGE(18);  // in input power mode set 18V for measure input power
526                                                 else
527                                                         compare.voltage = VOLTAGE(13);  // in normal mode start turning with 13V
528                                         }
529                                         else
530                                                 compare.voltage = voltage;
531
532                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, compare.voltage) );
533
534                                         // voltage was disabled..so we wait a longer time .. for normal switches 250ms should be enough
535                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) );
536
537                                         for (int seq_repeat = 0; seq_repeat < (di_param.m_seq_repeat?2:1); ++seq_repeat)
538                                         {
539                                                 if ( send_mask & 4 )
540                                                 {
541                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
542                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_TONEBURST]) );
543                                                 }
544
545                                                 int loops=0;
546
547                                                 if ( send_mask & 1 )
548                                                         ++loops;
549                                                 if ( send_mask & 2 )
550                                                         ++loops;
551
552                                                 loops <<= di_param.m_repeats;
553
554                                                 for ( int i = 0; i < loops;)  // fill commands...
555                                                 {
556                                                         eDVBDiseqcCommand diseqc;
557                                                         diseqc.len = 4;
558                                                         diseqc.data[0] = i ? 0xE1 : 0xE0;
559                                                         diseqc.data[1] = 0x10;
560                                                         if ( (send_mask & 2) && (di_param.m_command_order & 4) )
561                                                         {
562                                                                 diseqc.data[2] = 0x39;
563                                                                 diseqc.data[3] = ucsw;
564                                                         }
565                                                         else if ( send_mask & 1 )
566                                                         {
567                                                                 diseqc.data[2] = 0x38;
568                                                                 diseqc.data[3] = csw;
569                                                         }
570                                                         else  // no committed command confed.. so send uncommitted..
571                                                         {
572                                                                 diseqc.data[2] = 0x39;
573                                                                 diseqc.data[3] = ucsw;
574                                                         }
575                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
576
577                                                         i++;
578                                                         if ( i < loops )
579                                                         {
580                                                                 int cmd=0;
581                                                                 if (diseqc.data[2] == 0x38 && (send_mask & 2))
582                                                                         cmd=0x39;
583                                                                 else if (diseqc.data[2] == 0x39 && (send_mask & 1))
584                                                                         cmd=0x38;
585                                                                 int tmp = m_params[DELAY_BETWEEN_DISEQC_REPEATS];
586                                                                 if (cmd)
587                                                                 {
588                                                                         int delay = di_param.m_repeats ? (tmp - 54) / 2 : tmp;  // standard says 100msek between two repeated commands
589                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay) );
590                                                                         diseqc.data[2]=cmd;
591                                                                         diseqc.data[3]=(cmd==0x38) ? csw : ucsw;
592                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
593                                                                         ++i;
594                                                                         if ( i < loops )
595                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay ) );
596                                                                         else
597                                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
598                                                                 }
599                                                                 else  // delay 120msek when no command is in repeat gap
600                                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, tmp) );
601                                                         }
602                                                         else
603                                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_LAST_DISEQC_CMD]) );
604                                                 }
605
606                                                 if ( send_mask & 8 )  // toneburst at end of sequence
607                                                 {
608                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_TONEBURST, di_param.m_toneburst_param) );
609                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_TONEBURST]) );
610                                                 }
611                                         }
612                                 }
613
614                                 if ( RotorCmd != -1 && RotorCmd != lastRotorCmd )
615                                 {
616                                         eSecCommand::pair compare;
617                                         if (!send_mask)
618                                         {
619                                                 compare.steps = +3;
620                                                 compare.tone = iDVBFrontend::toneOff;
621                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
622                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
623                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
624
625                                                 compare.voltage = iDVBFrontend::voltageOff;
626                                                 compare.steps = +4;
627                                                 // the next is a check if voltage is switched off.. then we first set a voltage :)
628                                                 // else we set voltage after all diseqc stuff..
629                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NOT_VOLTAGE_GOTO, compare) );
630
631                                                 if (rotor_param.m_inputpower_parameters.m_use)
632                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) ); // set 18V for measure input power
633                                                 else
634                                                         sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) ); // in normal mode start turning with 13V
635
636                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_MOTOR_CMD]) ); // wait 750ms when voltage was disabled
637                                                 sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, +9) );  // no need to send stop rotor cmd and recheck voltage
638                                         }
639                                         else
640                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_BETWEEN_SWITCH_AND_MOTOR_CMD]) ); // wait 700ms when diseqc changed
641
642                                         eDVBDiseqcCommand diseqc;
643                                         diseqc.len = 3;
644                                         diseqc.data[0] = 0xE0;
645                                         diseqc.data[1] = 0x31;  // positioner
646                                         diseqc.data[2] = 0x60;  // stop
647                                         sec_sequence.push_back( eSecCommand(eSecCommand::IF_ROTORPOS_VALID_GOTO, +5) );
648                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
649                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
650                                         sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
651                                         // wait 150msec after send rotor stop cmd
652                                         sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_MOTOR_STOP_CMD]) );
653
654                                         diseqc.data[0] = 0xE0;
655                                         diseqc.data[1] = 0x31;          // positioner
656                                         if ( useGotoXX )
657                                         {
658                                                 diseqc.len = 5;
659                                                 diseqc.data[2] = 0x6E;  // drive to angular position
660                                                 diseqc.data[3] = ((RotorCmd & 0xFF00) / 0x100);
661                                                 diseqc.data[4] = RotorCmd & 0xFF;
662                                         }
663                                         else
664                                         {
665                                                 diseqc.len = 4;
666                                                 diseqc.data[2] = 0x6B;  // goto stored sat position
667                                                 diseqc.data[3] = RotorCmd;
668                                                 diseqc.data[4] = 0x00;
669                                         }
670
671                                         if ( rotor_param.m_inputpower_parameters.m_use )
672                                         { // use measure rotor input power to detect rotor state
673                                                 eSecCommand::rotor cmd;
674                                                 eSecCommand::pair compare;
675                                                 compare.voltage = VOLTAGE(18);
676                                                 compare.steps = +3;
677                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
678                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, compare.voltage) );
679 // measure idle power values
680                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER]) );  // wait 150msec after voltage change
681                                                 sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 1) );
682                                                 compare.val = 1;
683                                                 compare.steps = -2;
684                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO, compare) );
685                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(13)) );
686                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MEASURE_IDLE_INPUTPOWER]) );  // wait 150msec before measure
687                                                 sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_IDLE_INPUTPOWER, 0) );
688                                                 compare.val = 0;
689                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_MEASURE_IDLE_WAS_NOT_OK_GOTO, compare) );
690 ////////////////////////////
691                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
692                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_ROTOR_DISEQC_RETRYS, m_params[MOTOR_COMMAND_RETRIES]) );  // 2 retries
693                                                 sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_ROTORPARMS) );
694                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
695                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, 40) );  // 2 seconds rotor start timout
696 // rotor start loop
697                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // 50msec delay
698                                                 sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
699                                                 cmd.direction=1;  // check for running rotor
700                                                 cmd.deltaA=rotor_param.m_inputpower_parameters.m_delta;
701                                                 cmd.steps=+5;
702                                                 cmd.okcount=0;
703                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );  // check if rotor has started
704                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +2 ) );  // timeout .. we assume now the rotor is already at the correct position
705                                                 sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // goto loop start
706                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_NO_MORE_ROTOR_DISEQC_RETRYS_GOTO, +10 ) );  // timeout .. we assume now the rotor is already at the correct position
707                                                 sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -8) );  // goto loop start
708 ////////////////////
709                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, VOLTAGE(18)) );
710                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
711                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, m_params[MOTOR_RUNNING_TIMEOUT]*20) );  // 2 minutes running timeout
712 // rotor running loop
713                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );  // wait 50msec
714                                                 sec_sequence.push_back( eSecCommand(eSecCommand::MEASURE_RUNNING_INPUTPOWER) );
715                                                 cmd.direction=0;  // check for stopped rotor
716                                                 cmd.steps=+4;
717                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_INPUTPOWER_DELTA_GOTO, cmd ) );
718                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +4 ) );  // timeout ? this should never happen
719                                                 sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -4) );  // running loop start
720 /////////////////////
721                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
722                                                 sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
723                                         }
724                                         else
725                                         {  // use normal turning mode
726                                                 doSetVoltageToneFrontend=false;
727                                                 doSetFrontend=false;
728                                                 eSecCommand::rotor cmd;
729                                                 eSecCommand::pair compare;
730                                                 compare.voltage = VOLTAGE(13);
731                                                 compare.steps = +3;
732                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
733                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, compare.voltage) );
734                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_MOTOR_CMD]) );  // wait 150msec after voltage change
735
736                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
737                                                 sec_sequence.push_back( eSecCommand(eSecCommand::INVALIDATE_CURRENT_ROTORPARMS) );
738                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
739
740                                                 compare.voltage = voltage;
741                                                 compare.steps = +3;
742                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // correct final voltage?
743                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 2000) );  // wait 2 second before set high voltage
744                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
745
746                                                 compare.tone = tone;
747                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
748                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
749                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
750                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
751
752                                                 cmd.direction=1;  // check for running rotor
753                                                 cmd.deltaA=0;
754                                                 cmd.steps=+3;
755                                                 cmd.okcount=0;
756                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TIMEOUT, m_params[MOTOR_RUNNING_TIMEOUT]*4) );  // 2 minutes running timeout
757                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 250) );  // 250msec delay
758                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TUNER_LOCKED_GOTO, cmd ) );
759                                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TIMEOUT_GOTO, +3 ) ); 
760                                                 sec_sequence.push_back( eSecCommand(eSecCommand::GOTO, -3) );  // goto loop start
761                                                 sec_sequence.push_back( eSecCommand(eSecCommand::UPDATE_CURRENT_ROTORPARAMS) );
762                                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
763                                         }
764                                         frontend.setData(eDVBFrontend::NEW_ROTOR_CMD, RotorCmd);
765                                         frontend.setData(eDVBFrontend::NEW_ROTOR_POS, sat.orbital_position);
766                                 }
767                         }
768                         else
769                                 csw = band;
770
771                         frontend.setData(eDVBFrontend::CSW, csw);
772                         frontend.setData(eDVBFrontend::UCSW, ucsw);
773                         frontend.setData(eDVBFrontend::TONEBURST, di_param.m_toneburst_param);
774
775                         if (!linked && doSetVoltageToneFrontend)
776                         {
777                                 eSecCommand::pair compare;
778                                 compare.voltage = voltage;
779                                 compare.steps = +3;
780                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) ); // voltage already correct ?
781                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, voltage) );
782                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_FINAL_VOLTAGE_CHANGE]) );
783                                 compare.tone = tone;
784                                 sec_sequence.push_back( eSecCommand(eSecCommand::IF_TONE_GOTO, compare) );
785                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, tone) );
786                                 sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_CONT_TONE]) );
787                         }
788
789                         if (doSetFrontend)
790                         {
791                                 sec_sequence.push_back( eSecCommand(eSecCommand::START_TUNE_TIMEOUT) );
792                                 sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
793                         }
794                         frontend.setSecSequence(sec_sequence);
795
796                         return 0;
797                 }
798         }
799
800         eDebug("found no useable satellite configuration for orbital position (%d)", sat.orbital_position );
801         return -1;
802 }
803
804 RESULT eDVBSatelliteEquipmentControl::clear()
805 {
806         for (int i=0; i <= m_lnbidx; ++i)
807         {
808                 m_lnbs[i].m_satellites.clear();
809                 m_lnbs[i].tuner_mask = 0;
810         }
811         m_lnbidx=-1;
812
813 // clear linked tuner configuration
814         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
815         {
816                 it->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, -1);
817                 it->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, -1);
818                 it->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, -1);
819         }
820
821         return 0;
822 }
823
824 /* LNB Specific Parameters */
825 RESULT eDVBSatelliteEquipmentControl::addLNB()
826 {
827         if ( (m_lnbidx+1) < (int)(sizeof(m_lnbs) / sizeof(eDVBSatelliteLNBParameters)))
828                 m_curSat=m_lnbs[++m_lnbidx].m_satellites.end();
829         else
830         {
831                 eDebug("no more LNB free... cnt is %d", m_lnbidx);
832                 return -ENOSPC;
833         }
834         return 0;
835 }
836
837 RESULT eDVBSatelliteEquipmentControl::setLNBTunerMask(int tunermask)
838 {
839         if ( currentLNBValid() )
840                 m_lnbs[m_lnbidx].tuner_mask = tunermask;
841         else
842                 return -ENOENT;
843         return 0;
844 }
845
846 RESULT eDVBSatelliteEquipmentControl::setLNBLOFL(int lofl)
847 {
848         if ( currentLNBValid() )
849                 m_lnbs[m_lnbidx].m_lof_lo = lofl;
850         else
851                 return -ENOENT;
852         return 0;
853 }
854
855 RESULT eDVBSatelliteEquipmentControl::setLNBLOFH(int lofh)
856 {
857         if ( currentLNBValid() )
858                 m_lnbs[m_lnbidx].m_lof_hi = lofh;
859         else
860                 return -ENOENT;
861         return 0;
862 }
863
864 RESULT eDVBSatelliteEquipmentControl::setLNBThreshold(int threshold)
865 {
866         if ( currentLNBValid() )
867                 m_lnbs[m_lnbidx].m_lof_threshold = threshold;
868         else
869                 return -ENOENT;
870         return 0;
871 }
872
873 RESULT eDVBSatelliteEquipmentControl::setLNBIncreasedVoltage(bool onoff)
874 {
875         if ( currentLNBValid() )
876                 m_lnbs[m_lnbidx].m_increased_voltage = onoff;
877         else
878                 return -ENOENT;
879         return 0;
880 }
881
882 /* DiSEqC Specific Parameters */
883 RESULT eDVBSatelliteEquipmentControl::setDiSEqCMode(int diseqcmode)
884 {
885         if ( currentLNBValid() )
886                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_diseqc_mode = (eDVBSatelliteDiseqcParameters::t_diseqc_mode)diseqcmode;
887         else
888                 return -ENOENT;
889         return 0;
890 }
891
892 RESULT eDVBSatelliteEquipmentControl::setToneburst(int toneburst)
893 {
894         if ( currentLNBValid() )
895                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_toneburst_param = (eDVBSatelliteDiseqcParameters::t_toneburst_param)toneburst;
896         else
897                 return -ENOENT;
898         return 0;
899 }
900
901 RESULT eDVBSatelliteEquipmentControl::setRepeats(int repeats)
902 {
903         if ( currentLNBValid() )
904                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_repeats=repeats;
905         else
906                 return -ENOENT;
907         return 0;
908 }
909
910 RESULT eDVBSatelliteEquipmentControl::setCommittedCommand(int command)
911 {
912         if ( currentLNBValid() )
913                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_committed_cmd=command;
914         else
915                 return -ENOENT;
916         return 0;
917 }
918
919 RESULT eDVBSatelliteEquipmentControl::setUncommittedCommand(int command)
920 {
921         if ( currentLNBValid() )
922                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_uncommitted_cmd = command;
923         else
924                 return -ENOENT;
925         return 0;
926 }
927
928 RESULT eDVBSatelliteEquipmentControl::setCommandOrder(int order)
929 {
930         if ( currentLNBValid() )
931                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_command_order=order;
932         else
933                 return -ENOENT;
934         return 0;
935 }
936
937 RESULT eDVBSatelliteEquipmentControl::setFastDiSEqC(bool onoff)
938 {
939         if ( currentLNBValid() )
940                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_use_fast=onoff;
941         else
942                 return -ENOENT;
943         return 0;
944 }
945
946 RESULT eDVBSatelliteEquipmentControl::setSeqRepeat(bool onoff)
947 {
948         if ( currentLNBValid() )
949                 m_lnbs[m_lnbidx].m_diseqc_parameters.m_seq_repeat = onoff;
950         else
951                 return -ENOENT;
952         return 0;
953 }
954
955 /* Rotor Specific Parameters */
956 RESULT eDVBSatelliteEquipmentControl::setLongitude(float longitude)
957 {
958         if ( currentLNBValid() )
959                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_longitude=longitude;
960         else
961                 return -ENOENT;
962         return 0;
963 }
964
965 RESULT eDVBSatelliteEquipmentControl::setLatitude(float latitude)
966 {
967         if ( currentLNBValid() )
968                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_latitude=latitude;
969         else
970                 return -ENOENT;
971         return 0;
972 }
973
974 RESULT eDVBSatelliteEquipmentControl::setLoDirection(int direction)
975 {
976         if ( currentLNBValid() )
977                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_lo_direction=direction;
978         else
979                 return -ENOENT;
980         return 0;
981 }
982
983 RESULT eDVBSatelliteEquipmentControl::setLaDirection(int direction)
984 {
985         if ( currentLNBValid() )
986                 m_lnbs[m_lnbidx].m_rotor_parameters.m_gotoxx_parameters.m_la_direction=direction;
987         else
988                 return -ENOENT;
989         return 0;
990 }
991
992 RESULT eDVBSatelliteEquipmentControl::setUseInputpower(bool onoff)
993 {
994         if ( currentLNBValid() )
995                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_use=onoff;
996         else
997                 return -ENOENT;
998         return 0;
999 }
1000
1001 RESULT eDVBSatelliteEquipmentControl::setInputpowerDelta(int delta)
1002 {
1003         if ( currentLNBValid() )
1004                 m_lnbs[m_lnbidx].m_rotor_parameters.m_inputpower_parameters.m_delta=delta;
1005         else
1006                 return -ENOENT;
1007         return 0;
1008 }
1009
1010 /* Satellite Specific Parameters */
1011 RESULT eDVBSatelliteEquipmentControl::addSatellite(int orbital_position)
1012 {
1013         if ( currentLNBValid() )
1014         {
1015                 std::map<int, eDVBSatelliteSwitchParameters>::iterator it =
1016                         m_lnbs[m_lnbidx].m_satellites.find(orbital_position);
1017                 if ( it == m_lnbs[m_lnbidx].m_satellites.end() )
1018                 {
1019                         std::pair<std::map<int, eDVBSatelliteSwitchParameters>::iterator, bool > ret =
1020                                 m_lnbs[m_lnbidx].m_satellites.insert(
1021                                         std::pair<int, eDVBSatelliteSwitchParameters>(orbital_position, eDVBSatelliteSwitchParameters())
1022                                 );
1023                         if ( ret.second )
1024                                 m_curSat = ret.first;
1025                         else
1026                                 return -ENOMEM;
1027                 }
1028                 else
1029                         return -EEXIST;
1030         }
1031         else
1032                 return -ENOENT;
1033         return 0;
1034 }
1035
1036 RESULT eDVBSatelliteEquipmentControl::setVoltageMode(int mode)
1037 {
1038         if ( currentLNBValid() && m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1039                 m_curSat->second.m_voltage_mode = (eDVBSatelliteSwitchParameters::t_voltage_mode)mode;
1040         else
1041                 return -ENOENT;
1042         return 0;
1043
1044 }
1045
1046 RESULT eDVBSatelliteEquipmentControl::setToneMode(int mode)
1047 {
1048         if ( currentLNBValid() )
1049         {
1050                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1051                         m_curSat->second.m_22khz_signal = (eDVBSatelliteSwitchParameters::t_22khz_signal)mode;
1052                 else
1053                         return -EPERM;
1054         }
1055         else
1056                 return -ENOENT;
1057         return 0;
1058 }
1059
1060 RESULT eDVBSatelliteEquipmentControl::setRotorPosNum(int rotor_pos_num)
1061 {
1062         if ( currentLNBValid() )
1063         {
1064                 if ( m_curSat != m_lnbs[m_lnbidx].m_satellites.end() )
1065                         m_curSat->second.m_rotorPosNum=rotor_pos_num;
1066                 else
1067                         return -EPERM;
1068         }
1069         else
1070                 return -ENOENT;
1071         return 0;
1072 }
1073
1074 struct sat_compare
1075 {
1076         int orb_pos, lofl, lofh;
1077         sat_compare(int o, int lofl, int lofh)
1078                 :orb_pos(o), lofl(lofl), lofh(lofh)
1079         {}
1080         sat_compare(const sat_compare &x)
1081                 :orb_pos(x.orb_pos), lofl(x.lofl), lofh(x.lofh)
1082         {}
1083         bool operator < (const sat_compare & cmp) const
1084         {
1085                 if (orb_pos == cmp.orb_pos)
1086                 {
1087                         if ( abs(lofl-cmp.lofl) < 200000 )
1088                         {
1089                                 if (abs(lofh-cmp.lofh) < 200000)
1090                                         return false;
1091                                 return lofh<cmp.lofh;
1092                         }
1093                         return lofl<cmp.lofl;
1094                 }
1095                 return orb_pos < cmp.orb_pos;
1096         }
1097 };
1098
1099 PyObject *eDVBSatelliteEquipmentControl::get_exclusive_satellites(int tu1, int tu2)
1100 {
1101         ePyObject ret;
1102
1103         if (tu1 != tu2)
1104         {
1105                 eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
1106                 int cnt=0;
1107                 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it, ++cnt)
1108                 {
1109                         if (cnt == tu1)
1110                                 p1 = *it;
1111                         else if (cnt == tu2)
1112                                 p2 = *it;
1113                 }
1114
1115                 if (p1 && p2)
1116                 {
1117                         // check for linked tuners
1118
1119                         do 
1120                         {
1121                                 int tmp;
1122                                 p1->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
1123                                 if (tmp != -1)
1124                                         p1 = (eDVBRegisteredFrontend*)tmp;
1125                                 else
1126                                         break;
1127                         }
1128                         while (true);
1129
1130                         do 
1131                         {
1132                                 int tmp;
1133                                 p2->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
1134                                 if (tmp != -1)
1135                                         p2 = (eDVBRegisteredFrontend*)tmp;
1136                                 else
1137                                         break;
1138                         }
1139                         while (true);
1140
1141                         if (p1 != p2)
1142                         {
1143                                 int tmp1=-1;
1144                                 int tmp2=-1;
1145                                 // check for rotor dependency
1146                                 p1->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp1);
1147                                 if (tmp1 != -1)
1148                                         p1 = (eDVBRegisteredFrontend*)tmp1;
1149                                 p2->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp2);
1150                                 if (tmp2 != -1)
1151                                         p2 = (eDVBRegisteredFrontend*)tmp2;
1152                                 if (p1 != p2)
1153                                 {
1154                                         int tu1_mask = 1 << p1->m_frontend->getID(),
1155                                                 tu2_mask = 1 << p2->m_frontend->getID();
1156                                         std::set<sat_compare> tu1sats, tu2sats;
1157                                         std::list<sat_compare> tu1difference, tu2difference;
1158                                         std::insert_iterator<std::list<sat_compare> > insert1(tu1difference, tu1difference.begin()),
1159                                                 insert2(tu2difference, tu2difference.begin());
1160                                         for (int idx=0; idx <= m_lnbidx; ++idx )
1161                                         {
1162                                                 eDVBSatelliteLNBParameters &lnb_param = m_lnbs[idx];
1163                                                 for (std::map<int, eDVBSatelliteSwitchParameters>::iterator sit(lnb_param.m_satellites.begin());
1164                                                         sit != lnb_param.m_satellites.end(); ++sit)
1165                                                 {
1166                                                         if ( lnb_param.tuner_mask & tu1_mask )
1167                                                                 tu1sats.insert(sat_compare(sit->first, lnb_param.m_lof_lo, lnb_param.m_lof_hi));
1168                                                         if ( lnb_param.tuner_mask & tu2_mask )
1169                                                                 tu2sats.insert(sat_compare(sit->first, lnb_param.m_lof_lo, lnb_param.m_lof_hi));
1170                                                 }
1171                                         }
1172                                         std::set_difference(tu1sats.begin(), tu1sats.end(),
1173                                                 tu2sats.begin(), tu2sats.end(),
1174                                                 insert1);
1175                                         std::set_difference(tu2sats.begin(), tu2sats.end(),
1176                                                 tu1sats.begin(), tu1sats.end(),
1177                                                 insert2);
1178                                         if (!tu1sats.empty() || !tu2sats.empty())
1179                                         {
1180                                                 int idx=0;
1181                                                 ret = PyList_New(2+tu1difference.size()+tu2difference.size());
1182
1183                                                 PyList_SET_ITEM(ret, idx++, PyInt_FromLong(tu1difference.size()));
1184                                                 for(std::list<sat_compare>::iterator it(tu1difference.begin()); it != tu1difference.end(); ++it)
1185                                                         PyList_SET_ITEM(ret, idx++, PyInt_FromLong(it->orb_pos));
1186
1187                                                 PyList_SET_ITEM(ret, idx++, PyInt_FromLong(tu2difference.size()));
1188                                                 for(std::list<sat_compare>::iterator it(tu2difference.begin()); it != tu2difference.end(); ++it)
1189                                                         PyList_SET_ITEM(ret, idx++, PyInt_FromLong(it->orb_pos));
1190                                         }
1191                                 }
1192                         }
1193                 }
1194         }
1195         if (!ret)
1196         {
1197                 ret = PyList_New(2);
1198                 PyList_SET_ITEM(ret, 0, PyInt_FromLong(0));
1199                 PyList_SET_ITEM(ret, 1, PyInt_FromLong(0));
1200         }
1201         return ret;
1202 }
1203
1204 RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
1205 {
1206         if (tu1 != tu2)
1207         {
1208                 eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
1209
1210                 int cnt=0;
1211                 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it, ++cnt)
1212                 {
1213                         if (cnt == tu1)
1214                                 p1 = *it;
1215                         else if (cnt == tu2)
1216                                 p2 = *it;
1217                 }
1218                 if (p1 && p2)
1219                 {
1220                         p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (int)p2);
1221                         p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (int)p1);
1222                         return 0;
1223                 }
1224         }
1225         return -1;
1226 }
1227
1228 RESULT eDVBSatelliteEquipmentControl::setTunerDepends(int tu1, int tu2)
1229 {
1230         if (tu1 == tu2)
1231                 return -1;
1232
1233         eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
1234
1235         int cnt=0;
1236         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it, ++cnt)
1237         {
1238                 if (cnt == tu1)
1239                         p1 = *it;
1240                 else if (cnt == tu2)
1241                         p2 = *it;
1242         }
1243         if (p1 && p2)
1244         {
1245                 p1->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (int)p2);
1246                 p2->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, (int)p1);
1247                 return 0;
1248         }
1249         return -1;
1250 }
1251
1252 bool eDVBSatelliteEquipmentControl::isRotorMoving()
1253 {
1254         return m_rotorMoving;
1255 }
1256
1257 void eDVBSatelliteEquipmentControl::setRotorMoving(bool b)
1258 {
1259         m_rotorMoving=b;
1260 }