Support turbo2.
[vuplus_dvbapp] / lib / dvb / fbc.cpp
1 /* FBC Manager */
2 #include <lib/dvb/fbc.h>
3 #include <lib/dvb/dvb.h>
4 #include <lib/dvb/sec.h>
5 #include <lib/base/object.h>
6
7 #include <unistd.h>
8 #include <fcntl.h>
9
10 //#define FBC_DEBUG
11
12 #ifdef FBC_DEBUG
13 #define eFecDebug(arg...) eDebug(arg)
14 #else
15 #define eFecDebug(arg...)
16 #endif
17
18 static int getProcData(const char* filename)
19 {
20         int res = -1;
21         FILE *fp = fopen(filename,"r");
22         if(fp)
23         {
24                 fscanf(fp, "%d", &res);
25                 fclose(fp);
26         }
27         else
28         {
29                 eFecDebug("[*][eFBCTunerManager::getProcData] open failed, %s: %m", filename);
30         }
31         return res;
32 }
33
34 static void setProcData(const char* filename, int value)
35 {
36         eDebug("[*] setProcData %s -> %d", filename, value);
37         FILE *fp = fopen(filename, "w");
38         if(fp)
39         {
40                 fprintf(fp, "%d", value);
41                 fclose(fp);
42         }
43         else
44         {
45                 eFecDebug("[*][eFBCTunerManager::setProcData] open failed, %s: %m", filename);
46         }
47 }
48
49 static void loadConnectChoices(const char* filename, bool *connect_choices)
50 {
51         FILE *fp = fopen(filename,"r");
52         if(fp)
53         {
54                 int c;
55                 while(EOF != (c = fgetc(fp)))
56                 {
57                         if(isdigit(c))
58                                 connect_choices[c - '0'] = true;
59                 }
60                 fclose(fp);
61         }
62         else
63         {
64                 eFecDebug("[*][eFBCTunerManager::LoadFbcRootChoices] open failed, %s: %m", filename);
65         }
66 }
67
68
69 DEFINE_REF(eFBCTunerManager);
70
71 eFBCTunerManager* eFBCTunerManager::m_instance = (eFBCTunerManager*)0;
72
73 eFBCTunerManager* eFBCTunerManager::getInstance()
74 {
75         return m_instance;
76 }
77
78 eFBCTunerManager::eFBCTunerManager(ePtr<eDVBResourceManager> res_mgr)
79         :m_res_mgr(res_mgr)
80 {
81         if (!m_instance)
82                 m_instance = this;
83
84         eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
85         eSmartPtrList<eDVBRegisteredFrontend> &frontends_simulate = m_res_mgr->m_simulate_frontend;
86         /* each FBC set has 8 tuners. */
87         /* first set : 0, 1, 2, 3, 4, 5, 6, 7 */
88         /* second set : 8, 9, 10, 11, 12, 13, 14, 15 */
89         /* first, second frontend is top on a set */
90
91         bool isRoot;
92         int fe_id = -1;
93         int fbcSetID = -2;
94         int fbcIndex = 0;
95         int initFbcId = -1;
96         int prevFbcSetID = -1;
97         char procFileName[128];
98         std::string proc_fe;
99         bool connect_choices[32] = {false};
100
101         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
102         {
103                 // continue for DVB-C FBC Tuner
104                 if (!(it->m_frontend->supportsDeliverySystem(SYS_DVBS, false) || it->m_frontend->supportsDeliverySystem(SYS_DVBS2, false)))
105                         continue;
106
107                 fe_id = feSlotID(it);
108                 snprintf(procFileName, sizeof(procFileName), "/proc/stb/frontend/%d/fbc_set_id", fe_id);
109                 fbcSetID = getProcData(procFileName);
110                 if (fbcSetID != -1)
111                 {
112                         if (prevFbcSetID != fbcSetID)
113                         {
114                                 prevFbcSetID = fbcSetID;
115                                 memset(connect_choices, 0, sizeof(connect_choices));
116                                 snprintf(procFileName, sizeof(procFileName), "/proc/stb/frontend/%d/fbc_connect_choices", fe_id);
117                                 loadConnectChoices(procFileName, connect_choices);
118                                 fbcIndex =0; // reset
119                         }
120
121                         isRoot = false;
122                         if (fbcIndex < sizeof(connect_choices)/sizeof(connect_choices[0]))
123                         {
124                                 isRoot = connect_choices[fbcIndex];
125                         }
126
127                         initFbcId = isRoot ? fbcIndex : 0;
128
129                         FBC_TUNER elem = {fbcSetID, fbcIndex, isRoot, initFbcId};
130                         m_fbc_tuners[fe_id] = elem;
131
132                         /* set default fbc ID */
133                         setProcFBCID(fe_id, initFbcId, false);
134
135                         /* enable fbc tuner */
136                         it->m_frontend->setFBCTuner(true);
137
138                         fbcIndex++;
139                 }
140         }
141
142         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends_simulate.begin()); it != frontends_simulate.end(); ++it)
143         {
144                 // continue for DVB-C FBC Tuner
145                 if (!(it->m_frontend->supportsDeliverySystem(SYS_DVBS, false) || it->m_frontend->supportsDeliverySystem(SYS_DVBS2, false)))
146                         continue;
147
148                 fe_id = feSlotID(it);
149                 snprintf(procFileName, sizeof(procFileName), "/proc/stb/frontend/%d/fbc_set_id", fe_id);
150                 fbcSetID = getProcData(procFileName);
151                 if (fbcSetID != -1)
152                 {
153                         /* enable fbc tuner */
154                         it->m_frontend->setFBCTuner(true);
155                 }
156         }
157 }
158
159 eFBCTunerManager::~eFBCTunerManager()
160 {
161         if (m_instance == this)
162                 m_instance = 0;
163 }
164
165 int eFBCTunerManager::setProcFBCID(int fe_id, int fbc_connect, bool is_linked)
166 {
167         eFecDebug("[*][eFBCTunerManager::setProcFBCID] %d -> %d", fe_id, fbc_connect);
168         char filename[128];
169
170         /* set root */
171         sprintf(filename, "/proc/stb/frontend/%d/fbc_connect", fe_id);
172         setProcData(filename, fbc_connect);
173
174         /* set linked */
175         sprintf(filename, "/proc/stb/frontend/%d/fbc_link", fe_id);
176         setProcData(filename, (int)is_linked);
177
178         return 0;
179 }
180
181
182 int eFBCTunerManager::feSlotID(const eDVBRegisteredFrontend *fe) const
183 {
184         return fe->m_frontend->getSlotID();
185 }
186
187 void eFBCTunerManager::setDefaultFBCID(eDVBRegisteredFrontend *fe)
188 {
189         int fe_id = feSlotID(fe);
190         setProcFBCID(fe_id, getDefaultFBCID(fe_id), isLinked(fe));
191 }
192
193 void eFBCTunerManager::updateFBCID(eDVBRegisteredFrontend *next_fe, eDVBRegisteredFrontend *prev_fe)
194 {
195         setProcFBCID(feSlotID(next_fe), getFBCID(feSlotID(getTop(prev_fe))), isLinked(next_fe));
196 }
197
198 bool eFBCTunerManager::isLinked(eDVBRegisteredFrontend *fe) const
199 {
200  
201         long linked_prev_ptr = -1;
202         fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
203         return (linked_prev_ptr != -1);
204 }
205
206 bool eFBCTunerManager::isUnicable(eDVBRegisteredFrontend *fe) const
207 {
208         int slot_idx = feSlotID(fe);
209         bool is_unicable = false;
210
211         ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
212         for (int idx=0; idx <= sec->m_lnbidx; ++idx )
213         {
214                 eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
215                 if ( lnb_param.m_slot_mask & (1 << slot_idx) )
216                 {
217                         is_unicable = lnb_param.SatCR_idx != -1;
218                         break;
219                 }
220         }
221         return is_unicable;
222 }
223
224 bool eFBCTunerManager::isFeUsed(eDVBRegisteredFrontend *fe, bool a_simulate) const
225 {
226         if (fe->m_inuse > 0)
227                 return true;
228
229         bool simulate = !a_simulate;
230
231         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
232         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
233         {
234                 if (feSlotID(it) == feSlotID(fe))
235                 {
236                         return (it->m_inuse >0);
237                 }
238         }
239
240         eDebug("[*][eFBCTunerManager::isFeUsed] ERROR! can not found fe ptr (feid : %d, simulate : %d)", feSlotID(fe), simulate);
241         return false;
242 }
243
244 bool eFBCTunerManager::isSameFbcSet(int fe_a, int fe_b)
245 {
246         return m_fbc_tuners[fe_a].fbcSetID == m_fbc_tuners[fe_b].fbcSetID;
247 }
248
249 bool eFBCTunerManager::isRootFe(eDVBRegisteredFrontend *fe)
250 {
251         return m_fbc_tuners[feSlotID(fe)].isRoot;
252 }
253
254 int eFBCTunerManager::getFBCID(int fe_id)
255 {
256         return m_fbc_tuners[fe_id].fbcIndex;
257 }
258
259 int eFBCTunerManager::getDefaultFBCID(int fe_id)
260 {
261         return m_fbc_tuners[fe_id].initFbcId;
262 }
263
264 int eFBCTunerManager::getFBCSetID(int fe_id)
265 {
266         return m_fbc_tuners[fe_id].fbcSetID;
267 }
268
269 eDVBRegisteredFrontend *eFBCTunerManager::getPrev(eDVBRegisteredFrontend *fe) const
270 {
271         eDVBRegisteredFrontend *prev_fe = NULL;
272         long linked_prev_ptr = -1;
273         fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
274         if (linked_prev_ptr != -1)
275                 prev_fe = (eDVBRegisteredFrontend *)linked_prev_ptr;
276         return prev_fe;
277 }
278
279 eDVBRegisteredFrontend *eFBCTunerManager::getNext(eDVBRegisteredFrontend *fe) const
280 {
281         eDVBRegisteredFrontend *next_fe = NULL;
282         long linked_next_ptr = -1;
283         fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
284         if (linked_next_ptr != -1)
285                 next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
286         return next_fe;
287 }
288
289 eDVBRegisteredFrontend *eFBCTunerManager::getTop(eDVBRegisteredFrontend *fe) const
290 {
291         eDVBRegisteredFrontend *prev_fe = fe;
292         long linked_prev_ptr = -1;
293         fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
294         while(linked_prev_ptr != -1)
295         {
296                 prev_fe = (eDVBRegisteredFrontend *)linked_prev_ptr;
297                 prev_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
298         }
299         return prev_fe;
300 }
301
302 eDVBRegisteredFrontend *eFBCTunerManager::getLast(eDVBRegisteredFrontend *fe) const
303 {
304         eDVBRegisteredFrontend *next_fe = fe;
305         long linked_next_ptr = -1;
306         fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
307         while(linked_next_ptr != -1)
308         {
309                 next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
310                 next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
311         }
312         return next_fe;
313 }
314
315 eDVBRegisteredFrontend *eFBCTunerManager::getSimulFe(eDVBRegisteredFrontend *fe) const
316 {
317         eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_simulate_frontend;
318
319         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); it++)
320                 if (feSlotID(*it) == feSlotID(fe))
321                         return(*it);
322
323         return((eDVBRegisteredFrontend *)0);
324 }
325
326 void eFBCTunerManager::connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
327 {
328         if (next_fe)
329                 eFecDebug("     [*][eFBCTunerManager::connectLink] connect %d->%d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), feSlotID(next_fe), simulate?"(simulate)":"");
330         else
331                 eFecDebug("     [*][eFBCTunerManager::connectLink] connect %d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), simulate?"(simulate)":"");
332
333         prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
334         link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
335         if (next_fe)
336         {
337                 link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
338                 next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)link_fe);
339         }
340 }
341
342 void eFBCTunerManager::disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
343 {
344         if (next_fe)
345                 eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), feSlotID(next_fe), simulate?"(simulate)":"");
346         else
347                 eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), simulate?"(simulate)":"");
348
349         if (next_fe)
350         {
351                 prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
352                 next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
353
354                 link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
355                 link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
356         }
357         else
358         {
359                 prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
360                 link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
361         }
362 }
363
364 int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *&fbc_fe, bool simulate)
365 {
366         int best_score = 0;
367
368         eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
369         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
370         {
371                 if (!it->m_frontend->is_FBCTuner())
372                         continue;
373
374                 if (!isRootFe(*it))
375                         continue;
376
377                 if(!it->m_frontend->getEnabled())
378                         continue;
379
380                 if(!isSameFbcSet(feSlotID(link_fe), feSlotID(it)))
381                         continue;
382
383                 if(it->m_inuse == 0) // No link to a fe not in use.
384                         continue;
385
386                 if(isLinked(*it)) // No link to a fe linked to another.
387                         continue;
388
389                 if(isUnicable(*it))
390                         continue;
391
392                 eDVBRegisteredFrontend *top_fe = *it;
393                 eDVBRegisteredFrontend *prev_fe = getLast(top_fe);
394
395                 /* connect link */
396                 connectLink(link_fe, prev_fe, NULL, simulate);
397
398                 /* enable linked fe */
399                 link_fe->m_frontend->setEnabled(true);
400
401                 /* add slot mask*/
402                 updateLNBSlotMask(feSlotID(link_fe), feSlotID(*it), false);
403
404                 /* get score */
405                 int c = link_fe->m_frontend->isCompatibleWith(feparm);
406                 if (c > best_score)
407                 {
408                         best_score = c;
409                         fbc_fe = (eDVBRegisteredFrontend *)*it;
410                 }
411
412                 eFecDebug("[*][eFBCTunerManager::isCompatibleWith] score : %d (%d->%d)", c, feSlotID(it), feSlotID(link_fe));
413
414                 ASSERT(!getNext(link_fe));
415                 ASSERT(getPrev(link_fe));
416                 ASSERT(getLast(top_fe) == link_fe);
417
418                 /* disconnect link */
419                 disconnectLink(link_fe, prev_fe, NULL, simulate);
420
421                 /* disable linked fe */
422                 link_fe->m_frontend->setEnabled(false);
423
424                 /* remove slot mask*/
425                 updateLNBSlotMask(feSlotID(link_fe), feSlotID(top_fe), true);
426         }
427
428         eFecDebug("[*][eFBCTunerManager::isCompatibleWith] fe : %p(%d), score : %d %s", link_fe, feSlotID(link_fe), best_score, simulate?"(simulate)":"");
429
430         return best_score;
431 }
432
433 /* attach link_fe to tail of fe linked list */
434 void eFBCTunerManager::addLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate)
435 {
436         //printLinks(link_fe);
437
438         eFecDebug("     [*][eFBCTunerManager::addLink] addLink : %p(%d)->%p(%d) %s", top_fe, feSlotID(top_fe), link_fe, feSlotID(link_fe), simulate?"(simulate)":"");
439
440         eDVBRegisteredFrontend *next_fe = NULL;
441         eDVBRegisteredFrontend *prev_fe = NULL;
442
443         if(isRootFe(link_fe) || !isRootFe(top_fe))
444                 return;
445
446         /* search prev/next fe */
447         next_fe = top_fe;
448         while(true)
449         {
450                 prev_fe = next_fe;
451                 next_fe = getNext(prev_fe);
452                 if ((next_fe == NULL) || (feSlotID(next_fe) > feSlotID(link_fe)))
453                         break;
454         }
455
456         /* connect */
457         connectLink(link_fe, prev_fe, next_fe, simulate);
458
459         /* enable linked fe */
460         link_fe->m_frontend->setEnabled(true);
461
462         /* simulate connect */
463         if (!simulate)
464         {
465                 eDVBRegisteredFrontend *simulate_prev_fe = NULL;
466                 eDVBRegisteredFrontend *simulate_link_fe = NULL;
467                 eDVBRegisteredFrontend *simulate_next_fe = NULL;
468
469                 simulate_prev_fe = getSimulFe(prev_fe);
470                 simulate_link_fe = getSimulFe(link_fe);
471
472                 if (next_fe) 
473                         simulate_next_fe = getSimulFe(next_fe);
474
475                 eFecDebug("     [*][eFBCTunerManager::addLink] simulate fe : %p -> %p -> %p", simulate_prev_fe, simulate_link_fe, simulate_next_fe);
476
477                 connectLink(simulate_link_fe, simulate_prev_fe, simulate_next_fe, !simulate);
478
479                 /* enable simulate linked fe */
480                 simulate_link_fe->m_frontend->setEnabled(true);
481         }
482
483         /* set proc fbc_id */
484         if (!simulate)
485                 setProcFBCID(feSlotID(link_fe), getFBCID(feSlotID(top_fe)), isLinked(link_fe));
486
487         /* add slot mask*/
488         updateLNBSlotMask(feSlotID(link_fe), feSlotID(top_fe), false);
489
490         //printLinks(link_fe);
491 }
492
493 /* if fe, fe_simulated is unused, unlink current frontend from linked things. */
494 /* all unused linked fbc fe must be unlinked! */
495 void eFBCTunerManager::unLink(eDVBRegisteredFrontend *link_fe)
496 {
497         bool simulate = link_fe->m_frontend->is_simulate();
498         eFecDebug("     [*][eFBCTunerManager::unLink] fe id : %p(%d) %s", link_fe, feSlotID(link_fe), simulate?"(simulate)":"");
499
500         if (isRootFe(link_fe) || isFeUsed(link_fe, simulate) || isUnicable(link_fe) || !isLinked(link_fe))
501         {
502                 eFecDebug("     [*][eFBCTunerManager::unLink] skip..");
503                 return;
504         }
505
506         //printLinks(link_fe);
507
508         eDVBRegisteredFrontend *prev_fe = getPrev(link_fe);
509         eDVBRegisteredFrontend *next_fe = getNext(link_fe);
510
511         ASSERT(prev_fe);
512
513         disconnectLink(link_fe, prev_fe, next_fe, simulate);
514
515         /* disable linked fe */
516         link_fe->m_frontend->setEnabled(false);
517
518         /* simulate disconnect */
519         if (!simulate)
520         {
521                 eDVBRegisteredFrontend *simulate_prev_fe = NULL;
522                 eDVBRegisteredFrontend *simulate_link_fe = NULL;
523                 eDVBRegisteredFrontend *simulate_next_fe = NULL;
524
525                 simulate_prev_fe = getSimulFe(prev_fe);
526                 simulate_link_fe = getSimulFe(link_fe);
527
528                 if (next_fe) 
529                         simulate_next_fe = getSimulFe(next_fe);
530
531                 disconnectLink(simulate_link_fe, simulate_prev_fe, simulate_next_fe, !simulate);
532
533                 /* enable simulate linked fe */
534                 simulate_link_fe->m_frontend->setEnabled(false);
535         }
536
537         /* set default proc fbc_id */
538         //setDefaultFBCID(link_fe);
539
540         /* remove slot mask*/
541         updateLNBSlotMask(feSlotID(link_fe), feSlotID(getTop(prev_fe)), true);
542
543         //printLinks(link_fe);
544 }
545
546 int eFBCTunerManager::updateLNBSlotMask(int dest_slot, int src_slot, bool remove)
547 {
548         ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
549
550         int sec_lnbidx = sec->m_lnbidx;
551
552         int found = 0;
553         for (int idx=0; idx <= sec_lnbidx; ++idx )
554         {
555                 eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
556                 if ( lnb_param.m_slot_mask & (1 << src_slot) )
557                 {
558                         eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] m_slot_mask : %d", lnb_param.m_slot_mask);
559
560                         if (!remove)
561                                 lnb_param.m_slot_mask |= (1 << dest_slot);
562                         else
563                                 lnb_param.m_slot_mask &= ~(1 << dest_slot);
564
565                         eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] changed m_slot_mask : %d", lnb_param.m_slot_mask);
566                         found = 1;
567                 }
568         }
569
570         if (!found)
571                 eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] src %d not found", src_slot);
572
573         return 0;
574 }
575
576 bool eFBCTunerManager::canLink(eDVBRegisteredFrontend *fe)
577 {
578         return !(isRootFe(fe) || getPrev(fe) || getNext(fe) || isUnicable(fe));
579 }
580
581 int eFBCTunerManager::getLinkedSlotID(int fe_id) const
582 {
583         int link = -1;
584         eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
585         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
586         {
587                 if(it->m_frontend->getSlotID() == fe_id)
588                 {
589                         long prev_ptr = -1;
590                         it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
591                         if (prev_ptr != -1)
592                         {
593                                 eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
594                                 link = feSlotID(prev_fe);
595                         }
596                         break;
597                 }
598         }
599
600         eFecDebug(" [*][eFBCTunerManager::getLinkedSlotID] fe_id : %d, link : %d", fe_id, link);
601
602         return link;
603 }
604
605 bool eFBCTunerManager::isFBCLink(int fe_id)
606 {
607         bool res = false;
608         std::map<int, FBC_TUNER>::iterator it = m_fbc_tuners.find(fe_id);
609         if (it != m_fbc_tuners.end())
610         {
611                 res = !it->second.isRoot;
612         }
613         return res;
614 }
615
616 void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe) const
617 {
618         long linked_prev_ptr = -1;
619         eDVBRegisteredFrontend *linked_prev_fe = fe;
620         fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
621         while (linked_prev_ptr != -1)
622         {
623                 linked_prev_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
624                 linked_prev_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
625         }
626
627         long linked_next_ptr = -1;
628         eDVBRegisteredFrontend *linked_next_fe = linked_prev_fe;
629         eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", feSlotID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
630         linked_prev_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
631         while (linked_next_ptr != -1)
632         {
633                 linked_next_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
634                 eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", feSlotID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
635                 linked_next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
636         }
637
638         eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
639         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
640         {
641                 int prev = -1;
642                 int next = -1;
643                 long prev_ptr = -1;
644                 long next_ptr = -1;
645                 it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
646                 it->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, next_ptr);
647                 if (prev_ptr != -1)
648                 {
649                         eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
650                         prev = feSlotID(prev_fe);
651                 }
652
653                 if (next_ptr != -1)
654                 {
655                         eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
656                         next = feSlotID(next_fe);
657                 }
658                 
659                 eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %2d, inuse : %d, enabled : %d, fbc : %d, prev : %2d, cur : %2d, next : %2d", feSlotID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, feSlotID(it), next);
660         }
661
662         eSmartPtrList<eDVBRegisteredFrontend> &simulate_frontends = m_res_mgr->m_simulate_frontend;
663         for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(simulate_frontends.begin()); it != simulate_frontends.end(); ++it)
664         {
665                 int prev = -1;
666                 int next = -1;
667                 long prev_ptr = -1;
668                 long next_ptr = -1;
669                 it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
670                 it->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, next_ptr);
671                 if (prev_ptr != -1)
672                 {
673                         eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
674                         prev = feSlotID(prev_fe);
675                 }
676
677                 if (next_ptr != -1)
678                 {
679                         eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
680                         next = feSlotID(next_fe);
681                 }
682                 
683                 eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %2d, inuse : %d, enabled : %d, fbc : %d, prev : %2d, cur : %2d, next : %2d (simulate)", feSlotID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, feSlotID(it), next);
684         }
685 }
686