DVBSocketController.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
17 #include "DVBSocketController.hh"
18 
19 // Custom includes
20 #include <sstream>
21 #include <senf/Utils/Exception.hh>
23 #include <senf/Utils/membind.hh>
25 #include <boost/shared_ptr.hpp>
26 #include "DVBProtocolWrapper.hh"
27 
28 #define prefix_
29 //-/////////////////////////////////////////////////////////////////////////////////////////////////
30 
31 unsigned int senf::DVBSocketController::controllerNr(0);
32 
34  const Callback & cb_)
35  : frontendHandle( frontendHandle_ ),
36  type( frontendHandle.protocol().getInfo().type ),
37  parser( type ),
38  cb( cb_ ),
39  sectionNr(1),
40  pesNr(1),
41  event( "senf::DVBSocketController::readEvent",
42  senf::membind(&DVBSocketController::readEvent, this), frontendHandle,
43  senf::scheduler::FdEvent::EV_PRIO, false )
44 {
45  initConsole();
46 }
47 
49 {}
50 
52 senf::DVBSocketController::createDVBDemuxSectionHandle(int adapternumber, int demuxnumber,
53  bool addToConsole)
54 {
55  DVBDemuxSectionHandle sectionHandle(adapternumber, demuxnumber);
56  if (addToConsole)
57  this->addToConsole(sectionHandle);
58  return sectionHandle;
59 
60 }
61 
63 senf::DVBSocketController::createDVBDemuxPESHandle(int adapternumber, int demuxnumber,
64  bool addToConsole)
65 {
66  DVBDemuxPESHandle pesHandle(adapternumber, demuxnumber);
67  if (addToConsole)
68  this->addToConsole(pesHandle);
69  return pesHandle;
70 
71 }
72 
74 {
75  boost::shared_ptr<DVBSectionProtocolWrapper> wrap(new DVBSectionProtocolWrapper(sh));
76  sh.protocol().addWrapper(wrap);
77  dir.node().add("section" + senf::str(sectionNr), wrap->dir);
78  sectionNr++;
79 }
80 
82 {
83  boost::shared_ptr<DVBPESProtocolWrapper> wrap(new DVBPESProtocolWrapper(sh));
84  sh.protocol().addWrapper(wrap);
85  dir.node().add("pes"+ senf::str(pesNr), wrap->dir);
86  pesNr++;
87 }
88 
89 prefix_ void senf::DVBSocketController::tuneToCMD(std::string const & input, std::string const & mode)
90 {
91  struct dvb_frontend_parameters frontend;
92 
93  // no valid configline, so it will be treaten like a channel name
94  if (input.find(":") == std::string::npos)
95  {
96  if (mode.c_str()[0]=='a')
97  tuneTo(input);
98  else
99  tuneTo_sync(input);
100  return;
101  }
102  // add psydo name "foo" to complete configline syntax
103  frontend = parser.getFrontendParam("foo:"+input);
104 
105  if (mode.c_str()[0]=='a') {
106  switch (type) {
107  case FE_QPSK:
108  tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
109  frontend.u.qpsk.fec_inner);
110  break;
111  case FE_QAM:
112  tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
113  frontend.u.qam.fec_inner, frontend.u.qam.modulation);
114  break;
115  case FE_OFDM:
116  tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
117  frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
118  frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
119  frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
120  break;
121  default:
122  SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
123  }
124  }
125  else {
126  switch (type) {
127  case FE_QPSK:
128  tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
129  frontend.u.qpsk.fec_inner);
130  break;
131  case FE_QAM:
132  tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
133  frontend.u.qam.fec_inner, frontend.u.qam.modulation);
134  break;
135  case FE_OFDM:
136  tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
137  frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
138  frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
139  frontend.u.ofdm.guard_interval,
140  frontend.u.ofdm.hierarchy_information);
141  break;
142  default:
143  SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
144  }
145  }
146 }
147 
148 prefix_ void senf::DVBSocketController::tuneTo(std::string const & channel)
149 {
150  struct dvb_frontend_parameters frontend;
151 
152  std::string configLine = parser.getConfigLine(channel);
153 
154  frontend = parser.getFrontendParam(configLine);
155  switch (type) {
156  case FE_QPSK:
157  tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
158  frontend.u.qpsk.fec_inner);
159  break;
160  case FE_QAM:
161  tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
162  frontend.u.qam.fec_inner, frontend.u.qam.modulation);
163  break;
164  case FE_OFDM:
165  tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
166  frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
167  frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
168  frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
169  break;
170  default:
171  SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
172  }
173 }
174 
175 prefix_ void senf::DVBSocketController::tuneDVB_T(unsigned int frequency,
176  fe_spectral_inversion_t inversion,
177  fe_bandwidth_t bandwidth,
178  fe_code_rate_t code_rate_HP, /* high priority stream code rate */
179  fe_code_rate_t code_rate_LP, /* low priority stream code rate */
180  fe_modulation_t constellation, /* modulation type (see above) */
181  fe_transmit_mode_t transmission_mode,
182  fe_guard_interval_t guard_interval,
183  fe_hierarchy_t hierarchy_information
184  )
185 {
186  if (type != FE_OFDM)
187  SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
188  << getTypeString() << " for this operation you need a DVB-T Card!";
189 
190  event.enable();
191 
192  frontendHandle.protocol().setNonBlock();
193  frontendHandle.protocol().tuneDVB_T(frequency,
194  inversion,
195  bandwidth,
196  code_rate_HP,
197  code_rate_LP,
198  constellation,
199  transmission_mode,
200  guard_interval,
201  hierarchy_information);
202 }
203 
204 prefix_ void senf::DVBSocketController::tuneDVB_S(unsigned int frequency,
205  fe_spectral_inversion_t inversion,
206  unsigned int symbole_rate,
207  fe_code_rate_t code_rate)
208 {
209  if (type != FE_QPSK)
210  SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
211  << getTypeString() << " for this operation you need a DVB-S Card!";
212 
213  event.enable();
214 
215  frontendHandle.protocol().setNonBlock();
216  frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
217 }
218 
219 prefix_ void senf::DVBSocketController::tuneDVB_C(unsigned int frequency,
220  fe_spectral_inversion_t inversion,
221  unsigned int symbol_rate,
222  fe_code_rate_t fec_inner,
223  fe_modulation_t modulation
224  )
225 {
226  if (type != FE_QAM)
227  SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
228  << getTypeString() << " for this operation you need a DVB-C Card!";
229 
230  event.enable();
231 
232  frontendHandle.protocol().setNonBlock();
233 
234  frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
235 }
236 
237 prefix_ dvb_frontend_event senf::DVBSocketController::tuneTo_sync(std::string const & channel)
238 {
239  struct dvb_frontend_parameters frontend;
240  dvb_frontend_event ev;
241  std::string configLine = parser.getConfigLine(channel);
242 
243  frontend = parser.getFrontendParam(configLine);
244  switch (type) {
245  case FE_QPSK:
246  ev = tuneDVB_S_sync(frontend.frequency, frontend.inversion,
247  frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
248  break;
249  case FE_QAM:
250  ev = tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
251  frontend.u.qam.fec_inner, frontend.u.qam.modulation);
252  break;
253  case FE_OFDM:
254  ev = tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
255  frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
256  frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
257  frontend.u.ofdm.guard_interval,
258  frontend.u.ofdm.hierarchy_information);
259  break;
260  default:
261  SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
262  }
263  return ev;
264 }
265 
266 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_T_sync(unsigned int frequency,
267  fe_spectral_inversion_t inversion,
268  fe_bandwidth_t bandwidth,
269  fe_code_rate_t code_rate_HP, /* high priority stream code rate */
270  fe_code_rate_t code_rate_LP, /* low priority stream code rate */
271  fe_modulation_t constellation, /* modulation type (see above) */
272  fe_transmit_mode_t transmission_mode,
273  fe_guard_interval_t guard_interval,
274  fe_hierarchy_t hierarchy_information
275  )
276 {
277  if (type != FE_OFDM)
278  SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
279  << getTypeString() << " for this operation you need a DVB-T Card!";
280 
281  event.disable();
282 
283  frontendHandle.protocol().setNonBlock(false);
284 
285  frontendHandle.protocol().tuneDVB_T(frequency,
286  inversion,
287  bandwidth,
288  code_rate_HP,
289  code_rate_LP,
290  constellation,
291  transmission_mode,
292  guard_interval,
293  hierarchy_information);
294 
295  if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
296  SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
297 
298  return frontendHandle.protocol().getEvent();
299 }
300 
301 prefix_ dvb_frontend_event
303  fe_spectral_inversion_t inversion,
304  unsigned int symbole_rate, fe_code_rate_t code_rate)
305 {
306  if (type != FE_QPSK)
307  SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
308  << getTypeString() << " for this operation you need a DVB-S Card!";
309 
310  event.disable();
311 
312  frontendHandle.protocol().setNonBlock(false);
313 
314  frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
315 
316  if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
317  SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
318  return frontendHandle.protocol().getEvent();
319 }
320 
321 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_C_sync(unsigned int frequency,
322  fe_spectral_inversion_t inversion,
323  unsigned int symbol_rate,
324  fe_code_rate_t fec_inner,
325  fe_modulation_t modulation
326  )
327 {
328  if (type != FE_QAM)
329  SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
330  << getTypeString() << " for this operation you need a DVB-C Card!";
331 
332  event.disable();
333 
334  frontendHandle.protocol().setNonBlock(false);
335 
336  frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
337  if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
338  SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
339 
340  return frontendHandle.protocol().getEvent();
341 }
342 
343 
345 {
346  switch (type) {
347  case FE_QPSK:
348  return "DVB-S";
349  case FE_QAM:
350  return "DVB-C";
351  case FE_OFDM:
352  return "DVB-T";
353  default:
354  SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
355  }
356 }
357 
359  const
360 {
361  return frontendHandle.protocol().bitErrorRate();
362 }
363 
365  const
366 {
367  return frontendHandle.protocol().signalNoiseRatio();
368 }
369 
371  const
372 {
373  return frontendHandle.protocol().signalStrength();
374 }
375 
376 prefix_ std::string senf::DVBSocketController::getTuneInfo(std::string const & conf)
377 {
378  const char* cConf = conf.c_str();
379  std::stringstream info;
380 
381  fe_status_t status;
382  frontendHandle.protocol().setNonBlock(false);
383  uint16_t snr, signal;
384  uint32_t ber, uncorrected_blocks;
385  status = frontendHandle.protocol().status();
386  snr = frontendHandle.protocol().signalNoiseRatio();
387  signal = frontendHandle.protocol().signalStrength();
388  ber = frontendHandle.protocol().bitErrorRate();
389  uncorrected_blocks = frontendHandle.protocol().uncorrectedBlocks();
390 
391  info << std::hex;
392 
393  for (unsigned int i = 0; i < conf.size(); ++i) {
394  if (i>0)
395  info << " | ";
396  switch (cConf[i]) {
397  case 'S' :
398  info << "signal " << signal;
399  break;
400  case 's' :
401  info << "snr " << snr;
402  break;
403  case 'b' :
404  info << "ber " << ber;
405  break;
406  case 'u' :
407  info << "unc " << uncorrected_blocks;
408  break;
409  case 'f' :
410  info << "status: " << status2String(status);
411  break;
412  default:
413  break;
414  }
415  }
416  return info.str();
417 }
418 
419 prefix_ std::string senf::DVBSocketController::status2String(fe_status_t status)
420 {
421  std::string s("");
422  if (status & FE_HAS_LOCK)
423  return s += "HAS LOCK";
424  if (status & FE_HAS_CARRIER)
425  s += "HAS CARRIER ";
426  if (status & FE_HAS_VITERBI)
427  s += "HAS VITERBI ";
428  if (status & FE_HAS_SYNC)
429  s += "HAS SYNC ";
430  if (status & FE_HAS_SIGNAL)
431  s += "HAS SIGNAL ";
432  if (status & FE_TIMEDOUT)
433  s += "TIMED OUT ";
434  if (status & FE_REINIT)
435  s += "REINIT ";
436 
437  return s;
438 }
439 
441 {
442  return type;
443 }
444 
445 prefix_ void senf::DVBSocketController::readEvent(int event)
446 {
447  if (cb)
448  cb(frontendHandle.protocol().getEvent());
449 }
450 
451 prefix_ void senf::DVBSocketController::initConsole()
452 {
453  namespace fty = console::factory;
454  namespace kw = console::kw;
455 
456  dir.doc("DVB Controller " + senf::str(controllerNr));
457  ++controllerNr;
458 
459  dir.add("type", fty::Command(&DVBSocketController::getTypeString, this)
460  .doc("Shows actual type of card DVB-{T, S, C}") );
461 
462  dir.add("info", fty::Command(&DVBSocketController::getTuneInfo, this)
463  .doc("Returns a string which shows actual tuning status.\n"
464  "'S' prints signal strength (in hex)\n"
465  "'s' prints singal to noise ration (in hex)\n"
466  "'b' prints bit error rate (in hex)\n"
467  "'u' prints uncorrected blocks (in hex)\n"
468  "'f' prints readable overal status e.g. 'Has Lock'\n\n"
469  "These characters can be used to form the output. Be aware, some\n"
470  "features may not be supported be your current driver implementation\n"
471  "and could end in throwing an exception!")
472  .arg("conf", "Ssbuf", kw::default_value = "Ssbuf") );
473 
474  dir.add("tune", fty::Command(&DVBSocketController::tuneToCMD, this)
475  .doc("tunes to channel listet in the configfile.")
476  .arg("channel", "channel to tune")
477  .arg("mode", "mode 'sync' or 'async'", kw::default_value = "async") );
478 }
479 
480 //-/////////////////////////////////////////////////////////////////////////////////////////////////
481 #undef prefix_
482 
483 
484 // Local Variables:
485 // mode: c++
486 // fill-column: 100
487 // c-file-style: "senf"
488 // indent-tabs-mode: nil
489 // ispell-local-dictionary: "american"
490 // compile-command: "scons -u test"
491 // comment-column: 40
492 // End:
dvb_frontend_event tuneDVB_C_sync(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbol_rate, fe_code_rate_t fec_inner, fe_modulation_t modulation)
Tunes a DVB-C device.
Protocol & protocol()
Access the protocol interface.
void tuneTo(std::string const &channel)
Tunes a DVB device to a channel.
#define SENF_THROW_SYSTEM_EXCEPTION(desc)
uint32_t bitErrorRate() const
Returns the current bit error rate for the signal.
void tuneDVB_C(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbol_rate, fe_code_rate_t fec_inner, fe_modulation_t modulation)
Tunes a DVB-C device.
boost::function< void(const struct dvb_frontend_event &)> Callback
Callback which is called when an asynchronous tuning succeeds.
dvb_frontend_event tuneTo_sync(std::string const &channel)
Tunes a DVB device given by the type of the DVBFrontendHandle.
dvb_frontend_event tuneDVB_T_sync(unsigned int frequency, fe_spectral_inversion_t inversion, fe_bandwidth_t bandwidth, fe_code_rate_t code_rate_HP, fe_code_rate_t code_rate_LP, fe_modulation_t constellation, fe_transmit_mode_t transmission_mode, fe_guard_interval_t guard_interval, fe_hierarchy_t hierarsourcechy_information)
Tunes a DVB-T device.
Helperclass for configuration and controlling DVB devices.
console::ScopedDirectory dir
u8 type
unspecified_keyword_type parser
fe_type_t getType()
Returns the type of the card. The type is defined in frontend.h.
dvb_frontend_event tuneDVB_S_sync(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate)
Tunes a DVB-S device.
DVBDemuxPESHandle createDVBDemuxPESHandle(int adapternumber=0, int demuxnumber=0, bool addToConsole=false)
std::string status2String(fe_status_t status)
Returns a human readable status information.
static SENF_CLOCKSERVICE_CONSTEXPR clock_type seconds(int64_type const &v)
std::string getTypeString()
Returns the type of the card.
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
DVBSocketController(DVBFrontendHandle frontendHandle_=DVBFrontendHandle(0, 0), const Callback &cb=NULL)
void tuneDVB_T(unsigned int frequency, fe_spectral_inversion_t inversion, fe_bandwidth_t bandwidth, fe_code_rate_t code_rate_HP, fe_code_rate_t code_rate_LP, fe_modulation_t constellation, fe_transmit_mode_t transmission_mode, fe_guard_interval_t guard_interval, fe_hierarchy_t hierarchy_information)
Tunes a DVB-T device.
DirectoryNode & doc(std::string const &doc)
unsigned int signalToNoiseRatio() const
Returns the signal to noise ratio.
DVBDemuxSectionHandle createDVBDemuxSectionHandle(int adapternumber=0, int demuxnumber=0, bool addToConsole=false)
bool waitOOBReadable(senf::ClockService::clock_type timeout=senf::ClockService::clock_type(-1)) const
Wait, until read of prioritized data on the handle does not block (ignoring blocking state) ...
StatsDataCollectorKernel signal
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
unsigned int bitErrorRate() const
Returns the bit error rate.
dvb_frontend_event getEvent() const
fe_status_t status() const
This ioctl call returns status information about the front-end.
void tuneDVB_T(unsigned int frequency, fe_spectral_inversion_t inversion, fe_bandwidth_t bandwidth, fe_code_rate_t code_rate_HP, fe_code_rate_t code_rate_LP, fe_modulation_t constellation, fe_transmit_mode_t transmission_mode, fe_guard_interval_t guard_interval, fe_hierarchy_t hierarchy_information) const
Tunes a DVB-T device.
Helperclass for configuration and controlling DVB protocol handles.
DirectoryNode & node() const
void tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate)
Tunes a DVB-S device.
dvb_frontend_parameters getFrontendParam(std::string configLine)
unsigned int signalStrength() const
Returns the signal strength.
void addToConsole(DVBDemuxSectionHandle sh)
Adds an DVBDemuxSectionHandle to the console.
void tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate) const
Tunes a DVB-S device.
void tuneDVB_C(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbol_rate, fe_code_rate_t fec_inner, fe_modulation_t modulation) const
Tunes a DVB-C device.
std::string getConfigLine(std::string channel)
std::string getTuneInfo(const std::string &conf="Ssbuf")
Returns a string which shows actual tuning status.
void setNonBlock(bool on=true) const
int16_t signalNoiseRatio() const
Returns current signal-to-noise ratio.
uint32_t uncorrectedBlocks() const
Returns the number of uncorrected blocks.
int16_t signalStrength() const
Returns current signal strength.
#define prefix_
void tuneToCMD(std::string const &input, std::string const &mode="async")
Tunes a DVB device given by the type of the DVBFrontendHandle.
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)