Timur Davydov has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-trx/+/42678?usp=email )
Change subject: trx: add JSON serialization for 'show trx' ......................................................................
trx: add JSON serialization for 'show trx'
Introduce trx_to_json() helper to serialize the output of 'show trx' into JSON format.
Also initialize talloc/VTY context in websdr entrypoint to allow accessing TRX configuration programmatically.
Intended for external consumers (e.g. WebSDR frontend).
Change-Id: Icbfb754580daa6db9b5646cc6698a6a6ee1c1610 --- M CommonLibs/Makefile.am A CommonLibs/trx_stats_json.c A CommonLibs/trx_stats_json.h M Transceiver52M/osmo-trx-websdr.cpp 4 files changed, 290 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/78/42678/1
diff --git a/CommonLibs/Makefile.am b/CommonLibs/Makefile.am index 4a0652d..23feb98 100644 --- a/CommonLibs/Makefile.am +++ b/CommonLibs/Makefile.am @@ -59,3 +59,8 @@ debug.h \ osmo_signal.h \ config_defs.h + +if ENABLE_WEBSDR +libcommon_la_SOURCES += trx_stats_json.c +include_HEADERS = trx_stats_json.h +endif diff --git a/CommonLibs/trx_stats_json.c b/CommonLibs/trx_stats_json.c new file mode 100644 index 0000000..8eff19d --- /dev/null +++ b/CommonLibs/trx_stats_json.c @@ -0,0 +1,243 @@ +/* JSON helpers for OsmoTRX: trx serialization API implementation + * + * Copyright (C) 2026 Timur Davydov dtv.comp@gmail.com + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdarg.h> + +#include <osmocom/core/utils.h> + +#include "trx_vty.h" +#include "config_defs.h" + +#include "trx_stats_json.h" + +/* function trx_from_vty is implemented in trx_vty.c */ +struct trx_ctx *trx_from_vty(struct vty *v); + +/* JSON serialization context for transceiver config */ +struct trx_stats_json_ctx { + char *buf; + size_t buflen; + size_t off; +}; + +/* append a single character into ctx->buf */ +static int tsj_append_char(struct trx_stats_json_ctx *ctx, char c) +{ + if (ctx->off + 1 >= ctx->buflen) + return -ENOSPC; + + ctx->buf[ctx->off++] = c; + ctx->buf[ctx->off] = '\0'; + + return 0; +} + +/* append a formatted string into ctx->buf */ +static int tsj_append_fmt(struct trx_stats_json_ctx *ctx, const char *fmt, ...) +{ + va_list ap; + int rc; + size_t rem; + + if (ctx->off >= ctx->buflen) + return -ENOSPC; + + rem = ctx->buflen - ctx->off; + va_start(ap, fmt); + rc = vsnprintf(ctx->buf + ctx->off, rem, fmt, ap); + va_end(ap); + + if (rc < 0) + return -EIO; + if ((size_t)rc >= rem) + return -ENOSPC; + + ctx->off += rc; + return 0; +} + +/* simple JSON string escaper that appends into ctx->buf */ +static int tsj_append_json_str(struct trx_stats_json_ctx *ctx, const char *s) +{ + int rc; + + if (!s) s = ""; + + rc = tsj_append_char(ctx, '"'); + if (rc) + return rc; + + for (size_t j = 0; s[j] != '\0'; j++) { + char c = s[j]; + if (c == '"' || c == '\') { + rc = tsj_append_char(ctx, '\'); + if (rc) + return rc; + rc = tsj_append_char(ctx, c); + if (rc) + return rc; + } else if ((unsigned char)c < 0x20) { + rc = tsj_append_char(ctx, ' '); + if (rc) + return rc; + } else { + rc = tsj_append_char(ctx, c); + if (rc) + return rc; + } + } + + return tsj_append_char(ctx, '"'); +} + +/* Build JSON for 'show trx' by enumerating transceivers */ +int trx_to_json(char *buf, size_t buflen) +{ + struct trx_ctx *trx = trx_from_vty(NULL); + struct trx_stats_json_ctx ctx = { + .buf = buf, + .buflen = buflen, + }; + int rc; + + if (!buf || buflen == 0) + return -EINVAL; + + rc = tsj_append_char(&ctx, '{'); + if (rc) + return rc; + + if (!trx) { + rc = tsj_append_fmt(&ctx, ""trx_config":null"); + if (rc) + return rc; + } else { + rc = tsj_append_fmt(&ctx, ""trx_config":{"); + if (rc) + return rc; + + rc = tsj_append_fmt(&ctx, ""local_ip":"); + if (rc) + return rc; + + rc = tsj_append_json_str(&ctx, trx->cfg.bind_addr); + if (rc) + return rc; + + rc = tsj_append_fmt(&ctx, ","remote_ip":"); + if (rc) + return rc; + + rc = tsj_append_json_str(&ctx, trx->cfg.remote_addr); + if (rc) + return rc; + + rc = tsj_append_fmt(&ctx, ","base_port":%u,"dev_args":", trx->cfg.base_port); + if (rc) + return rc; + + rc = tsj_append_json_str(&ctx, trx->cfg.dev_args); + if (rc) + return rc; + + const char *filler_str = get_value_string(filler_names, trx->cfg.filler); + const char *clock_ref_str = get_value_string(clock_ref_names, trx->cfg.clock_ref); + + rc = tsj_append_fmt(&ctx, ","tx_sps":%u,"rx_sps":%u,"filler":", + trx->cfg.tx_sps, trx->cfg.rx_sps); + if (rc) + return rc; + + rc = tsj_append_json_str(&ctx, filler_str); + if (rc) + return rc; + + rc = tsj_append_fmt(&ctx, ","rtsc":%u,"rach_delay":%u,"clock_ref":", + trx->cfg.rtsc, trx->cfg.rach_delay); + if (rc) + return rc; + + rc = tsj_append_json_str(&ctx, clock_ref_str); + if (rc) + return rc; + + rc = tsj_append_fmt(&ctx, + ","multi_arfcn":%s,"offset":%f,"rssi_offset":%f" + ","swap_channels":%s,"egprs":%s,"ext_rach":%s,"sched_rr":%u,"stack_size":%u" + ","channels":[", + trx->cfg.multi_arfcn ? "true" : "false", + trx->cfg.offset, trx->cfg.rssi_offset, + trx->cfg.swap_channels ? "true" : "false", + trx->cfg.egprs ? "true" : "false", + trx->cfg.ext_rach ? "true" : "false", + trx->cfg.sched_rr, trx->cfg.stack_size); + if (rc) + return rc; + + for (unsigned int i = 0; i < trx->cfg.num_chans; i++) { + struct trx_chan *chan = &trx->cfg.chans[i]; + if (i != 0) { + rc = tsj_append_char(&ctx, ','); + if (rc) + return rc; + } + rc = tsj_append_fmt(&ctx, "{"idx":%u,"rx_path":", chan->idx); + if (rc) + return rc; + + rc = tsj_append_json_str(&ctx, chan->rx_path); + if (rc) + return rc; + + rc = tsj_append_fmt(&ctx, ","tx_path":"); + if (rc) + return rc; + + rc = tsj_append_json_str(&ctx, chan->tx_path); + if (rc) + return rc; + + rc = tsj_append_char(&ctx, '}'); + if (rc) + return rc; + } + + rc = tsj_append_char(&ctx, ']'); + if (rc) + return rc; + + rc = tsj_append_char(&ctx, '}'); + if (rc) + return rc; + } + + rc = tsj_append_char(&ctx, '}'); + if (rc) + return rc; + + return (int)ctx.off; +} diff --git a/CommonLibs/trx_stats_json.h b/CommonLibs/trx_stats_json.h new file mode 100644 index 0000000..37f331f --- /dev/null +++ b/CommonLibs/trx_stats_json.h @@ -0,0 +1,36 @@ +/* JSON helpers for OsmoTXR: trx serialization API + * + * Copyright (C) 2026 Timur Davydov dtv.comp@gmail.com + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +#ifndef TRX_STATS_JSON_H +#define TRX_STATS_JSON_H +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int trx_to_json(char *buf, size_t buflen); + +#ifdef __cplusplus +} +#endif + +#endif /* TRX_STATS_JSON_H */ diff --git a/Transceiver52M/osmo-trx-websdr.cpp b/Transceiver52M/osmo-trx-websdr.cpp index 8913893..69265af 100644 --- a/Transceiver52M/osmo-trx-websdr.cpp +++ b/Transceiver52M/osmo-trx-websdr.cpp @@ -40,6 +40,7 @@ uint32_t g_tx_ts; uint32_t g_tx_len;
+static void *tall_trx_ctx; static struct trx_ctx *g_trx_ctx;
static RadioDevice *usrp; @@ -201,6 +202,9 @@ convolve_init(); convert_init();
+ tall_trx_ctx = talloc_named_const(NULL, 0, "OsmoTRX"); + g_trx_ctx = vty_trx_ctx_alloc(tall_trx_ctx); + g_trx_ctx->cfg.tx_sps = 4; g_trx_ctx->cfg.rx_sps = 4; g_trx_ctx->cfg.base_port = 5700; @@ -218,6 +222,8 @@
srandom(time(NULL));
+ trx_vty_init(g_trx_ctx); + if(trx_start(g_trx_ctx) < 0) return EXIT_FAILURE;