2 #include <lib/dvb/fbc.h>
3 #include <lib/dvb/dvb.h>
4 #include <lib/dvb/sec.h>
5 #include <lib/base/object.h>
13 #define eFecDebug(arg...) eDebug(arg)
15 #define eFecDebug(arg...)
18 static int getProcData(const char* filename)
21 FILE *fp = fopen(filename,"r");
24 fscanf(fp, "%d", &res);
29 eFecDebug("[*][eFBCTunerManager::getProcData] open failed, %s: %m", filename);
34 static void setProcData(const char* filename, int value)
36 eDebug("[*] setProcData %s -> %d", filename, value);
37 FILE *fp = fopen(filename, "w");
40 fprintf(fp, "%d", value);
45 eFecDebug("[*][eFBCTunerManager::setProcData] open failed, %s: %m", filename);
49 static void loadConnectChoices(const char* filename, bool *connect_choices)
51 FILE *fp = fopen(filename,"r");
55 while(EOF != (c = fgetc(fp)))
58 connect_choices[c - '0'] = true;
64 eFecDebug("[*][eFBCTunerManager::LoadFbcRootChoices] open failed, %s: %m", filename);
69 DEFINE_REF(eFBCTunerManager);
71 eFBCTunerManager* eFBCTunerManager::m_instance = (eFBCTunerManager*)0;
73 eFBCTunerManager* eFBCTunerManager::getInstance()
78 eFBCTunerManager::eFBCTunerManager(ePtr<eDVBResourceManager> res_mgr)
84 eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_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 */
95 int prevFbcSetID = -1;
98 bool connect_choices[32] = {false};
100 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
102 // continue for DVB-C FBC Tuner
103 if (!(it->m_frontend->supportsDeliverySystem(SYS_DVBS, false) || it->m_frontend->supportsDeliverySystem(SYS_DVBS2, false)))
106 int fe_id = feSlotID(it);
107 snprintf(tmp, sizeof(tmp), "/proc/stb/frontend/%d", fe_id);
109 fbcSetID = getProcData(std::string(proc_fe + "/fbc_set_id").c_str());
112 if (prevFbcSetID != fbcSetID)
114 prevFbcSetID = fbcSetID;
115 memset(connect_choices, 0, sizeof(connect_choices));
116 loadConnectChoices(std::string(proc_fe + "/fbc_connect_choices").c_str(), connect_choices);
117 fbcIndex =0; // reset
121 if (fbcIndex < sizeof(connect_choices)/sizeof(connect_choices[0]))
123 isRoot = connect_choices[fbcIndex];
126 initFbcId = isRoot ? fbcIndex : 0;
128 FBC_TUNER elem = {fbcSetID, fbcIndex, isRoot, initFbcId};
129 m_fbc_tuners[fe_id] = elem;
131 /* set default fbc ID */
132 setProcFBCID(fe_id, initFbcId, false);
134 /* enable fbc tuner */
135 it->m_frontend->setFBCTuner(true);
142 eFBCTunerManager::~eFBCTunerManager()
144 if (m_instance == this)
148 int eFBCTunerManager::setProcFBCID(int fe_id, int fbc_connect, bool is_linked)
150 eFecDebug("[*][eFBCTunerManager::setProcFBCID] %d -> %d", fe_id, fbc_connect);
154 sprintf(filename, "/proc/stb/frontend/%d/fbc_connect", fe_id);
155 setProcData(filename, fbc_connect);
158 sprintf(filename, "/proc/stb/frontend/%d/fbc_link", fe_id);
159 setProcData(filename, (int)is_linked);
165 int eFBCTunerManager::feSlotID(const eDVBRegisteredFrontend *fe) const
167 return fe->m_frontend->getSlotID();
170 void eFBCTunerManager::setDefaultFBCID(eDVBRegisteredFrontend *fe)
172 int fe_id = feSlotID(fe);
173 setProcFBCID(fe_id, getDefaultFBCID(fe_id), isLinked(fe));
176 void eFBCTunerManager::updateFBCID(eDVBRegisteredFrontend *next_fe, eDVBRegisteredFrontend *prev_fe)
178 setProcFBCID(feSlotID(next_fe), getFBCID(feSlotID(getTop(prev_fe))), isLinked(next_fe));
181 bool eFBCTunerManager::isLinked(eDVBRegisteredFrontend *fe) const
184 long linked_prev_ptr = -1;
185 fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
186 return (linked_prev_ptr != -1);
189 bool eFBCTunerManager::isUnicable(eDVBRegisteredFrontend *fe) const
191 int slot_idx = feSlotID(fe);
192 bool is_unicable = false;
194 ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
195 for (int idx=0; idx <= sec->m_lnbidx; ++idx )
197 eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
198 if ( lnb_param.m_slot_mask & (1 << slot_idx) )
200 is_unicable = lnb_param.SatCR_idx != -1;
207 bool eFBCTunerManager::isFeUsed(eDVBRegisteredFrontend *fe, bool a_simulate) const
212 bool simulate = !a_simulate;
214 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
215 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
217 if (feSlotID(it) == feSlotID(fe))
219 return (it->m_inuse >0);
223 eDebug("[*][eFBCTunerManager::isFeUsed] ERROR! can not found fe ptr (feid : %d, simulate : %d)", feSlotID(fe), simulate);
227 bool eFBCTunerManager::isSameFbcSet(int fe_a, int fe_b)
229 return m_fbc_tuners[fe_a].fbcSetID == m_fbc_tuners[fe_b].fbcSetID;
232 bool eFBCTunerManager::isRootFe(eDVBRegisteredFrontend *fe)
234 return m_fbc_tuners[feSlotID(fe)].isRoot;
237 int eFBCTunerManager::getFBCID(int fe_id)
239 return m_fbc_tuners[fe_id].fbcIndex;
242 int eFBCTunerManager::getDefaultFBCID(int fe_id)
244 return m_fbc_tuners[fe_id].initFbcId;
247 int eFBCTunerManager::getFBCSetID(int fe_id)
249 return m_fbc_tuners[fe_id].fbcSetID;
252 eDVBRegisteredFrontend *eFBCTunerManager::getPrev(eDVBRegisteredFrontend *fe) const
254 eDVBRegisteredFrontend *prev_fe = NULL;
255 long linked_prev_ptr = -1;
256 fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
257 if (linked_prev_ptr != -1)
258 prev_fe = (eDVBRegisteredFrontend *)linked_prev_ptr;
262 eDVBRegisteredFrontend *eFBCTunerManager::getNext(eDVBRegisteredFrontend *fe) const
264 eDVBRegisteredFrontend *next_fe = NULL;
265 long linked_next_ptr = -1;
266 fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
267 if (linked_next_ptr != -1)
268 next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
272 eDVBRegisteredFrontend *eFBCTunerManager::getTop(eDVBRegisteredFrontend *fe) const
274 eDVBRegisteredFrontend *prev_fe = fe;
275 long linked_prev_ptr = -1;
276 fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
277 while(linked_prev_ptr != -1)
279 prev_fe = (eDVBRegisteredFrontend *)linked_prev_ptr;
280 prev_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
285 eDVBRegisteredFrontend *eFBCTunerManager::getLast(eDVBRegisteredFrontend *fe) const
287 eDVBRegisteredFrontend *next_fe = fe;
288 long linked_next_ptr = -1;
289 fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
290 while(linked_next_ptr != -1)
292 next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
293 next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
298 eDVBRegisteredFrontend *eFBCTunerManager::getSimulFe(eDVBRegisteredFrontend *fe) const
300 eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_simulate_frontend;
302 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); it++)
303 if (feSlotID(*it) == feSlotID(fe))
306 return((eDVBRegisteredFrontend *)0);
309 void eFBCTunerManager::connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
312 eFecDebug(" [*][eFBCTunerManager::connectLink] connect %d->%d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), feSlotID(next_fe), simulate?"(simulate)":"");
314 eFecDebug(" [*][eFBCTunerManager::connectLink] connect %d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), simulate?"(simulate)":"");
316 prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
317 link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
320 link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
321 next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)link_fe);
325 void eFBCTunerManager::disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
328 eFecDebug(" [*][eFBCTunerManager::disconnectLink] disconnect %d->%d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), feSlotID(next_fe), simulate?"(simulate)":"");
330 eFecDebug(" [*][eFBCTunerManager::disconnectLink] disconnect %d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), simulate?"(simulate)":"");
334 prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
335 next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
337 link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
338 link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
342 prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
343 link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
347 int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *&fbc_fe, bool simulate)
351 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
352 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
354 if (!it->m_frontend->is_FBCTuner())
360 if(!it->m_frontend->getEnabled())
363 if(!isSameFbcSet(feSlotID(link_fe), feSlotID(it)))
366 if(it->m_inuse == 0) // No link to a fe not in use.
369 if(isLinked(*it)) // No link to a fe linked to another.
375 eDVBRegisteredFrontend *top_fe = *it;
376 eDVBRegisteredFrontend *prev_fe = getLast(top_fe);
379 connectLink(link_fe, prev_fe, NULL, simulate);
381 /* enable linked fe */
382 link_fe->m_frontend->setEnabled(true);
385 updateLNBSlotMask(feSlotID(link_fe), feSlotID(*it), false);
388 int c = link_fe->m_frontend->isCompatibleWith(feparm);
392 fbc_fe = (eDVBRegisteredFrontend *)*it;
395 eFecDebug("[*][eFBCTunerManager::isCompatibleWith] score : %d (%d->%d)", c, feSlotID(it), feSlotID(link_fe));
397 ASSERT(!getNext(link_fe));
398 ASSERT(getPrev(link_fe));
399 ASSERT(getLast(top_fe) == link_fe);
401 /* disconnect link */
402 disconnectLink(link_fe, prev_fe, NULL, simulate);
404 /* disable linked fe */
405 link_fe->m_frontend->setEnabled(false);
407 /* remove slot mask*/
408 updateLNBSlotMask(feSlotID(link_fe), feSlotID(top_fe), true);
411 eFecDebug("[*][eFBCTunerManager::isCompatibleWith] fe : %p(%d), score : %d %s", link_fe, feSlotID(link_fe), best_score, simulate?"(simulate)":"");
416 /* attach link_fe to tail of fe linked list */
417 void eFBCTunerManager::addLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate)
419 //printLinks(link_fe);
421 eFecDebug(" [*][eFBCTunerManager::addLink] addLink : %p(%d)->%p(%d) %s", top_fe, feSlotID(top_fe), link_fe, feSlotID(link_fe), simulate?"(simulate)":"");
423 eDVBRegisteredFrontend *next_fe = NULL;
424 eDVBRegisteredFrontend *prev_fe = NULL;
426 if(isRootFe(link_fe) || !isRootFe(top_fe))
429 /* search prev/next fe */
434 next_fe = getNext(prev_fe);
435 if ((next_fe == NULL) || (feSlotID(next_fe) > feSlotID(link_fe)))
440 connectLink(link_fe, prev_fe, next_fe, simulate);
442 /* enable linked fe */
443 link_fe->m_frontend->setEnabled(true);
445 /* simulate connect */
448 eDVBRegisteredFrontend *simulate_prev_fe = NULL;
449 eDVBRegisteredFrontend *simulate_link_fe = NULL;
450 eDVBRegisteredFrontend *simulate_next_fe = NULL;
452 simulate_prev_fe = getSimulFe(prev_fe);
453 simulate_link_fe = getSimulFe(link_fe);
456 simulate_next_fe = getSimulFe(next_fe);
458 eFecDebug(" [*][eFBCTunerManager::addLink] simulate fe : %p -> %p -> %p", simulate_prev_fe, simulate_link_fe, simulate_next_fe);
460 connectLink(simulate_link_fe, simulate_prev_fe, simulate_next_fe, !simulate);
462 /* enable simulate linked fe */
463 simulate_link_fe->m_frontend->setEnabled(true);
466 /* set proc fbc_id */
468 setProcFBCID(feSlotID(link_fe), getFBCID(feSlotID(top_fe)), isLinked(link_fe));
471 updateLNBSlotMask(feSlotID(link_fe), feSlotID(top_fe), false);
473 //printLinks(link_fe);
476 /* if fe, fe_simulated is unused, unlink current frontend from linked things. */
477 /* all unused linked fbc fe must be unlinked! */
478 void eFBCTunerManager::unLink(eDVBRegisteredFrontend *link_fe)
480 bool simulate = link_fe->m_frontend->is_simulate();
481 eFecDebug(" [*][eFBCTunerManager::unLink] fe id : %p(%d) %s", link_fe, feSlotID(link_fe), simulate?"(simulate)":"");
483 if (isRootFe(link_fe) || isFeUsed(link_fe, simulate) || isUnicable(link_fe) || !isLinked(link_fe))
485 eFecDebug(" [*][eFBCTunerManager::unLink] skip..");
489 //printLinks(link_fe);
491 eDVBRegisteredFrontend *prev_fe = getPrev(link_fe);
492 eDVBRegisteredFrontend *next_fe = getNext(link_fe);
496 disconnectLink(link_fe, prev_fe, next_fe, simulate);
498 /* disable linked fe */
499 link_fe->m_frontend->setEnabled(false);
501 /* simulate disconnect */
504 eDVBRegisteredFrontend *simulate_prev_fe = NULL;
505 eDVBRegisteredFrontend *simulate_link_fe = NULL;
506 eDVBRegisteredFrontend *simulate_next_fe = NULL;
508 simulate_prev_fe = getSimulFe(prev_fe);
509 simulate_link_fe = getSimulFe(link_fe);
512 simulate_next_fe = getSimulFe(next_fe);
514 disconnectLink(simulate_link_fe, simulate_prev_fe, simulate_next_fe, !simulate);
516 /* enable simulate linked fe */
517 simulate_link_fe->m_frontend->setEnabled(false);
520 /* set default proc fbc_id */
521 //setDefaultFBCID(link_fe);
523 /* remove slot mask*/
524 updateLNBSlotMask(feSlotID(link_fe), feSlotID(getTop(prev_fe)), true);
526 //printLinks(link_fe);
529 int eFBCTunerManager::updateLNBSlotMask(int dest_slot, int src_slot, bool remove)
531 ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
533 int sec_lnbidx = sec->m_lnbidx;
536 for (int idx=0; idx <= sec_lnbidx; ++idx )
538 eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
539 if ( lnb_param.m_slot_mask & (1 << src_slot) )
541 eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] m_slot_mask : %d", lnb_param.m_slot_mask);
544 lnb_param.m_slot_mask |= (1 << dest_slot);
546 lnb_param.m_slot_mask &= ~(1 << dest_slot);
548 eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] changed m_slot_mask : %d", lnb_param.m_slot_mask);
554 eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] src %d not found", src_slot);
559 bool eFBCTunerManager::canLink(eDVBRegisteredFrontend *fe)
561 return !(isRootFe(fe) || getPrev(fe) || getNext(fe) || isUnicable(fe));
564 int eFBCTunerManager::getLinkedSlotID(int fe_id) const
567 eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
568 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
570 if(it->m_frontend->getSlotID() == fe_id)
573 it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
576 eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
577 link = feSlotID(prev_fe);
583 eFecDebug(" [*][eFBCTunerManager::getLinkedSlotID] fe_id : %d, link : %d", fe_id, link);
588 bool eFBCTunerManager::isFBCLink(int fe_id)
591 std::map<int, FBC_TUNER>::iterator it = m_fbc_tuners.find(fe_id);
592 if (it != m_fbc_tuners.end())
594 res = !it->second.isRoot;
599 void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe) const
601 long linked_prev_ptr = -1;
602 eDVBRegisteredFrontend *linked_prev_fe = fe;
603 fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
604 while (linked_prev_ptr != -1)
606 linked_prev_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
607 linked_prev_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
610 long linked_next_ptr = -1;
611 eDVBRegisteredFrontend *linked_next_fe = linked_prev_fe;
612 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());
613 linked_prev_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
614 while (linked_next_ptr != -1)
616 linked_next_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
617 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());
618 linked_next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
621 eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
622 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
628 it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
629 it->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, next_ptr);
632 eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
633 prev = feSlotID(prev_fe);
638 eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
639 next = feSlotID(next_fe);
642 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);
645 eSmartPtrList<eDVBRegisteredFrontend> &simulate_frontends = m_res_mgr->m_simulate_frontend;
646 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(simulate_frontends.begin()); it != simulate_frontends.end(); ++it)
652 it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
653 it->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, next_ptr);
656 eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
657 prev = feSlotID(prev_fe);
662 eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
663 next = feSlotID(next_fe);
666 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);