DVBSocketController.cc

Go to the documentation of this file.
00001 // $Id: DVBSocketController.cc 1772 2011-03-10 12:45:21Z tho $
00002 //
00003 // Copyright (C) 2007
00004 // Fraunhofer (FOKUS)
00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY
00006 //     Anton Gillert <atx@berlios.de>
00007 //
00008 // This program is free software; you can redistribute it and/or modify
00009 // it under the terms of the GNU General Public License as published by
00010 // the Free Software Foundation; either version 2 of the License, or
00011 // (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the
00020 // Free Software Foundation, Inc.,
00021 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00026 #include "DVBSocketController.hh"
00027 
00028 // Custom includes
00029 #include <sstream>
00030 #include <senf/Utils/Exception.hh>
00031 #include <senf/Utils/Logger/Logger.hh>
00032 #include <senf/Utils/membind.hh>
00033 #include <senf/Utils/Console/ParsedCommand.hh>
00034 #include <boost/shared_ptr.hpp>
00035 #include "DVBProtocolWrapper.hh"
00036 
00037 #define prefix_
00038 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00039 
00040 unsigned int senf::DVBSocketController::controllerNr(0);
00041 
00042 senf::DVBSocketController::DVBSocketController(DVBFrontendHandle frontendHandle_,
00043                                                const Callback & cb_)
00044     : dir( this ),
00045       frontendHandle( frontendHandle_ ),
00046       type( frontendHandle.protocol().getInfo().type ),
00047       parser( type ),
00048       cb( cb_ ),
00049       sectionNr(1),
00050       pesNr(1),
00051       event( "senf::DVBSocketController::readEvent",
00052              senf::membind(&DVBSocketController::readEvent, this), frontendHandle,
00053              senf::scheduler::FdEvent::EV_PRIO, false )
00054 {
00055     initConsole();
00056 }
00057 
00058 prefix_ senf::DVBSocketController::~DVBSocketController()
00059 {}
00060 
00061 prefix_ senf::DVBDemuxSectionHandle
00062 senf::DVBSocketController::createDVBDemuxSectionHandle(int adapternumber, int demuxnumber,
00063                                                        bool addToConsole)
00064 {
00065     DVBDemuxSectionHandle sectionHandle(adapternumber, demuxnumber);
00066     if (addToConsole)
00067         this->addToConsole(sectionHandle);
00068     return sectionHandle;
00069 
00070 }
00071 
00072 prefix_ senf::DVBDemuxPESHandle
00073 senf::DVBSocketController::createDVBDemuxPESHandle(int adapternumber, int demuxnumber,
00074                                                    bool addToConsole)
00075 {
00076     DVBDemuxPESHandle pesHandle(adapternumber, demuxnumber);
00077     if (addToConsole)
00078         this->addToConsole(pesHandle);
00079     return pesHandle;
00080 
00081 }
00082 
00083 prefix_ void senf::DVBSocketController::addToConsole(senf::DVBDemuxSectionHandle sh)
00084 {
00085     boost::shared_ptr<DVBSectionProtocolWrapper> wrap(new DVBSectionProtocolWrapper(sh));
00086     sh.protocol().addWrapper(wrap);
00087     dir.node().add("section" + senf::str(sectionNr), wrap->dir);
00088     sectionNr++;
00089 }
00090 
00091 prefix_ void senf::DVBSocketController::addToConsole(senf::DVBDemuxPESHandle sh)
00092 {
00093     boost::shared_ptr<DVBPESProtocolWrapper> wrap(new DVBPESProtocolWrapper(sh));
00094     sh.protocol().addWrapper(wrap);
00095     dir.node().add("pes"+ senf::str(pesNr), wrap->dir);
00096     pesNr++;
00097 }
00098 
00099 prefix_ void senf::DVBSocketController::tuneToCMD(std::string const & input, std::string const & mode)
00100 {
00101     struct dvb_frontend_parameters frontend;
00102 
00103     // no valid configline, so it will be treaten like a channel name
00104     if (input.find(":") == std::string::npos)
00105     {
00106         if (mode.c_str()[0]=='a')
00107             tuneTo(input);
00108         else
00109             tuneTo_sync(input);
00110         return;
00111     }
00112     // add psydo name "foo" to complete configline syntax
00113     frontend = parser.getFrontendParam("foo:"+input);
00114 
00115     if (mode.c_str()[0]=='a') {
00116         switch (type) {
00117             case FE_QPSK:
00118                 tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
00119                           frontend.u.qpsk.fec_inner);
00120                 break;
00121             case FE_QAM:
00122                 tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
00123                           frontend.u.qam.fec_inner, frontend.u.qam.modulation);
00124                 break;
00125             case FE_OFDM:
00126                 tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
00127                           frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
00128                           frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
00129                           frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
00130                 break;
00131             default:
00132                 SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
00133         }
00134     }
00135     else {
00136         switch (type) {
00137             case FE_QPSK:
00138                 tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
00139                                frontend.u.qpsk.fec_inner);
00140                 break;
00141             case FE_QAM:
00142                 tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
00143                                frontend.u.qam.fec_inner, frontend.u.qam.modulation);
00144                 break;
00145             case FE_OFDM:
00146                 tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
00147                                frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
00148                                frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
00149                                frontend.u.ofdm.guard_interval,
00150                                frontend.u.ofdm.hierarchy_information);
00151                 break;
00152             default:
00153                 SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
00154         }
00155     }
00156 }
00157 
00158 prefix_ void senf::DVBSocketController::tuneTo(std::string const & channel)
00159 {
00160     struct dvb_frontend_parameters frontend;
00161 
00162     std::string configLine = parser.getConfigLine(channel);
00163 
00164     frontend = parser.getFrontendParam(configLine);
00165     switch (type) {
00166         case FE_QPSK:
00167             tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
00168                       frontend.u.qpsk.fec_inner);
00169             break;
00170         case FE_QAM:
00171             tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
00172                       frontend.u.qam.fec_inner, frontend.u.qam.modulation);
00173             break;
00174         case FE_OFDM:
00175             tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
00176                       frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
00177                       frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
00178                       frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
00179             break;
00180         default:
00181             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
00182     }
00183 }
00184 
00185 prefix_ void senf::DVBSocketController::tuneDVB_T(unsigned int frequency,
00186                 fe_spectral_inversion_t inversion,
00187                 fe_bandwidth_t bandwidth,
00188                 fe_code_rate_t code_rate_HP, /* high priority stream code rate */
00189                 fe_code_rate_t code_rate_LP, /* low priority stream code rate */
00190                 fe_modulation_t constellation, /* modulation type (see above) */
00191                 fe_transmit_mode_t transmission_mode,
00192                 fe_guard_interval_t guard_interval,
00193                 fe_hierarchy_t hierarchy_information
00194                 )
00195 {
00196     if (type != FE_OFDM)
00197         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
00198             << getTypeString() << " for this operation you need a DVB-T Card!";
00199 
00200     event.enable();
00201 
00202     frontendHandle.protocol().setNonBlock();
00203     frontendHandle.protocol().tuneDVB_T(frequency,
00204                 inversion,
00205                 bandwidth,
00206                 code_rate_HP,
00207                 code_rate_LP,
00208                 constellation,
00209                 transmission_mode,
00210                 guard_interval,
00211                 hierarchy_information);
00212 }
00213 
00214 prefix_ void senf::DVBSocketController::tuneDVB_S(unsigned int frequency,
00215                                                   fe_spectral_inversion_t inversion,
00216                                                   unsigned int symbole_rate,
00217                                                   fe_code_rate_t code_rate)
00218 {
00219     if (type != FE_QPSK)
00220         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
00221             << getTypeString() << " for this operation you need a DVB-S Card!";
00222 
00223     event.enable();
00224 
00225     frontendHandle.protocol().setNonBlock();
00226     frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
00227 }
00228 
00229 prefix_ void senf::DVBSocketController::tuneDVB_C(unsigned int frequency,
00230                 fe_spectral_inversion_t inversion,
00231                 unsigned int symbol_rate,
00232                 fe_code_rate_t fec_inner,
00233                 fe_modulation_t modulation
00234                 )
00235 {
00236     if (type != FE_QAM)
00237         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
00238             << getTypeString() << " for this operation you need a DVB-C Card!";
00239 
00240     event.enable();
00241 
00242     frontendHandle.protocol().setNonBlock();
00243 
00244     frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
00245 }
00246 
00247 prefix_ dvb_frontend_event senf::DVBSocketController::tuneTo_sync(std::string const & channel)
00248 {
00249     struct dvb_frontend_parameters frontend;
00250     dvb_frontend_event ev;
00251     std::string configLine = parser.getConfigLine(channel);
00252 
00253     frontend = parser.getFrontendParam(configLine);
00254     switch (type) {
00255         case FE_QPSK:
00256             ev = tuneDVB_S_sync(frontend.frequency, frontend.inversion,
00257                                 frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
00258             break;
00259         case FE_QAM:
00260             ev = tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
00261                                 frontend.u.qam.fec_inner, frontend.u.qam.modulation);
00262             break;
00263         case FE_OFDM:
00264             ev = tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
00265                                 frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
00266                                 frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
00267                                 frontend.u.ofdm.guard_interval,
00268                                 frontend.u.ofdm.hierarchy_information);
00269             break;
00270         default:
00271             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
00272     }
00273     return ev;
00274 }
00275 
00276 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_T_sync(unsigned int frequency,
00277                 fe_spectral_inversion_t inversion,
00278                 fe_bandwidth_t bandwidth,
00279                 fe_code_rate_t code_rate_HP, /* high priority stream code rate */
00280                 fe_code_rate_t code_rate_LP, /* low priority stream code rate */
00281                 fe_modulation_t constellation, /* modulation type (see above) */
00282                 fe_transmit_mode_t transmission_mode,
00283                 fe_guard_interval_t guard_interval,
00284                 fe_hierarchy_t hierarchy_information
00285                 )
00286 {
00287     if (type != FE_OFDM)
00288         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
00289             << getTypeString() << " for this operation you need a DVB-T Card!";
00290 
00291     event.disable();
00292 
00293     frontendHandle.protocol().setNonBlock(false);
00294 
00295     frontendHandle.protocol().tuneDVB_T(frequency,
00296             inversion,
00297             bandwidth,
00298             code_rate_HP,
00299             code_rate_LP,
00300             constellation,
00301             transmission_mode,
00302             guard_interval,
00303             hierarchy_information);
00304 
00305     if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
00306         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
00307 
00308     return frontendHandle.protocol().getEvent();
00309 }
00310 
00311 prefix_ dvb_frontend_event
00312 senf::DVBSocketController::tuneDVB_S_sync(unsigned int frequency,
00313                                           fe_spectral_inversion_t inversion,
00314                                           unsigned int symbole_rate, fe_code_rate_t code_rate)
00315 {
00316     if (type != FE_QPSK)
00317         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
00318             << getTypeString() << " for this operation you need a DVB-S Card!";
00319 
00320     event.disable();
00321 
00322     frontendHandle.protocol().setNonBlock(false);
00323 
00324     frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
00325 
00326     if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
00327         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
00328     return frontendHandle.protocol().getEvent();
00329 }
00330 
00331 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_C_sync(unsigned int frequency,
00332                 fe_spectral_inversion_t inversion,
00333                 unsigned int symbol_rate,
00334                 fe_code_rate_t fec_inner,
00335                 fe_modulation_t modulation
00336                 )
00337 {
00338     if (type != FE_QAM)
00339         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
00340             << getTypeString() << " for this operation you need a DVB-C Card!";
00341 
00342     event.disable();
00343 
00344     frontendHandle.protocol().setNonBlock(false);
00345 
00346     frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
00347     if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
00348         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
00349 
00350     return frontendHandle.protocol().getEvent();
00351 }
00352 
00353 
00354 prefix_ std::string senf::DVBSocketController::getTypeString()
00355 {
00356     switch (type) {
00357         case FE_QPSK:
00358             return "DVB-S";
00359         case FE_QAM:
00360             return "DVB-C";
00361         case FE_OFDM:
00362             return "DVB-T";
00363         default:
00364             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
00365     }
00366 }
00367 
00368 prefix_ unsigned int senf::DVBSocketController::bitErrorRate()
00369 {
00370     return frontendHandle.protocol().bitErrorRate();
00371 }
00372 
00373 prefix_ unsigned int senf::DVBSocketController::signalToNoiseRatio()
00374 {
00375     return frontendHandle.protocol().signalNoiseRatio();
00376 }
00377 
00378 prefix_ unsigned int senf::DVBSocketController::signalStrength()
00379 {
00380     return frontendHandle.protocol().signalStrength();
00381 }
00382 
00383 prefix_ std::string senf::DVBSocketController::getTuneInfo(std::string const & conf)
00384 {
00385     const char* cConf = conf.c_str();
00386     std::stringstream info;
00387 
00388     fe_status_t status;
00389     frontendHandle.protocol().setNonBlock(false);
00390     uint16_t snr, signal;
00391     uint32_t ber, uncorrected_blocks;
00392     status = frontendHandle.protocol().status();
00393     snr = frontendHandle.protocol().signalNoiseRatio();
00394     signal = frontendHandle.protocol().signalStrength();
00395     ber = frontendHandle.protocol().bitErrorRate();
00396     uncorrected_blocks = frontendHandle.protocol().uncorrectedBlocks();
00397 
00398     info << std::hex;
00399 
00400     for (unsigned int i = 0; i < conf.size(); ++i) {
00401         if (i>0)
00402             info << " | ";
00403         switch (cConf[i]) {
00404             case 'S' :
00405                 info << "signal " << signal;
00406                 break;
00407             case 's' :
00408                 info << "snr " << snr;
00409                 break;
00410             case 'b' :
00411                 info << "ber " << ber;
00412                 break;
00413             case 'u' :
00414                 info << "unc " << uncorrected_blocks;
00415                 break;
00416             case 'f' :
00417                 info << "status: " << status2String(status);
00418                 break;
00419             default:
00420                 break;
00421         }
00422     }
00423     return info.str();
00424 }
00425 
00426 prefix_ std::string senf::DVBSocketController::status2String(fe_status_t status)
00427 {
00428     std::string s("");
00429     if (status & FE_HAS_LOCK)
00430         return s += "HAS LOCK";
00431     if (status & FE_HAS_CARRIER)
00432         s += "HAS CARRIER ";
00433     if (status & FE_HAS_VITERBI)
00434         s += "HAS VITERBI ";
00435     if (status & FE_HAS_SYNC)
00436         s += "HAS SYNC ";
00437     if (status & FE_HAS_SIGNAL)
00438         s += "HAS SIGNAL ";
00439     if (status & FE_TIMEDOUT)
00440         s += "TIMED OUT ";
00441     if (status & FE_REINIT)
00442         s += "REINIT ";
00443 
00444     return s;
00445 }
00446 
00447 prefix_ fe_type_t senf::DVBSocketController::getType()
00448 {
00449     return type;
00450 }
00451 
00452 prefix_ void senf::DVBSocketController::readEvent(int event)
00453 {
00454     if (cb)
00455         cb(frontendHandle.protocol().getEvent());
00456 }
00457 
00458 prefix_ void senf::DVBSocketController::initConsole()
00459 {
00460     namespace fty = console::factory;
00461     namespace kw = console::kw;
00462 
00463     dir.doc("DVB Controller " + controllerNr);
00464     ++controllerNr;
00465 
00466     dir.add("type", fty::Command(&DVBSocketController::getTypeString, this)
00467             .doc("Shows actual type of card DVB-{T, S, C}") );
00468 
00469     dir.add("info", fty::Command(&DVBSocketController::getTuneInfo, this)
00470             .doc("Returns a string which shows actual tuning status.\n"
00471                  "'S' prints signal strength (in hex)\n"
00472                  "'s' prints singal to noise ration (in hex)\n"
00473                  "'b' prints bit error rate (in hex)\n"
00474                  "'u' prints uncorrected blocks (in hex)\n"
00475                  "'f' prints readable overal status e.g. 'Has Lock'\n\n"
00476                  "These characters can be used to form the output. Be aware, some\n"
00477                  "features may not be supported be your current driver implementation\n"
00478                  "and could end in throwing an exception!")
00479             .arg("conf", "Ssbuf", kw::default_value = "Ssbuf") );
00480 
00481     dir.add("tune", fty::Command(&DVBSocketController::tuneToCMD, this)
00482             .doc("tunes to channel listet in the configfile.")
00483             .arg("channel", "channel to tune")
00484             .arg("mode", "mode 'sync' or 'async'", kw::default_value = "async") );
00485 }
00486 
00487 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00488 #undef prefix_
00489 
00490 
00491 // Local Variables:
00492 // mode: c++
00493 // fill-column: 100
00494 // c-file-style: "senf"
00495 // indent-tabs-mode: nil
00496 // ispell-local-dictionary: "american"
00497 // compile-command: "scons -u test"
00498 // comment-column: 40
00499 // End: