HardwareDVBInterface.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 "HardwareDVBInterface.hh"
18 
19 // Custom includes
22 
23 #define prefix_
24 //-/////////////////////////////////////////////////////////////////////////////////////////////////
25 
26 //-/////////////////////////////////////////////////////////////////////////////////////////////////
27 // senf::emu::HardwareDVBInterface
28 
30  : frequency_(0), bandwidth_(8000)
31 {
32  // register all known modulations
34  registerModulation( id);
35  }
36  registerFrequencyRange(500000, 750000);
37 }
38 
40 {
43 
44  namespace fty = console::factory;
45  consoleDir().add("registerFrequencyRange", fty::Command(&HardwareDVBInterface::registerFrequencyRange, this) );
46 }
47 
48 prefix_ void senf::emu::HardwareDVBInterface::registerFrequencyRange(unsigned frequencyLower, unsigned frequencyUpper)
49 {
51  registerFrequency(frequencyLower, frequencyUpper, bandwidth_, bandwidth_);
52 }
53 
54 prefix_ void senf::emu::HardwareDVBInterface::v_coverageRange(unsigned distance)
55 {
56  // not supported by DVB
57 }
58 
59 prefix_ unsigned senf::emu::HardwareDVBInterface::v_frequency()
60  const
61 {
62  return frequency_;
63 }
64 
65 prefix_ unsigned senf::emu::HardwareDVBInterface::v_bandwidth()
66  const
67 {
68  return bandwidth_;
69 }
70 
71 prefix_ void senf::emu::HardwareDVBInterface::v_frequency(unsigned freq, unsigned bw)
72 {
73  frequency_ = freq;
74  bandwidth_ = bw;
75 }
76 
79 {
80  ModulationParameter::id_t modId (DVBModulationParameterRegistry::instance().parameterId(fec, mod, gi));
81  DVBModulationParameterRegistry::instance().findModulationById(modId); // will throw if id is unknown
82  modulationId_ = modId;
83  frequency(freq, 8000); // we assume a fixed bandwidth of 8 MHz
84 }
85 
86 
87 //-/////////////////////////////////////////////////////////////////////////////////////////////////
88 // senf::emu::detail::HardwareDVBSenderInterfaceNet
89 
90 prefix_ senf::emu::detail::HardwareDVBSenderInterfaceNet::HardwareDVBSenderInterfaceNet(std::string const & iface)
92 {
93  ppi::connect(forwardSwitch, sink);
94 }
95 
96 //-/////////////////////////////////////////////////////////////////////////////////////////////////
97 // senf::emu::HardwareDVBSenderInterface
98 
100  : HardwareDVBSenderInterfaceNet(iface),
101  WirelessTransmitter( HardwareDVBSenderInterfaceNet::forwardSwitch.input),
102  iface_(iface), ctrl_(iface), txPower_(0)
103 {
106 }
107 
108 prefix_ void senf::emu::HardwareDVBSenderInterface::v_enable()
109 {
110  HardwareDVBSenderInterfaceNet::forwardSwitch.forward(true);
111 }
112 
113 prefix_ void senf::emu::HardwareDVBSenderInterface::v_disable()
114 {
115  HardwareDVBSenderInterfaceNet::forwardSwitch.forward(false);
116 }
117 
118 prefix_ bool senf::emu::HardwareDVBSenderInterface::v_enabled()
119  const
120 {
121  return HardwareDVBSenderInterfaceNet::forwardSwitch.forward();
122 }
123 
124 prefix_ unsigned senf::emu::HardwareDVBSenderInterface::v_mtu()
125  const
126 {
127  return ctrl_.mtu();
128 }
129 
130 prefix_ void senf::emu::HardwareDVBSenderInterface::v_mtu(unsigned v)
131 {
132  ctrl_.mtu(v);
133 }
134 
135 prefix_ void senf::emu::HardwareDVBSenderInterface::v_id(MACAddress const & mac)
136 {
137  throw senf::SystemException(ENOTSUP);
138 }
139 
140 prefix_ senf::MACAddress senf::emu::HardwareDVBSenderInterface::v_id()
141  const
142 {
143  return ctrl_.hardwareAddress();
144 }
145 
146 prefix_ int senf::emu::HardwareDVBSenderInterface::v_txPower()
147  const
148 {
149  return txPower_;
150 }
151 
152 prefix_ void senf::emu::HardwareDVBSenderInterface::v_txPower(int power)
153 {
154  txPower_ = power;
155 }
156 
157 prefix_ senf::emu::ModulationParameter::id_t senf::emu::HardwareDVBSenderInterface::v_modulationId()
158  const
159 {
160  return modulationId_;
161 }
162 
163 prefix_ void senf::emu::HardwareDVBSenderInterface::v_modulationId(ModulationParameter::id_t id)
164 {
165  DVBModulationParameterRegistry::instance().findModulationById( id); // will throw if id is unknown
166  modulationId_ = id;
167 }
168 
169 prefix_ std::string const & senf::emu::HardwareDVBSenderInterface::v_device()
170  const
171 {
172  return iface_;
173 }
174 
175 
176 //-/////////////////////////////////////////////////////////////////////////////////////////////////
177 // senf::emu::detail::ActiveDVBSocketSource
178 
179 prefix_ senf::emu::detail::ActiveDVBSocketSource::ActiveDVBSocketSource(Handle handle)
180  : handle_(handle), event_(handle_, senf::ppi::IOEvent::Read|senf::ppi::IOEvent::Err)
181 {
182  registerEvent( event_, &ActiveDVBSocketSource::read );
183  route(event_, output);
184 }
185 
186 prefix_ void senf::emu::detail::ActiveDVBSocketSource::read(senf::ppi::IOEvent::Event event)
187 {
188  if (event.events & ppi::IOEvent::Err) {
189  SENF_LOG((senf::log::IMPORTANT) ("Error on read event. Ignored."));
190  return;
191  }
192 
193  MPESection mpe;
194  try {
195  mpe = reader_(handle_);
196  } catch (SystemException const & e) {
197  switch (e.errorNumber()) {
198 // case ECRC:
199 // SENF_LOG((senf::log::MESSAGE) ("Last section had a CRC error. Ignored."));
200 // return;
201  case EOVERFLOW:
202  SENF_LOG((senf::log::IMPORTANT) ("Overflow. The filtered data was not read from the buffer in due time. Ignored."));
203  return;
204  default:
205  throw e;
206  }
207  }
208 
209  outputMPE2Eth( mpe);
210 }
211 
212 prefix_ void senf::emu::detail::ActiveDVBSocketSource::outputMPE2Eth(MPESection mpein)
213 {
214  if (mpein.size() < MPESectionType::initSize()) {
215  SENF_LOG((senf::log::IMPORTANT)("insufficient MPE section packet size: " << mpein.size() << "."));
216  return;
217  }
218  if (mpein.size() != mpein->section_length() + 3) {
219  SENF_LOG((senf::log::IMPORTANT)("length field value differ packet size: length=" << mpein->section_length() << " size=" << mpein.size() << "."));
220  }
221  if (mpein->crc() == mpein.parser().calcCrc()) {
222  if (mpein->llc_snap_flag()) {
223  try {
224  output.write(mpein.find<EthernetPacket>());
225  } catch (SystemException const & e) {
226  SENF_LOG((senf::log::NOTICE)("discarding invalid MPE section. Size of section is " << mpein.size() << "."));
227  SENF_LOG((senf::log::VERBOSE)("The exception thrown was: " << e.what()));
228  }
229  }
230  } else {
231  SENF_LOG((senf::log::NOTICE)("discarding MPE section because of CRC mismatch. CRC is" << mpein->crc()));
232  }
233 }
234 
235 //-/////////////////////////////////////////////////////////////////////////////////////////////////
236 // senf::emu::detail::InterfaceAnnotator
237 
238 prefix_ senf::emu::detail::DVBReceiverInterfaceAnnotator::DVBReceiverInterfaceAnnotator(
239  HardwareDVBReceiverInterface const & interface, DVBSocketController const & dvbSocketCtrl)
240  : interface_(interface), dvbSocketCtrl_(dvbSocketCtrl), lastSNRUpdate_(0)
241 {
242  route(input, output);
243  input.onRequest(&DVBReceiverInterfaceAnnotator::request);
244 }
245 
246 #define DEFAULT_DVB_NOISE -110
247 
248 prefix_ void senf::emu::detail::DVBReceiverInterfaceAnnotator::request()
249 {
250  Packet p (input());
251  p.annotation<annotations::Timestamp>().fromWallClock();
252  p.annotation<annotations::Interface>().value = interface_.id();
253  if (lastSNRUpdate_ + ClockService::seconds(1) < scheduler::now())
254  snr_ = dvbSocketCtrl_.signalToNoiseRatio();
255  {
256  emu::annotations::Quality & q (p.annotation<emu::annotations::Quality>());
257  q.noise = DEFAULT_DVB_NOISE;
258  q.snr = snr_;
259  q.rssi = snr_ + q.noise;
260  q.flags.frameLength = p.size();
261  }
262  output(p);
263 }
264 
265 //-/////////////////////////////////////////////////////////////////////////////////////////////////
266 // senf::emu::detail::HardwareDVBReceiverInterfaceNet
267 
268 prefix_ senf::emu::detail::HardwareDVBReceiverInterfaceNet::HardwareDVBReceiverInterfaceNet()
269  : dvbSourceHandle( 0, 0),
270  dvbControlHandle( 0, 0),
271  dvbStuffingHandle( 0, 0),
272  dvbSource( dvbSourceHandle),
273  annotator(self(), self().dvbController)
274 {
275  ppi::connect(dvbSource, annotator);
276  ppi::connect(annotator, forwardSwitch);
277 }
278 
279 prefix_ void senf::emu::detail::HardwareDVBReceiverInterfaceNet::initHandle()
280 {
281  dvbSourceHandle.protocol().setBufferSize( 256*4096);
282  dvbSourceHandle.protocol().setSectionFilter( self().tsPid_);
283  dvbControlHandle.protocol().setBufferSize( 256*4096);
284  dvbControlHandle.protocol().setPESFilter( self().stuffingPid_, DMX_IN_FRONTEND, DMX_OUT_TS_TAP, DMX_PES_OTHER, 0);
285 // controlHandle_.protocol().setPESFilter(DEFAULT_DVB_STUFFING_PID,DMX_IN_FRONTEND,DMX_OUT_TS_TAP,DMX_PES_OTHER,DMX_IMMEDIATE_START);
286 }
287 
288 prefix_ senf::emu::HardwareDVBReceiverInterface const & senf::emu::detail::HardwareDVBReceiverInterfaceNet::self()
289  const
290 {
291  return *static_cast<HardwareDVBReceiverInterface const *>(this);
292 }
293 
294 //-/////////////////////////////////////////////////////////////////////////////////////////////////
295 // senf::emu::HardwareDVBReceiverInterface
296 
298  : WirelessReceiver( HardwareDVBReceiverInterfaceNet::forwardSwitch.output),
299  ifaceIdFactory_( new SimpleInterfaceIdFactory()), id_(ifaceIdFactory_->getId()), stuffingPid_(8190),
300  dvbController( DVBFrontendHandle(0, 0), membind(&HardwareDVBReceiverInterface::tuneEvent, this)),
301  dev_("DVB-Receiver")
302 {
305 
306  namespace fty = console::factory;
307  consoleDir().add("tsPID", fty::Variable(tsPid_)
308  .onChange(membind(&HardwareDVBReceiverInterface::tsPidChanged, this)) );
309  consoleDir().add("stuffingPID", fty::Variable(stuffingPid_));
310  consoleDir().add("dvb", dvbController.dir).doc( "Configure DVB device");
311  consoleDir().add("tune", fty::Command(
312  SENF_MEMBINDFNP(void, HardwareDVBReceiverInterface, tune, (std::string const &))) );
313 
314  dvbController.addToConsole(dvbSourceHandle);
315  dvbController.addToConsole(dvbControlHandle);
316 }
317 
318 prefix_ int senf::emu::HardwareDVBReceiverInterface::tsPidChanged(int oldPid)
319 {
320  HardwareDVBReceiverInterfaceNet::initHandle();
321  return tsPid_;
322 }
323 
324 prefix_ bool senf::emu::HardwareDVBReceiverInterface::v_promisc()
325  const
326 {
327  return true;
328 }
329 
330 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_promisc(bool v)
331 {
332  if (!v)
333  throw InvalidArgumentException("promisc mode cannot be disabled.");
334 }
335 
336 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_annotationMode(bool a)
337 {
338  throw InvalidArgumentException("annotation mode not implemented.");
339 }
340 
341 prefix_ bool senf::emu::HardwareDVBReceiverInterface::v_annotationMode()
342  const
343 {
344  return false;
345 }
346 
347 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_mcAdd(MACAddress const & address)
348 {
349  throw SystemException(ENOTSUP);
350 }
351 
352 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_mcDrop(MACAddress const & address)
353 {
354  throw SystemException(ENOTSUP);
355 }
356 
357 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_enable()
358 {
359  HardwareDVBReceiverInterfaceNet::forwardSwitch.forward(true);
360 }
361 
362 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_disable()
363 {
364  HardwareDVBReceiverInterfaceNet::forwardSwitch.forward(false);
365 }
366 
367 prefix_ bool senf::emu::HardwareDVBReceiverInterface::v_enabled()
368  const
369 {
370  return HardwareDVBReceiverInterfaceNet::forwardSwitch.forward();
371 }
372 
373 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_id(MACAddress const & mac)
374 {
375  ifaceIdFactory_->releaseId( id_);
376  id_ = mac;
377 }
378 
379 prefix_ senf::MACAddress senf::emu::HardwareDVBReceiverInterface::v_id()
380  const
381 {
382  return id_;
383 }
384 
385 prefix_ std::string const & senf::emu::HardwareDVBReceiverInterface::v_device()
386  const
387 {
388  return dev_;
389 }
390 
391 
392 prefix_ boost::shared_ptr<senf::emu::InterfaceIdFactoryBase> senf::emu::HardwareDVBReceiverInterface::ifaceIdFactory()
393 {
394  return ifaceIdFactory_;
395 }
396 
397 prefix_ void senf::emu::HardwareDVBReceiverInterface::ifaceIdFactory(boost::shared_ptr<InterfaceIdFactoryBase> factory)
398 {
399  ifaceIdFactory_->releaseId( id_);
400  ifaceIdFactory_ = factory;
401  id_ = MACAddress::None;
402  id( ifaceIdFactory_->getId());
403 }
404 
405 prefix_ void senf::emu::HardwareDVBReceiverInterface::tuneEvent(struct dvb_frontend_event const & ev)
406 {
407  // TODO: make sure that tuning is successful or otherwise report an error
408  SENF_LOG((senf::log::MESSAGE) ("DVB device tune event received: status=" << dvbController.status2String(ev.status))) ;
409 }
410 
411 prefix_ void senf::emu::HardwareDVBReceiverInterface::v_tune(DVBModulationParameter::fec_rate_t fec,
413 {
414  dvbController.tuneDVB_T(
415  frequency,
416  INVERSION_AUTO,
417  BANDWIDTH_8_MHZ, // we assume a fixed bandwidth of 8 MHz
418  fe_code_rate_t(fec), // high priority stream code rate
419  fe_code_rate_t(fec), // low priority stream code rate
420  fe_modulation_t(mod), // modulation type
421  TRANSMISSION_MODE_8K,
422  fe_guard_interval_t(gi),
423  HIERARCHY_NONE );
424  HardwareDVBInterface::v_tune(fec, mod, gi, frequency);
425 }
426 
427 prefix_ void senf::emu::HardwareDVBReceiverInterface::tune(std::string const & channelName)
428 {
429  DVBConfigParser parser (FE_OFDM);
430  struct dvb_frontend_parameters frontend (parser.getFrontendParam(
431  parser.getConfigLine(channelName) ));
432  tune(
433  DVBModulationParameter::fec_rate_t(frontend.u.ofdm.code_rate_HP),
434  DVBModulationParameter::modulation_t(frontend.u.ofdm.constellation),
435  DVBModulationParameter::guard_interval_t(frontend.u.ofdm.guard_interval),
436  frontend.frequency);
437 }
438 
439 //-/////////////////////////////////////////////////////////////////////////////////////////////////
440 #undef prefix_
static MACAddress const None
#define SENF_MEMBINDFNP(ret, cls, fn, args)
std::uint8_t mac[6]
console::ScopedDirectory dir
int errorNumber() const
void registerFrequency(unsigned frequency, unsigned bandwidth)
register single frequency/bandwidth combination
unspecified_keyword_type parser
static DVBModulationParameterRegistry & instance()
Definition: DVBInterface.hh:77
std::string status2String(fe_status_t status)
#define DEFAULT_DVB_NOISE
static SENF_CLOCKSERVICE_CONSTEXPR clock_type seconds(int64_type const &v)
ModulationParameter::id_t modulationId_
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
Annotations public header.
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)
HardwareDVBInterface public header.
console::DirectoryNode & consoleDir() const
Access interface console directory.
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)
unsigned frequency() const
Get current channel frequency.
Receive capable wireless interface base class.
virtual void v_tune(DVBModulationParameter::fec_rate_t fec, DVBModulationParameter::modulation_t mod, DVBModulationParameter::guard_interval_t gi, unsigned frequency)
MACAddress const & id() const
Get interface MAC Address.
DVBModulationParameter const & findModulationById(ModulationParameter::id_t id) const
void addToConsole(DVBDemuxSectionHandle sh)
ppi::connector::PassiveInputJack< EthernetPacket > input
MACAddress hardwareAddress() const
virtual char const * what() const
static PacketParserBase::size_type initSize()
HardwareDVBSenderInterface(std::string const &iface)
Transmit capable wireless interface base class.
ConcretePacket< MPESectionType > MPESection
ConcretePacket< EthernetPacketType > EthernetPacket
#define SENF_LOG(args)
void clearRegisteredFrequencies()
remove all registered frequencies
#define prefix_
void registerModulation(ModulationParameter::id_t id)
register modulation configuration
__be16 freq
boost::shared_ptr< InterfaceIdFactoryBase > ifaceIdFactory()