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