WirelessInterfaceAPI.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 "WirelessInterfaceAPI.hh"
19 
20 // Custom includes
21 #include <senf/Utils/String.hh>
22 #include <senf/Utils/algorithm.hh>
23 
24 #define prefix_
25 //-/////////////////////////////////////////////////////////////////////////////////////////////////
26 
27 //-/////////////////////////////////////////////////////////////////////////////////////////////////
28 // senf::emu::ModulationParameter & -Registry
29 
30 prefix_ senf::emu::ModulationParameter::ModulationParameter(std::string const & _coding, short _minRssi,
31  unsigned _rate, unsigned _bandwidth, boost::uint8_t _linkTypeId, std::string const & _info)
32  : coding(_coding), minRssi(_minRssi), rate(_rate), bandwidth(_bandwidth), linkTypeId(_linkTypeId), info(_info)
33 {}
34 
36 {
37  parameter.id = boost::uint32_t(parameter.linkTypeId) << 24 | boost::uint32_t(parameter.v_modulationId());
38  if (modulations_.count(parameter.id) == 0)
39  modulations_.insert(parameter.id, parameter.v_clone());
40  return parameter.id;
41 }
42 
44  const
45 {
46  Modulations::const_iterator it (modulations_.find(id));
47  if (it == modulations_.end())
48  throw ModulationParameter::Error() << id << " (unknown id)";
49  return *(it->second);
50 }
51 
53  : senf::Exception("Invalid modulation parameter: ")
54 {}
55 
57  const
58 {
59  os << " id: " << id << std::endl
60  << " coding: " << coding << std::endl
61  << " rate: " << rate << std::endl
62  << "bandwidth: " << bandwidth << std::endl
63  << "min. RSSI: " << minRssi << std::endl;
64  v_dump(os);
65 }
66 
68  const
69 {
70  boost::format fmt ("%10d%1.1s %11.11s %7d %9d %8d ");
71  os << fmt % "id" % "" % "coding" % "rate" % "bandwidth" % "min.RSSI";
72  v_dumpTableHeader(os);
73  os << std::endl;
74 }
75 
76 prefix_ void senf::emu::ModulationParameter::dumpTableRow(std::ostream & os, bool is_current_modulation)
77  const
78 {
79  boost::format fmt ("%10d%1.1s %11.11s %7d %9d %8d ");
80  os << fmt % id % (is_current_modulation ? "*" : "") % coding % rate % bandwidth % minRssi;
81  v_dumpTableRow(os);
82  os << std::endl;
83 }
84 
85 
86 //-/////////////////////////////////////////////////////////////////////////////////////////////////
87 // senf::emu::WirelessInterface
88 
90 {
92 
93  namespace fty = console::factory;
94 
95  consoleDir().add("modulations",
96  fty::Command(&WirelessInterface::listModulations, this)
97  .doc("List wireless parameter configurations.") );
98  consoleDir().add("frequencies",
99  fty::Command(&WirelessInterface::listFrequencies, this)
100  .doc("List wireless frequencies and bandwidths") );
101  consoleDir().add("frequency",
102  fty::Command(SENF_MEMBINDFNP(void, WirelessInterface, frequency, (unsigned)))
103  .arg("frequency", "frequency of new channel")
104  .doc("Change to new channel given by frequency. The bandwidth is not changed.\n"
105  "For valid frequencies and bandwidths, see 'frequencies'") );
106  consoleDir().add("frequency",
107  fty::Command(SENF_MEMBINDFNP(void, WirelessInterface, frequency, (unsigned,unsigned)))
108  .arg("frequency", "frequency of new channel")
109  .arg("bandwidth", "new channel bandwidth")
110  .doc("Change to new channel given by frequency and bandwidth. For valid frequencies and\n"
111  "bandwidths, see 'frequencies'") );
112  consoleDir().add("whitelistedFrequencyRange",
114  .arg("frequencyLower", "frequency interval lower bound")
115  .arg("frequencyUpper", "frequency interval upper bound")
116  .doc("add a whitelisted frequency range") );
117  consoleDir().add("whitelistedChannel",
118  fty::Command(&WirelessInterface::whitelistedChannel, this)
119  .arg("center frequency", "center frequency of the whitelisted channel in kHz")
120  .arg("bandwidth", "bandwidth in kHz")
121  .doc("add a whitelisted channel") );
122  consoleDir().add("clearWhitelistedFrequencies",
124  .doc("clear all configured whitelisted frequencies") );
125  consoleDir().add("coverageRange",
126  fty::Command(&WirelessInterface::coverageRange, this)
127  .arg("distance", "distance in meters")
128  .doc("set coverage range") );
129 }
130 
131 prefix_ void senf::emu::WirelessInterface::listModulations(std::ostream & os)
132  const
133 {
134  ModulationParameterIds const & modIds (modulationParameterIds());
135  if (modIds.empty()) {
136  os << "no modulations configured" << std::endl;
137  return;
138  }
140  ModulationParameter::id_t cmid (0);
141  if (canTransmit()) {
142  cmid = transmitter().modulation();
143  os << "Current modulation: " << std::endl;
144  registry.findModulationById(cmid).dump(os);
145  os << std::endl;
146  }
147  registry.findModulationById( *modIds.begin()).dumpTableHeader(os);
148  for (ModulationParameter::id_t mid : modIds) {
149  registry.findModulationById(mid).dumpTableRow(os, mid==cmid);
150  }
151 }
152 
153 prefix_ void senf::emu::WirelessInterface::listFrequencies(std::ostream & os)
154  const
155 {
156  unsigned bw (bandwidth());
157  unsigned freq (frequency());
158  os << "Frequency: " << freq
159  << "\nBandwidth: " << bw << "\n\n";
160  boost::format fmt ("%3d%1.1s %10d%1.1s%-10d %10d%1.1s%-10d\n");
161  os << fmt
162  % "#" % "" % "FREQ" % "U" % "ENCY" % "BAND" % "W" % "IDTH";
163  unsigned n (0);
164  for (Frequency const & f : frequencies()) {
165  os << fmt
166  % n++
167  % (f.bandwidthLower <= bw && f.bandwidthUpper >= bw &&
168  f.frequencyLower <= freq && f.frequencyUpper >= freq ? "*" : "")
169  % f.frequencyLower
170  % (f.frequencyLower == f.frequencyUpper ? "" : "-")
171  % (f.frequencyLower == f.frequencyUpper ? "" : senf::str(f.frequencyUpper))
172  % f.bandwidthLower
173  % (f.bandwidthLower == f.bandwidthUpper ? "" : "-")
174  % (f.bandwidthLower == f.bandwidthUpper ? "" : senf::str(f.bandwidthUpper));
175  }
176  os << "Whitelisted Frequency Ranges:\n";
177  for (FrequencyInterval const & f : whitelistedFrequencies_) {
178  os << f.first << " - " << f.second << std::endl;
179  }
180 }
181 
182 prefix_ void senf::emu::WirelessInterface::lookupFrequency(unsigned freq, unsigned bw)
183  const
184 {
185  if (! frequency_is_whitelisted(whitelistedFrequencies_)(freq-bw/2, freq+bw/2))
186  throw InvalidArgumentException("invalid freq, bw ") << freq << ", " << bw << " (not whitelisted)";
187 
188  // for h/w wlan we allow fractional bandwidths settings to support 20/40 MHz scans
189  // So just stop here. If the channel is complete bogus, the NL call will fail.
190  // this needs a major cleanup
191  if (dynamic_cast<senf::emu::HardwareWLANInterface const *>(this) != NULL)
192  return;
193 
194  Frequencies::const_iterator i (
195  frequencies_.project<ByLower>(
196  frequencies_.get<ByUpper>().lower_bound(boost::make_tuple(bw, freq))));
197  Frequencies::const_iterator i_end (
198  frequencies_.get<ByLower>().upper_bound(boost::make_tuple(bw, freq)));
199 
200  for (; i != i_end; ++i)
201  if (bw >= i->bandwidthLower && bw <= i->bandwidthUpper &&
202  ((freq == i->frequencyLower && freq == i->frequencyUpper) ||
203  (freq >= i->frequencyLower+bw/2 && freq <= i->frequencyUpper-bw/2)))
204  return;
205 
206  throw InvalidArgumentException("invalid freq, bw ") << freq << ", " << bw;
207 }
208 
209 prefix_ senf::emu::WirelessInterface::frequency_is_whitelisted::frequency_is_whitelisted(FrequencyIntervals const & whitelistedFrequencies)
210  : whitelistedFrequencies_(whitelistedFrequencies)
211 {}
212 
213 prefix_ bool senf::emu::WirelessInterface::frequency_is_whitelisted::operator()(unsigned frequencyLower, unsigned frequencyUpper)
214 {
215  if (whitelistedFrequencies_.empty())
216  return true;
217  for (FrequencyInterval const & freqInterval : whitelistedFrequencies_) {
218  if (freqInterval.first <= frequencyLower && freqInterval.second >= frequencyUpper)
219  return true;
220  }
221  return false;
222 }
223 
224 prefix_ bool senf::emu::WirelessInterface::frequency_is_whitelisted::operator()(Frequency const & frequency)
225 {
226  SENF_ASSERT( frequency.frequencyLower == frequency.frequencyUpper,
227  "complex frequency ranges are not supported for whitelisting. Sorry.");
228  SENF_ASSERT( frequency.bandwidthLower == frequency.bandwidthUpper,
229  "complex frequency ranges are not supported for whitelisting. Sorry.");
230  return operator()( frequency.frequencyLower - frequency.bandwidthLower/2,
231  frequency.frequencyLower + frequency.bandwidthLower/2 );
232 }
233 
234 prefix_ void senf::emu::WirelessInterface::whitelistedFrequencyRange(unsigned frequencyLower, unsigned frequencyUpper)
235 {
236  if (frequencyUpper <= frequencyLower)
237  throw InvalidArgumentException("frequencyUpper (") << frequencyUpper << ") <= frequencyLower (" << frequencyLower << ")";
238  whitelistedFrequencies_.insert( std::make_pair(frequencyLower, frequencyUpper));
239 }
240 
242 {
243  if (frequency < bandwidth/2)
244  throw InvalidArgumentException("frequency (") << frequency << ") < bandwidth/2 (" << bandwidth/2 << ")";
245  whitelistedFrequencies_.insert( std::make_pair(frequency-bandwidth/2, frequency+bandwidth/2));
246 }
247 
249 {
250  whitelistedFrequencies_.clear();
251 }
252 
253 //-/////////////////////////////////////////////////////////////////////////////////////////////////
254 // senf::emu::WirelessTransmitter
255 
257 {
258  Transmitter::init();
259 
260  namespace fty = console::factory;
261 
262  interface().consoleDir()
263  .add("txpower", fty::Command(SENF_MEMBINDFNP(void, WirelessTransmitter, txPower, (int)))
264  .arg("power", "new transmit power")
265  .doc("Set current transmit power. Use 'txpowers' to list valid values or\n"
266  "get the current txpower value.") );
267  interface().consoleDir()
268  .add("txpowers", fty::Command(&WirelessTransmitter::listTxpowers, this)
269  .doc("List valid transmit power values for current parameter configuration.\n"
270  "This lists depends on the selected parameter configuration !\n"
271  "\n"
272  "The unit of the value listed in the POWER column is wireless interface type and\n"
273  "driver dependent.") );
274 }
275 
276 prefix_ void senf::emu::WirelessTransmitter::listTxpowers(std::ostream & os)
277  const
278 {
279  int txp (txPower());
280  os << "txPower: " << txp << "\n\n";
281  boost::format fmt ("%3d%1.1s %9d%1.1s%-9d\n");
282  os << fmt % "#" % "" % "PO" % "W" % "ER";
283  TxPowersRange p (txPowers());
284  unsigned n (0);
285  for (TxPowersRange::iterator i (p.begin()); i != p.end(); ++i, ++n)
286  os << fmt
287  % n
288  % (i->lower <= txp && i->upper >= txp ? "*" : "")
289  % i->lower
290  % (i->lower == i->upper ? "" : "-")
291  % (i->lower == i->upper ? "" : senf::str(i->upper));
292 }
293 
295  const
296 {
297  return v_modulationId();
298 }
299 
301 {
302  if (! senf::contains(interface().modulationParameterIds(), id))
303  throw ModulationParameter::Error() << id;
304  v_modulationId(id);
305 }
306 
308 {
309  txPowers_.insert(TxPower(power, power));
310 }
311 
312 prefix_ void senf::emu::WirelessTransmitter::registerTxPower(int powerLower, int powerUpper)
313 {
314  if (powerLower >= powerUpper)
315  throw InvalidArgumentException("Reversed power parameter in senf::emu::WirelessTransmitter::registerTxPower() ")
316  << powerLower << " >= " << powerUpper;
317  txPowers_.insert(TxPower(powerLower, powerUpper));
318 }
319 
320 //-/////////////////////////////////////////////////////////////////////////////////////////////////
321 #undef prefix_
322 
323 
324 // Local Variables:
325 // mode: c++
326 // fill-column: 100
327 // comment-column: 40
328 // c-file-style: "senf"
329 // indent-tabs-mode: nil
330 // ispell-local-dictionary: "american"
331 // compile-command: "scons -u test"
332 // End:
WirelessInterfaceAPI public header.
unsigned registerModulation(ModulationParameter &parameter)
#define SENF_MEMBINDFNP(ret, cls, fn, args)
unsigned bandwidth
Bandwidth in KHz.
ModulationParameter const & findModulationById(ModulationParameter::id_t id) const
short minRssi
Minimum RSSI value.
Wireless modulation parameter.
Interface API base class specialization for wireless interfaces.
#define prefix_
void whitelistedChannel(unsigned frequency, unsigned bandwidth)
unsigned rate
Bitrate in kbit/s.
void init()
Initialize interface.
Definition: InterfaceAPI.cc:38
console::ScopedDirectory & consoleDir()
void dump(std::ostream &os) const
void coverageRange(unsigned distance)
set the coverage range of the interface in meters
boost::iterator_range< TxPowers::const_iterator > TxPowersRange
unsigned bandwidthLower
Bandwidth interval lower bound.
void dumpTableHeader(std::ostream &os) const
#define SENF_ASSERT(x, comment)
void whitelistedFrequencyRange(unsigned frequencyLower, unsigned frequencyUpper)
static ModulationParameterRegistry & instance()
void dumpTableRow(std::ostream &os, bool is_current_modulation) const
Transmit capable wireless interface base class.
unsigned frequencyLower
Frequency interval lower bound.
ModulationParameter(std::string const &_coding, short _minRssi, unsigned _rate, unsigned _bandwidth, boost::uint8_t _linkTypeId, std::string const &_info="")
unsigned bandwidthUpper
Bandwidth interval upper bound.
ModulationParameter::id_t modulation() const
Get current modulation parameter configuration id.
HardwareWLANInterface public header.
unsigned frequencyUpper
Frequency interval upper bound.
__be16 freq