2013-11-16 02:14:33 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
|
|
|
|
*
|
2019-07-22 10:05:52 +00:00
|
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
|
|
*
|
2013-11-16 02:14:33 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Transceiver.h"
|
|
|
|
#include "radioDevice.h"
|
2018-12-12 15:03:38 +00:00
|
|
|
#include "Utils.h"
|
2013-11-16 02:14:33 +00:00
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
2018-10-23 11:12:17 +00:00
|
|
|
#include <getopt.h>
|
2017-06-29 13:35:22 +00:00
|
|
|
#include <sched.h>
|
Add support to set Rx/TxAntenna
Some devices have different Rx or Tx ports with different RF characteristics.
For instance LimeSDR has H (High), L (Low) and W (Wide) band Rx ports,
each of one being more suitable to a specific range of frequencies.
In case one wants to support several GSM bands, the best option is to
use the WideBand port and connect the antenna physically to that port in
the board. Then the firmware must be instructed ro read from that port.
Support for Rx/Tx port configuration is already in there for all the
layers (Limesuite, SoapySDR, SoapyUHD, UHD), but we are missing the
required bits in osmo-trx to make use of the available UHD API. This
commit addresses it.
Before this patch, the Rx/Tx paths configured could be changed by means
of the LimeSuiteGUI app, but after running osmo-trx, the values were
changed to the default ones.
One can now start using osmo-trx with 1 channel and specific Rx/Tx ports
by using for instance: osmo-trx -c 1 -y BAND1 -z LNAW
Default behaviour if no specific path or an empry path is passed ("") is
to do the same as preiously, ie. nothing by not calling the
set{T,R}xAntenna APIs.
One can also configure only specific channels, for instance to configure
only the first Tx channel and the second Rx channel:
osmo-trx -c 2 -y BAND1, -z ,LNAW
Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
2018-02-05 12:05:06 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
|
|
|
#include <sstream>
|
|
|
|
#include <iostream>
|
2019-03-29 18:20:06 +00:00
|
|
|
#include <sys/signalfd.h>
|
2013-11-16 02:14:33 +00:00
|
|
|
|
|
|
|
#include <GSMCommon.h>
|
|
|
|
#include <Logger.h>
|
|
|
|
|
2017-03-15 17:09:35 +00:00
|
|
|
extern "C" {
|
2018-02-21 19:15:47 +00:00
|
|
|
#include <osmocom/core/talloc.h>
|
2018-02-21 19:15:18 +00:00
|
|
|
#include <osmocom/core/application.h>
|
2018-02-21 19:15:47 +00:00
|
|
|
#include <osmocom/core/msgb.h>
|
2018-02-20 15:48:15 +00:00
|
|
|
#include <osmocom/core/stats.h>
|
|
|
|
#include <osmocom/vty/logging.h>
|
|
|
|
#include <osmocom/vty/ports.h>
|
|
|
|
#include <osmocom/vty/misc.h>
|
|
|
|
#include <osmocom/vty/telnet_interface.h>
|
|
|
|
#include <osmocom/ctrl/control_vty.h>
|
|
|
|
#include <osmocom/ctrl/ports.h>
|
|
|
|
#include <osmocom/ctrl/control_if.h>
|
|
|
|
#include <osmocom/vty/stats.h>
|
2018-06-15 13:19:21 +00:00
|
|
|
#include <osmocom/vty/command.h>
|
2020-07-29 16:05:25 +00:00
|
|
|
#include <osmocom/vty/cpu_sched_vty.h>
|
2018-06-15 13:19:21 +00:00
|
|
|
|
2017-03-15 17:09:35 +00:00
|
|
|
#include "convolve.h"
|
|
|
|
#include "convert.h"
|
2018-02-20 15:48:15 +00:00
|
|
|
#include "trx_vty.h"
|
|
|
|
#include "debug.h"
|
2018-09-03 14:50:49 +00:00
|
|
|
#include "osmo_signal.h"
|
2019-05-24 14:54:19 +00:00
|
|
|
#include "trx_rate_ctr.h"
|
2017-03-15 17:09:35 +00:00
|
|
|
}
|
|
|
|
|
2018-02-20 15:48:15 +00:00
|
|
|
#define DEFAULT_CONFIG_FILE "osmo-trx.cfg"
|
2013-11-16 02:14:33 +00:00
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
#define charp2str(a) ((a) ? std::string(a) : std::string(""))
|
|
|
|
|
|
|
|
static char* config_file = (char*)DEFAULT_CONFIG_FILE;
|
2013-11-16 02:14:33 +00:00
|
|
|
|
2019-03-29 18:20:06 +00:00
|
|
|
struct osmo_fd signal_ofd;
|
2013-11-16 02:14:33 +00:00
|
|
|
volatile bool gshutdown = false;
|
|
|
|
|
2018-02-21 19:15:47 +00:00
|
|
|
static void *tall_trx_ctx;
|
2018-02-20 15:48:15 +00:00
|
|
|
static struct trx_ctx *g_trx_ctx;
|
|
|
|
static struct ctrl_handle *g_ctrlh;
|
2018-02-21 19:15:47 +00:00
|
|
|
|
2018-02-21 10:59:26 +00:00
|
|
|
static RadioDevice *usrp;
|
|
|
|
static RadioInterface *radio;
|
|
|
|
|
2013-11-16 02:14:33 +00:00
|
|
|
/* Create radio interface
|
|
|
|
* The interface consists of sample rate changes, frequency shifts,
|
|
|
|
* channel multiplexing, and other conversions. The transceiver core
|
|
|
|
* accepts input vectors sampled at multiples of the GSM symbol rate.
|
|
|
|
* The radio interface connects the main transceiver with the device
|
|
|
|
* object, which may be operating some other rate.
|
|
|
|
*/
|
2018-02-21 17:47:35 +00:00
|
|
|
RadioInterface *makeRadioInterface(struct trx_ctx *trx,
|
2013-11-16 02:14:33 +00:00
|
|
|
RadioDevice *usrp, int type)
|
|
|
|
{
|
|
|
|
RadioInterface *radio = NULL;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case RadioDevice::NORMAL:
|
2018-02-21 17:47:35 +00:00
|
|
|
radio = new RadioInterface(usrp, trx->cfg.tx_sps,
|
|
|
|
trx->cfg.rx_sps, trx->cfg.num_chans);
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
|
|
|
case RadioDevice::RESAMP_64M:
|
|
|
|
case RadioDevice::RESAMP_100M:
|
2018-02-21 17:47:35 +00:00
|
|
|
radio = new RadioInterfaceResamp(usrp, trx->cfg.tx_sps,
|
|
|
|
trx->cfg.rx_sps);
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
2016-06-24 21:25:39 +00:00
|
|
|
case RadioDevice::MULTI_ARFCN:
|
2018-02-21 17:47:35 +00:00
|
|
|
radio = new RadioInterfaceMulti(usrp, trx->cfg.tx_sps,
|
|
|
|
trx->cfg.rx_sps, trx->cfg.num_chans);
|
2016-06-24 21:25:39 +00:00
|
|
|
break;
|
2013-11-16 02:14:33 +00:00
|
|
|
default:
|
|
|
|
LOG(ALERT) << "Unsupported radio interface configuration";
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!radio->init(type)) {
|
|
|
|
LOG(ALERT) << "Failed to initialize radio interface";
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return radio;
|
|
|
|
}
|
|
|
|
|
2018-09-03 14:50:49 +00:00
|
|
|
/* Callback function to be called every time we receive a signal from TRANSC */
|
|
|
|
static int transc_sig_cb(unsigned int subsys, unsigned int signal,
|
|
|
|
void *handler_data, void *signal_data)
|
|
|
|
{
|
|
|
|
switch (signal) {
|
2019-06-04 10:39:28 +00:00
|
|
|
case S_MAIN_STOP_REQUIRED:
|
2018-09-03 14:50:49 +00:00
|
|
|
gshutdown = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-16 02:14:33 +00:00
|
|
|
/* Create transceiver core
|
|
|
|
* The multi-threaded modem core operates at multiples of the GSM rate of
|
|
|
|
* 270.8333 ksps and consists of GSM specific modulation, demodulation,
|
|
|
|
* and decoding schemes. Also included are the socket interfaces for
|
|
|
|
* connecting to the upper layer stack.
|
|
|
|
*/
|
2018-02-21 17:47:35 +00:00
|
|
|
int makeTransceiver(struct trx_ctx *trx, RadioInterface *radio)
|
2013-11-16 02:14:33 +00:00
|
|
|
{
|
|
|
|
VectorFIFO *fifo;
|
|
|
|
|
2020-10-13 15:27:08 +00:00
|
|
|
transceiver = new Transceiver(&trx->cfg, GSM::Time(3,0), radio);
|
|
|
|
if (!transceiver->init()) {
|
2013-11-16 02:14:33 +00:00
|
|
|
LOG(ALERT) << "Failed to initialize transceiver";
|
2018-02-21 10:59:26 +00:00
|
|
|
return -1;
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
for (size_t i = 0; i < trx->cfg.num_chans; i++) {
|
2013-11-16 02:14:33 +00:00
|
|
|
fifo = radio->receiveFIFO(i);
|
2018-02-21 10:59:26 +00:00
|
|
|
if (fifo && transceiver->receiveFIFO(fifo, i))
|
2013-11-16 02:14:33 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
LOG(ALERT) << "Could not attach FIFO to channel " << i;
|
2018-02-21 10:59:26 +00:00
|
|
|
return -1;
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
2018-02-21 10:59:26 +00:00
|
|
|
return 0;
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void sig_handler(int signo)
|
|
|
|
{
|
2019-03-29 17:36:30 +00:00
|
|
|
|
|
|
|
if (gshutdown)
|
|
|
|
/* We are in the middle of shutdown process, avoid any kind of extra
|
|
|
|
action like printing */
|
|
|
|
return;
|
|
|
|
|
2019-08-14 14:26:45 +00:00
|
|
|
fprintf(stderr, "signal %d received\n", signo);
|
2018-02-21 19:15:18 +00:00
|
|
|
switch (signo) {
|
|
|
|
case SIGINT:
|
|
|
|
case SIGTERM:
|
2019-08-14 14:26:45 +00:00
|
|
|
fprintf(stderr, "shutting down\n");
|
2018-02-21 19:15:18 +00:00
|
|
|
gshutdown = true;
|
|
|
|
break;
|
2018-02-21 19:15:47 +00:00
|
|
|
case SIGABRT:
|
2020-11-25 16:50:21 +00:00
|
|
|
/* in case of abort, we want to obtain a talloc report and
|
|
|
|
* then run default SIGABRT handler, who will generate coredump
|
|
|
|
* and abort the process. abort() should do this for us after we
|
|
|
|
* return, but program wouldn't exit if an external SIGABRT is
|
|
|
|
* received.
|
|
|
|
*/
|
|
|
|
talloc_report(tall_trx_ctx, stderr);
|
|
|
|
talloc_report_full(tall_trx_ctx, stderr);
|
|
|
|
signal(SIGABRT, SIG_DFL);
|
|
|
|
raise(SIGABRT);
|
|
|
|
break;
|
2018-02-21 19:15:47 +00:00
|
|
|
case SIGUSR1:
|
|
|
|
talloc_report(tall_trx_ctx, stderr);
|
|
|
|
talloc_report_full(tall_trx_ctx, stderr);
|
|
|
|
break;
|
|
|
|
case SIGUSR2:
|
|
|
|
talloc_report_full(tall_trx_ctx, stderr);
|
|
|
|
break;
|
2019-03-29 18:20:06 +00:00
|
|
|
case SIGHUP:
|
|
|
|
log_targets_reopen();
|
2018-02-21 19:15:18 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-03-29 18:20:06 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int signalfd_callback(struct osmo_fd *ofd, unsigned int what)
|
|
|
|
{
|
|
|
|
struct signalfd_siginfo fdsi;
|
|
|
|
ssize_t s;
|
|
|
|
|
|
|
|
s = read(ofd->fd, &fdsi, sizeof(struct signalfd_siginfo));
|
|
|
|
if (s < 0) {
|
|
|
|
LOG(FATAL) << "Failed to read from signalfd ("<< ofd->fd << "): " << errno;
|
|
|
|
gshutdown = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
sig_handler(fdsi.ssi_signo);
|
|
|
|
return 0;
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void setup_signal_handlers()
|
|
|
|
{
|
2019-03-29 18:20:06 +00:00
|
|
|
sigset_t set;
|
|
|
|
int sfd;
|
|
|
|
|
2018-02-21 19:15:18 +00:00
|
|
|
signal(SIGABRT, &sig_handler);
|
|
|
|
osmo_init_ignore_signals();
|
2019-03-29 18:20:06 +00:00
|
|
|
|
|
|
|
/* Other threads created by this thread (main) will inherit a copy of the
|
|
|
|
signal mask. */
|
|
|
|
sigemptyset(&set);
|
|
|
|
sigaddset(&set, SIGINT);
|
|
|
|
sigaddset(&set, SIGTERM);
|
|
|
|
sigaddset(&set, SIGUSR1);
|
|
|
|
sigaddset(&set, SIGUSR2);
|
|
|
|
sigaddset(&set, SIGHUP);
|
|
|
|
if (pthread_sigmask(SIG_BLOCK, &set, NULL)) {
|
|
|
|
fprintf(stderr, "pthread_sigmask() failed.\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((sfd = signalfd(-1, &set, 0)) == -1) {
|
|
|
|
fprintf(stderr, "signalfd() failed (%d).\n", errno);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2020-05-09 16:54:17 +00:00
|
|
|
osmo_fd_setup(&signal_ofd, sfd, OSMO_FD_READ, signalfd_callback, NULL, 0);
|
2019-04-02 09:45:04 +00:00
|
|
|
if (osmo_fd_register(&signal_ofd) < 0) {
|
|
|
|
fprintf(stderr, "osmo_fd_register() failed.\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void print_help()
|
|
|
|
{
|
2020-10-23 22:32:26 +00:00
|
|
|
printf( "Some useful options:\n"
|
|
|
|
" -h, --help This text\n"
|
|
|
|
" -C, --config Filename The config file to use\n"
|
|
|
|
" -V, --version Print the version of OsmoTRX\n"
|
|
|
|
"\nVTY reference generation:\n"
|
|
|
|
" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n"
|
|
|
|
" --vty-ref-xml Generate the VTY reference XML output and exit.\n"
|
2018-02-20 19:01:10 +00:00
|
|
|
);
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
static void print_deprecated(char opt)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Cmd line option '" << opt << "' is deprecated and will be soon removed."
|
|
|
|
<< " Please use VTY cfg option instead."
|
2018-07-20 20:03:39 +00:00
|
|
|
<< " All cmd line options are already being overridden by VTY options if set.";
|
2018-02-21 17:47:35 +00:00
|
|
|
}
|
|
|
|
|
2020-10-23 22:32:26 +00:00
|
|
|
static void handle_long_options(const char *prog_name, const int long_option)
|
|
|
|
{
|
|
|
|
static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
|
|
|
|
|
|
|
|
switch (long_option) {
|
|
|
|
case 1:
|
|
|
|
vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
|
|
|
|
if (vty_ref_mode < 0) {
|
|
|
|
fprintf(stderr, "%s: Unknown VTY reference generation "
|
|
|
|
"mode '%s'\n", prog_name, optarg);
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
|
|
|
|
get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
|
|
|
|
get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
|
|
|
|
vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
|
|
|
|
exit(0);
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
static void handle_options(int argc, char **argv, struct trx_ctx* trx)
|
2013-11-16 02:14:33 +00:00
|
|
|
{
|
|
|
|
int option;
|
2018-02-21 17:47:35 +00:00
|
|
|
unsigned int i;
|
|
|
|
std::vector<std::string> rx_paths, tx_paths;
|
|
|
|
bool rx_paths_set = false, tx_paths_set = false;
|
2020-10-09 18:47:12 +00:00
|
|
|
static int long_option = 0;
|
2018-10-23 11:12:17 +00:00
|
|
|
static struct option long_options[] = {
|
|
|
|
{"help", 0, 0, 'h'},
|
|
|
|
{"config", 1, 0, 'C'},
|
|
|
|
{"version", 0, 0, 'V'},
|
2020-10-23 22:32:26 +00:00
|
|
|
{"vty-ref-mode", 1, &long_option, 1},
|
|
|
|
{"vty-ref-xml", 0, &long_option, 2},
|
2018-10-23 11:12:17 +00:00
|
|
|
{NULL, 0, 0, 0}
|
|
|
|
};
|
2013-11-16 02:14:33 +00:00
|
|
|
|
2018-10-23 11:12:17 +00:00
|
|
|
while ((option = getopt_long(argc, argv, "ha:l:i:j:p:c:dmxgfo:s:b:r:A:R:Set:y:z:C:V", long_options,
|
|
|
|
NULL)) != -1) {
|
2013-11-16 02:14:33 +00:00
|
|
|
switch (option) {
|
|
|
|
case 'h':
|
|
|
|
print_help();
|
|
|
|
exit(0);
|
|
|
|
break;
|
2020-10-09 18:47:12 +00:00
|
|
|
case 0:
|
2020-10-23 22:32:26 +00:00
|
|
|
handle_long_options(argv[0], long_option);
|
|
|
|
break;
|
2013-11-16 02:14:33 +00:00
|
|
|
case 'a':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
osmo_talloc_replace_string(trx, &trx->cfg.dev_args, optarg);
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
2018-03-06 17:38:22 +00:00
|
|
|
case 'l':
|
|
|
|
print_deprecated(option);
|
|
|
|
log_set_log_level(osmo_stderr_target, atoi(optarg));
|
|
|
|
break;
|
2013-11-16 02:14:33 +00:00
|
|
|
case 'i':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
osmo_talloc_replace_string(trx, &trx->cfg.remote_addr, optarg);
|
2017-08-16 14:53:23 +00:00
|
|
|
break;
|
|
|
|
case 'j':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
osmo_talloc_replace_string(trx, &trx->cfg.bind_addr, optarg);
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
|
|
|
case 'p':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.base_port = atoi(optarg);
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
|
|
|
case 'c':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.num_chans = atoi(optarg);
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
2016-06-24 21:25:39 +00:00
|
|
|
case 'm':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.multi_arfcn = true;
|
2016-06-24 21:25:39 +00:00
|
|
|
break;
|
2013-11-16 02:14:33 +00:00
|
|
|
case 'x':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.clock_ref = REF_EXTERNAL;
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
2016-07-18 02:29:08 +00:00
|
|
|
case 'g':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.clock_ref = REF_GPS;
|
2016-07-18 02:29:08 +00:00
|
|
|
break;
|
2014-01-25 07:34:03 +00:00
|
|
|
case 'f':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.filler = FILLER_DUMMY;
|
2014-01-25 07:34:03 +00:00
|
|
|
break;
|
2014-03-06 19:16:11 +00:00
|
|
|
case 'o':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.offset = atof(optarg);
|
2014-03-06 19:16:11 +00:00
|
|
|
break;
|
2013-11-16 02:14:33 +00:00
|
|
|
case 's':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.tx_sps = atoi(optarg);
|
2015-05-20 01:26:31 +00:00
|
|
|
break;
|
2016-06-27 22:39:16 +00:00
|
|
|
case 'b':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.rx_sps = atoi(optarg);
|
2016-06-27 22:39:16 +00:00
|
|
|
break;
|
2015-05-20 01:26:31 +00:00
|
|
|
case 'r':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.rtsc = atoi(optarg);
|
|
|
|
if (!trx->cfg.egprs) /* Don't override egprs which sets different filler */
|
|
|
|
trx->cfg.filler = FILLER_NORM_RAND;
|
2013-11-16 02:14:33 +00:00
|
|
|
break;
|
2016-03-23 14:06:32 +00:00
|
|
|
case 'A':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.rach_delay = atoi(optarg);
|
|
|
|
trx->cfg.filler = FILLER_ACCESS_RAND;
|
2016-03-23 14:06:32 +00:00
|
|
|
break;
|
2015-06-04 03:47:56 +00:00
|
|
|
case 'R':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.rssi_offset = atof(optarg);
|
2020-10-13 15:03:37 +00:00
|
|
|
trx->cfg.force_rssi_offset = true;
|
2015-06-04 03:47:56 +00:00
|
|
|
break;
|
2015-06-07 05:07:45 +00:00
|
|
|
case 'S':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.swap_channels = true;
|
2015-06-07 05:07:45 +00:00
|
|
|
break;
|
2016-03-06 11:44:34 +00:00
|
|
|
case 'e':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.egprs = true;
|
2016-03-06 11:44:34 +00:00
|
|
|
break;
|
2017-06-29 13:35:22 +00:00
|
|
|
case 't':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
trx->cfg.sched_rr = atoi(optarg);
|
2017-06-29 13:35:22 +00:00
|
|
|
break;
|
Add support to set Rx/TxAntenna
Some devices have different Rx or Tx ports with different RF characteristics.
For instance LimeSDR has H (High), L (Low) and W (Wide) band Rx ports,
each of one being more suitable to a specific range of frequencies.
In case one wants to support several GSM bands, the best option is to
use the WideBand port and connect the antenna physically to that port in
the board. Then the firmware must be instructed ro read from that port.
Support for Rx/Tx port configuration is already in there for all the
layers (Limesuite, SoapySDR, SoapyUHD, UHD), but we are missing the
required bits in osmo-trx to make use of the available UHD API. This
commit addresses it.
Before this patch, the Rx/Tx paths configured could be changed by means
of the LimeSuiteGUI app, but after running osmo-trx, the values were
changed to the default ones.
One can now start using osmo-trx with 1 channel and specific Rx/Tx ports
by using for instance: osmo-trx -c 1 -y BAND1 -z LNAW
Default behaviour if no specific path or an empry path is passed ("") is
to do the same as preiously, ie. nothing by not calling the
set{T,R}xAntenna APIs.
One can also configure only specific channels, for instance to configure
only the first Tx channel and the second Rx channel:
osmo-trx -c 2 -y BAND1, -z ,LNAW
Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
2018-02-05 12:05:06 +00:00
|
|
|
case 'y':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
tx_paths = comma_delimited_to_vector(optarg);
|
|
|
|
tx_paths_set = true;
|
Add support to set Rx/TxAntenna
Some devices have different Rx or Tx ports with different RF characteristics.
For instance LimeSDR has H (High), L (Low) and W (Wide) band Rx ports,
each of one being more suitable to a specific range of frequencies.
In case one wants to support several GSM bands, the best option is to
use the WideBand port and connect the antenna physically to that port in
the board. Then the firmware must be instructed ro read from that port.
Support for Rx/Tx port configuration is already in there for all the
layers (Limesuite, SoapySDR, SoapyUHD, UHD), but we are missing the
required bits in osmo-trx to make use of the available UHD API. This
commit addresses it.
Before this patch, the Rx/Tx paths configured could be changed by means
of the LimeSuiteGUI app, but after running osmo-trx, the values were
changed to the default ones.
One can now start using osmo-trx with 1 channel and specific Rx/Tx ports
by using for instance: osmo-trx -c 1 -y BAND1 -z LNAW
Default behaviour if no specific path or an empry path is passed ("") is
to do the same as preiously, ie. nothing by not calling the
set{T,R}xAntenna APIs.
One can also configure only specific channels, for instance to configure
only the first Tx channel and the second Rx channel:
osmo-trx -c 2 -y BAND1, -z ,LNAW
Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
2018-02-05 12:05:06 +00:00
|
|
|
break;
|
|
|
|
case 'z':
|
2018-02-21 17:47:35 +00:00
|
|
|
print_deprecated(option);
|
|
|
|
rx_paths = comma_delimited_to_vector(optarg);
|
|
|
|
rx_paths_set = true;
|
Add support to set Rx/TxAntenna
Some devices have different Rx or Tx ports with different RF characteristics.
For instance LimeSDR has H (High), L (Low) and W (Wide) band Rx ports,
each of one being more suitable to a specific range of frequencies.
In case one wants to support several GSM bands, the best option is to
use the WideBand port and connect the antenna physically to that port in
the board. Then the firmware must be instructed ro read from that port.
Support for Rx/Tx port configuration is already in there for all the
layers (Limesuite, SoapySDR, SoapyUHD, UHD), but we are missing the
required bits in osmo-trx to make use of the available UHD API. This
commit addresses it.
Before this patch, the Rx/Tx paths configured could be changed by means
of the LimeSuiteGUI app, but after running osmo-trx, the values were
changed to the default ones.
One can now start using osmo-trx with 1 channel and specific Rx/Tx ports
by using for instance: osmo-trx -c 1 -y BAND1 -z LNAW
Default behaviour if no specific path or an empry path is passed ("") is
to do the same as preiously, ie. nothing by not calling the
set{T,R}xAntenna APIs.
One can also configure only specific channels, for instance to configure
only the first Tx channel and the second Rx channel:
osmo-trx -c 2 -y BAND1, -z ,LNAW
Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
2018-02-05 12:05:06 +00:00
|
|
|
break;
|
2018-02-20 15:48:15 +00:00
|
|
|
case 'C':
|
2018-02-21 17:47:35 +00:00
|
|
|
config_file = optarg;
|
2018-02-20 15:48:15 +00:00
|
|
|
break;
|
2018-06-15 13:19:21 +00:00
|
|
|
case 'V':
|
|
|
|
print_version(1);
|
|
|
|
exit(0);
|
|
|
|
break;
|
2013-11-16 02:14:33 +00:00
|
|
|
default:
|
2018-02-21 17:47:35 +00:00
|
|
|
goto bad_config;
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-20 01:26:31 +00:00
|
|
|
|
2019-12-03 20:41:13 +00:00
|
|
|
if (argc > optind) {
|
|
|
|
LOG(ERROR) << "Unsupported positional arguments on command line";
|
|
|
|
goto bad_config;
|
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
/* Cmd line option specific validation & setup */
|
2016-03-07 06:19:15 +00:00
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
if (trx->cfg.num_chans > TRX_CHAN_MAX) {
|
|
|
|
LOG(ERROR) << "Too many channels requested, maximum is " << TRX_CHAN_MAX;
|
2016-07-20 23:35:03 +00:00
|
|
|
goto bad_config;
|
2015-05-20 01:26:31 +00:00
|
|
|
}
|
2018-02-21 17:47:35 +00:00
|
|
|
if ((tx_paths_set && tx_paths.size() != trx->cfg.num_chans) ||
|
|
|
|
(rx_paths_set && rx_paths.size() != trx->cfg.num_chans)) {
|
|
|
|
LOG(ERROR) << "Num of channels and num of Rx/Tx Antennas doesn't match";
|
2016-07-20 23:35:03 +00:00
|
|
|
goto bad_config;
|
2015-05-20 01:26:31 +00:00
|
|
|
}
|
2018-02-21 17:47:35 +00:00
|
|
|
for (i = 0; i < trx->cfg.num_chans; i++) {
|
|
|
|
trx->cfg.chans[i].trx = trx;
|
|
|
|
trx->cfg.chans[i].idx = i;
|
|
|
|
if (tx_paths_set)
|
|
|
|
osmo_talloc_replace_string(trx, &trx->cfg.chans[i].tx_path, tx_paths[i].c_str());
|
|
|
|
if (rx_paths_set)
|
|
|
|
osmo_talloc_replace_string(trx, &trx->cfg.chans[i].rx_path, rx_paths[i].c_str());
|
Add support to set Rx/TxAntenna
Some devices have different Rx or Tx ports with different RF characteristics.
For instance LimeSDR has H (High), L (Low) and W (Wide) band Rx ports,
each of one being more suitable to a specific range of frequencies.
In case one wants to support several GSM bands, the best option is to
use the WideBand port and connect the antenna physically to that port in
the board. Then the firmware must be instructed ro read from that port.
Support for Rx/Tx port configuration is already in there for all the
layers (Limesuite, SoapySDR, SoapyUHD, UHD), but we are missing the
required bits in osmo-trx to make use of the available UHD API. This
commit addresses it.
Before this patch, the Rx/Tx paths configured could be changed by means
of the LimeSuiteGUI app, but after running osmo-trx, the values were
changed to the default ones.
One can now start using osmo-trx with 1 channel and specific Rx/Tx ports
by using for instance: osmo-trx -c 1 -y BAND1 -z LNAW
Default behaviour if no specific path or an empry path is passed ("") is
to do the same as preiously, ie. nothing by not calling the
set{T,R}xAntenna APIs.
One can also configure only specific channels, for instance to configure
only the first Tx channel and the second Rx channel:
osmo-trx -c 2 -y BAND1, -z ,LNAW
Change-Id: I1735e6ab05a05b0312d6d679b16ebd4a2260fa23
2018-02-05 12:05:06 +00:00
|
|
|
}
|
|
|
|
|
2016-07-20 23:35:03 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
bad_config:
|
|
|
|
print_help();
|
|
|
|
exit(0);
|
2013-11-16 02:14:33 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
int trx_validate_config(struct trx_ctx *trx)
|
|
|
|
{
|
2019-04-01 00:55:48 +00:00
|
|
|
if (trx->cfg.multi_arfcn && trx->cfg.num_chans > TRX_MCHAN_MAX) {
|
2018-02-21 17:47:35 +00:00
|
|
|
LOG(ERROR) << "Unsupported number of channels";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Force 4 SPS for EDGE or multi-ARFCN configurations */
|
|
|
|
if ((trx->cfg.egprs || trx->cfg.multi_arfcn) &&
|
2018-10-21 10:15:30 +00:00
|
|
|
(trx->cfg.tx_sps!=4 || trx->cfg.rx_sps!=4)) {
|
2018-02-21 17:47:35 +00:00
|
|
|
LOG(ERROR) << "EDGE and Multi-Carrier options require 4 tx and rx sps. Check you config.";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int set_sched_rr(unsigned int prio)
|
2017-06-29 13:35:22 +00:00
|
|
|
{
|
|
|
|
struct sched_param param;
|
|
|
|
int rc;
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.sched_priority = prio;
|
2020-07-29 16:05:25 +00:00
|
|
|
LOG(INFO) << "Setting SCHED_RR priority " << param.sched_priority
|
|
|
|
<< ". This setting is DEPRECATED, please use 'policy rr " << param.sched_priority
|
|
|
|
<< "' under the 'sched' VTY node instead.";
|
2017-06-29 13:35:22 +00:00
|
|
|
rc = sched_setscheduler(getpid(), SCHED_RR, ¶m);
|
|
|
|
if (rc != 0) {
|
2018-02-21 17:47:35 +00:00
|
|
|
LOG(ERROR) << "Config: Setting SCHED_RR failed";
|
2017-06-29 13:35:22 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-29 09:49:08 +00:00
|
|
|
static void print_simd_info(void)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_SSE3
|
|
|
|
LOGP(DMAIN, LOGL_INFO, "SSE3 support compiled in");
|
|
|
|
#ifdef HAVE___BUILTIN_CPU_SUPPORTS
|
|
|
|
if (__builtin_cpu_supports("sse3"))
|
|
|
|
LOGPC(DMAIN, LOGL_INFO, " and supported by CPU\n");
|
|
|
|
else
|
|
|
|
LOGPC(DMAIN, LOGL_INFO, ", but not supported by CPU\n");
|
|
|
|
#else
|
|
|
|
LOGPC(DMAIN, LOGL_INFO, ", but runtime SIMD detection disabled\n");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SSE4_1
|
|
|
|
LOGP(DMAIN, LOGL_INFO, "SSE4.1 support compiled in");
|
|
|
|
#ifdef HAVE___BUILTIN_CPU_SUPPORTS
|
|
|
|
if (__builtin_cpu_supports("sse4.1"))
|
|
|
|
LOGPC(DMAIN, LOGL_INFO, " and supported by CPU\n");
|
|
|
|
else
|
|
|
|
LOGPC(DMAIN, LOGL_INFO, ", but not supported by CPU\n");
|
|
|
|
#else
|
|
|
|
LOGPC(DMAIN, LOGL_INFO, ", but runtime SIMD detection disabled\n");
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef HAVE_ATOMIC_OPS
|
|
|
|
#pragma message ("Built without atomic operation support. Using Mutex, it may affect performance!")
|
|
|
|
LOG(NOTICE) << "Built without atomic operation support. Using Mutex, it may affect performance!";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
static void print_config(struct trx_ctx *trx)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
std::ostringstream ost("");
|
|
|
|
|
|
|
|
ost << "Config Settings" << std::endl;
|
2018-03-06 17:38:22 +00:00
|
|
|
ost << " Log Level............... " << (unsigned int) osmo_stderr_target->loglevel << std::endl;
|
2018-02-21 17:47:35 +00:00
|
|
|
ost << " Device args............. " << charp2str(trx->cfg.dev_args) << std::endl;
|
|
|
|
ost << " TRX Base Port........... " << trx->cfg.base_port << std::endl;
|
|
|
|
ost << " TRX Address............. " << charp2str(trx->cfg.bind_addr) << std::endl;
|
2018-04-28 19:25:09 +00:00
|
|
|
ost << " GSM BTS Address......... " << charp2str(trx->cfg.remote_addr) << std::endl;
|
2018-02-21 17:47:35 +00:00
|
|
|
ost << " Channels................ " << trx->cfg.num_chans << std::endl;
|
|
|
|
ost << " Tx Samples-per-Symbol... " << trx->cfg.tx_sps << std::endl;
|
|
|
|
ost << " Rx Samples-per-Symbol... " << trx->cfg.rx_sps << std::endl;
|
|
|
|
ost << " EDGE support............ " << trx->cfg.egprs << std::endl;
|
2018-10-22 00:52:18 +00:00
|
|
|
ost << " Extended RACH support... " << trx->cfg.ext_rach << std::endl;
|
2018-02-21 17:47:35 +00:00
|
|
|
ost << " Reference............... " << trx->cfg.clock_ref << std::endl;
|
2019-10-14 21:33:07 +00:00
|
|
|
ost << " Filler Burst Type....... " << get_value_string(filler_names, trx->cfg.filler) << std::endl;
|
|
|
|
ost << " Filler Burst TSC........ " << trx->cfg.rtsc << std::endl;
|
|
|
|
ost << " Filler Burst RACH Delay. " << trx->cfg.rach_delay << std::endl;
|
2018-02-21 17:47:35 +00:00
|
|
|
ost << " Multi-Carrier........... " << trx->cfg.multi_arfcn << std::endl;
|
2018-08-23 06:41:06 +00:00
|
|
|
ost << " LO freq. offset......... " << trx->cfg.offset << std::endl;
|
|
|
|
if (trx->cfg.freq_offset_khz != 0)
|
|
|
|
ost << " Tune freq. offset....... " << trx->cfg.freq_offset_khz << std::endl;
|
2020-10-13 15:03:37 +00:00
|
|
|
ost << " RSSI to dBm offset...... " << trx->cfg.rssi_offset << (trx->cfg.force_rssi_offset ? "" : " (relative)") << std::endl;
|
2018-02-21 17:47:35 +00:00
|
|
|
ost << " Swap channels........... " << trx->cfg.swap_channels << std::endl;
|
|
|
|
ost << " Tx Antennas.............";
|
|
|
|
for (i = 0; i < trx->cfg.num_chans; i++) {
|
|
|
|
std::string p = charp2str(trx->cfg.chans[i].tx_path);
|
|
|
|
ost << " '" << ((p != "") ? p : "<default>") << "'";
|
|
|
|
}
|
|
|
|
ost << std::endl;
|
|
|
|
ost << " Rx Antennas.............";
|
|
|
|
for (i = 0; i < trx->cfg.num_chans; i++) {
|
|
|
|
std::string p = charp2str(trx->cfg.chans[i].rx_path);
|
|
|
|
ost << " '" << ((p != "") ? p : "<default>") << "'";
|
|
|
|
}
|
|
|
|
ost << std::endl;
|
|
|
|
|
2018-12-03 17:21:13 +00:00
|
|
|
LOG(INFO) << ost << std::endl;
|
2018-02-21 17:47:35 +00:00
|
|
|
}
|
|
|
|
|
2018-02-21 10:59:26 +00:00
|
|
|
static void trx_stop()
|
|
|
|
{
|
2018-12-03 17:21:13 +00:00
|
|
|
LOG(NOTICE) << "Shutting down transceiver..." << std::endl;
|
2018-02-21 10:59:26 +00:00
|
|
|
|
|
|
|
delete transceiver;
|
|
|
|
delete radio;
|
|
|
|
delete usrp;
|
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
static int trx_start(struct trx_ctx *trx)
|
2013-11-16 02:14:33 +00:00
|
|
|
{
|
2018-02-21 17:47:35 +00:00
|
|
|
int type, chans;
|
|
|
|
unsigned int i;
|
|
|
|
std::vector<std::string> rx_paths, tx_paths;
|
2016-06-22 23:09:44 +00:00
|
|
|
RadioDevice::InterfaceType iface = RadioDevice::NORMAL;
|
2018-02-21 10:59:26 +00:00
|
|
|
|
|
|
|
/* Create the low level device object */
|
2018-02-21 17:47:35 +00:00
|
|
|
if (trx->cfg.multi_arfcn)
|
2018-02-21 10:59:26 +00:00
|
|
|
iface = RadioDevice::MULTI_ARFCN;
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
/* Generate vector of rx/tx_path: */
|
|
|
|
for (i = 0; i < trx->cfg.num_chans; i++) {
|
|
|
|
rx_paths.push_back(charp2str(trx->cfg.chans[i].rx_path));
|
|
|
|
tx_paths.push_back(charp2str(trx->cfg.chans[i].tx_path));
|
|
|
|
}
|
2018-02-21 10:59:26 +00:00
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
usrp = RadioDevice::make(trx->cfg.tx_sps, trx->cfg.rx_sps, iface,
|
|
|
|
trx->cfg.num_chans, trx->cfg.offset,
|
|
|
|
tx_paths, rx_paths);
|
|
|
|
type = usrp->open(charp2str(trx->cfg.dev_args), trx->cfg.clock_ref, trx->cfg.swap_channels);
|
2018-02-21 10:59:26 +00:00
|
|
|
if (type < 0) {
|
|
|
|
LOG(ALERT) << "Failed to create radio device" << std::endl;
|
|
|
|
goto shutdown;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup the appropriate device interface */
|
2018-02-21 17:47:35 +00:00
|
|
|
radio = makeRadioInterface(trx, usrp, type);
|
2018-02-21 10:59:26 +00:00
|
|
|
if (!radio)
|
|
|
|
goto shutdown;
|
|
|
|
|
|
|
|
/* Create the transceiver core */
|
2018-02-21 17:47:35 +00:00
|
|
|
if (makeTransceiver(trx, radio) < 0)
|
2018-02-21 10:59:26 +00:00
|
|
|
goto shutdown;
|
|
|
|
|
|
|
|
chans = transceiver->numChans();
|
2018-12-03 17:21:13 +00:00
|
|
|
LOG(NOTICE) << "-- Transceiver active with "
|
2018-02-21 10:59:26 +00:00
|
|
|
<< chans << " channel(s)" << std::endl;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
shutdown:
|
|
|
|
trx_stop();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2018-02-20 15:48:15 +00:00
|
|
|
int rc;
|
2013-11-16 02:14:33 +00:00
|
|
|
|
2018-02-21 19:15:47 +00:00
|
|
|
tall_trx_ctx = talloc_named_const(NULL, 0, "OsmoTRX");
|
|
|
|
msgb_talloc_ctx_init(tall_trx_ctx, 0);
|
2018-02-20 15:48:15 +00:00
|
|
|
g_vty_info.tall_ctx = tall_trx_ctx;
|
|
|
|
|
2018-02-21 19:15:18 +00:00
|
|
|
setup_signal_handlers();
|
|
|
|
|
2018-02-21 14:41:03 +00:00
|
|
|
g_trx_ctx = vty_trx_ctx_alloc(tall_trx_ctx);
|
2018-02-20 15:48:15 +00:00
|
|
|
|
2017-03-15 17:09:35 +00:00
|
|
|
convolve_init();
|
|
|
|
convert_init();
|
|
|
|
|
2018-04-16 12:50:11 +00:00
|
|
|
osmo_init_logging2(tall_trx_ctx, &log_info);
|
2019-09-17 18:26:53 +00:00
|
|
|
log_enable_multithread();
|
2018-02-20 15:48:15 +00:00
|
|
|
osmo_stats_init(tall_trx_ctx);
|
|
|
|
vty_init(&g_vty_info);
|
2020-01-02 15:39:11 +00:00
|
|
|
logging_vty_add_cmds();
|
2018-02-20 15:48:15 +00:00
|
|
|
ctrl_vty_init(tall_trx_ctx);
|
2020-07-29 16:05:25 +00:00
|
|
|
osmo_cpu_sched_vty_init(tall_trx_ctx);
|
2018-02-20 15:48:15 +00:00
|
|
|
trx_vty_init(g_trx_ctx);
|
|
|
|
|
|
|
|
osmo_talloc_vty_add_cmds();
|
|
|
|
osmo_stats_vty_add_cmds();
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
handle_options(argc, argv, g_trx_ctx);
|
2013-11-16 02:14:33 +00:00
|
|
|
|
2018-02-20 15:48:15 +00:00
|
|
|
rate_ctr_init(tall_trx_ctx);
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
rc = vty_read_config_file(config_file, NULL);
|
2018-02-20 15:48:15 +00:00
|
|
|
if (rc < 0) {
|
2018-02-21 17:47:35 +00:00
|
|
|
fprintf(stderr, "Failed to open config file: '%s'\n", config_file);
|
2018-02-20 15:48:15 +00:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = telnet_init_dynif(tall_trx_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_TRX);
|
|
|
|
if (rc < 0)
|
|
|
|
exit(1);
|
|
|
|
|
2019-07-22 10:30:14 +00:00
|
|
|
g_ctrlh = ctrl_interface_setup_dynip(NULL, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_TRX, NULL);
|
2018-02-20 15:48:15 +00:00
|
|
|
if (!g_ctrlh) {
|
2018-12-03 17:21:13 +00:00
|
|
|
LOG(ERROR) << "Failed to create CTRL interface.\n";
|
2018-02-20 15:48:15 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
/* Backward compatibility: Hack to have 1 channel allocated by default.
|
|
|
|
* Can be Dropped once we * get rid of "-c" cmdline param */
|
|
|
|
if (g_trx_ctx->cfg.num_chans == 0) {
|
|
|
|
g_trx_ctx->cfg.num_chans = 1;
|
|
|
|
g_trx_ctx->cfg.chans[0].trx = g_trx_ctx;
|
|
|
|
g_trx_ctx->cfg.chans[0].idx = 0;
|
|
|
|
LOG(ERROR) << "No explicit channel config found. Make sure you" \
|
|
|
|
" configure channels in VTY config. Using 1 channel as default," \
|
|
|
|
" but expect your config to break in the future.";
|
2017-06-29 13:35:22 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 09:49:08 +00:00
|
|
|
print_simd_info();
|
2018-02-21 17:47:35 +00:00
|
|
|
print_config(g_trx_ctx);
|
|
|
|
|
|
|
|
if (trx_validate_config(g_trx_ctx) < 0) {
|
|
|
|
LOG(ERROR) << "Config failure - exiting";
|
2013-11-16 02:14:33 +00:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
if (g_trx_ctx->cfg.sched_rr) {
|
|
|
|
if (set_sched_rr(g_trx_ctx->cfg.sched_rr) < 0)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2019-06-04 10:39:28 +00:00
|
|
|
osmo_signal_register_handler(SS_MAIN, transc_sig_cb, NULL);
|
2019-05-24 14:54:19 +00:00
|
|
|
trx_rate_ctr_init(tall_trx_ctx, g_trx_ctx);
|
|
|
|
|
2013-11-16 02:14:33 +00:00
|
|
|
srandom(time(NULL));
|
|
|
|
|
2018-02-21 17:47:35 +00:00
|
|
|
if(trx_start(g_trx_ctx) < 0)
|
2018-02-21 10:59:26 +00:00
|
|
|
return EXIT_FAILURE;
|
2013-11-16 02:14:33 +00:00
|
|
|
|
|
|
|
while (!gshutdown)
|
2018-02-20 15:48:15 +00:00
|
|
|
osmo_select_main(0);
|
2013-11-16 02:14:33 +00:00
|
|
|
|
2018-02-21 10:59:26 +00:00
|
|
|
trx_stop();
|
2013-11-16 02:14:33 +00:00
|
|
|
|
2019-03-29 18:20:06 +00:00
|
|
|
osmo_fd_unregister(&signal_ofd);
|
|
|
|
osmo_fd_close(&signal_ofd);
|
2019-06-04 10:39:28 +00:00
|
|
|
osmo_signal_unregister_handler(SS_MAIN, transc_sig_cb, NULL);
|
2013-11-16 02:14:33 +00:00
|
|
|
return 0;
|
|
|
|
}
|