fixeria has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-trx/+/43107?usp=email )
Change subject: libosmo-trx/trxc: add SETSLOT parameter parser/builder
......................................................................
libosmo-trx/trxc: add SETSLOT parameter parser/builder
Add struct osmo_trxc_setslot plus osmo_trxc_setslot_parse()/_build()
for the "<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]" SETSLOT parameters,
including VAMOS combinations (VFF/VHH/VFH/HVHH) with per-sub-channel
TSC overrides.
Change-Id: I17a1176b1418edd0caf750d50acda0482d4ad04a
---
M libosmo-trx/include/osmocom/trx/trxc.h
M libosmo-trx/src/trxc.c
M tests/libosmo-trx/trxc_test.c
M tests/libosmo-trx/trxc_test.ok
4 files changed, 253 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/07/43107/1
diff --git a/libosmo-trx/include/osmocom/trx/trxc.h
b/libosmo-trx/include/osmocom/trx/trxc.h
index 6f6891e..df7901e 100644
--- a/libosmo-trx/include/osmocom/trx/trxc.h
+++ b/libosmo-trx/include/osmocom/trx/trxc.h
@@ -4,6 +4,9 @@
#include <stdint.h>
#include <stddef.h>
+#include <stdbool.h>
+
+#include <osmocom/core/utils.h>
/*! Maximum length of a command verb (incl. '\0') */
#define OSMO_TRXC_CMD_LEN_MAX 32
@@ -61,3 +64,63 @@
/* Clock socket: "IND CLOCK <fn>" */
int osmo_trxc_clock_ind_parse(uint32_t *fn, const char *buf, size_t len);
int osmo_trxc_clock_ind_build(char *buf, size_t buf_size, uint32_t fn);
+
+/* SETSLOT: "<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]" */
+
+/*! Classic (non-VAMOS) GSM TS 05.02 channel combinations, as used by the
+ * <chan_comb> parameter of SETSLOT. Numeric values match the wire format. */
+enum osmo_trxc_chan_comb {
+ OSMO_TRXC_CHAN_COMB_UNUSED = 0, /*!< Channel is
transmitted, but unused */
+ OSMO_TRXC_CHAN_COMB_TCHF = 1,
+ OSMO_TRXC_CHAN_COMB_TCHH_IDLE = 2, /*!< TCH/HS, idle every
other slot */
+ OSMO_TRXC_CHAN_COMB_TCHH = 3,
+ OSMO_TRXC_CHAN_COMB_BCCH = 4, /*!< DL:
FCCH+SCH+CCCH+BCCH, UL: RACH */
+ OSMO_TRXC_CHAN_COMB_BCCH_SDCCH4 = 5, /*!< DL: +SDCCH/4+SACCH/4, UL:
+SDCCH/4 */
+ OSMO_TRXC_CHAN_COMB_CCCH = 6, /*!< DL: CCCH+BCCH, UL:
RACH */
+ OSMO_TRXC_CHAN_COMB_SDCCH8 = 7, /*!< SDCCH/8 + SACCH/8 */
+ OSMO_TRXC_CHAN_COMB_TCHF_FACCH_SACCHM = 8,
+ OSMO_TRXC_CHAN_COMB_TCHF_SACCHM = 9,
+ OSMO_TRXC_CHAN_COMB_TCHFD_SACCHMD = 10,
+ OSMO_TRXC_CHAN_COMB_PBCCH = 11, /*!<
PBCCH+PCCCH+PDTCH+PACCH+PTCCH */
+ OSMO_TRXC_CHAN_COMB_PCCCH = 12, /*!<
PCCCH+PDTCH+PACCH+PTCCH */
+ OSMO_TRXC_CHAN_COMB_PDTCH = 13, /*!< PDTCH+PACCH+PTCCH */
+};
+
+/*! VAMOS-enabled channel combinations: the <chan_comb> parameter of SETSLOT
+ * is symbolic (not numeric) for these. */
+enum osmo_trxc_vamos_comb {
+ OSMO_TRXC_VAMOS_COMB_VFF = 1, /*!< V0(TCH/F) & V1(TCH/F) */
+ OSMO_TRXC_VAMOS_COMB_VHH, /*!< V0(TCH/H0)&V1(TCH/H0) +
V0(TCH/H1)&V1(TCH/H1) */
+ OSMO_TRXC_VAMOS_COMB_VFH, /*!< V0(TCH/F) & V1(TCH/H0) + V0(TCH/F)
& V1(TCH/H1) */
+ OSMO_TRXC_VAMOS_COMB_HVHH, /*!< TCH/H0 + V0(TCH/H1) & V1(TCH/H1)
(mixed) */
+};
+
+extern const struct value_string osmo_trxc_vamos_comb_names[];
+static inline const char *osmo_trxc_vamos_comb_name(enum osmo_trxc_vamos_comb
comb)
+{
+ return get_value_string(osmo_trxc_vamos_comb_names, comb);
+}
+
+#define OSMO_TRXC_SETSLOT_TSC_MAX 3 /*!< up to 3 sub-channels (VAMOS
"HVHH") */
+
+/*! One "C<tsc>/S<tsc_set>" override, as used by SETSLOT for (VAMOS)
+ * sub-channels that don't use the endpoint-wide TSC (SETTSC). */
+struct osmo_trxc_setslot_tsc {
+ uint8_t tsc;
+ uint8_t tsc_set;
+};
+
+/*! Parsed SETSLOT parameters. */
+struct osmo_trxc_setslot {
+ uint8_t tn;
+ bool vamos; /*!< false: chan_comb is valid, true: vamos_comb is
valid */
+ union {
+ enum osmo_trxc_chan_comb chan_comb;
+ enum osmo_trxc_vamos_comb vamos_comb;
+ };
+ unsigned int num_tsc; /*!< number of valid entries in tsc[] */
+ struct osmo_trxc_setslot_tsc tsc[OSMO_TRXC_SETSLOT_TSC_MAX];
+};
+
+int osmo_trxc_setslot_parse(struct osmo_trxc_setslot *ss, const struct
osmo_trxc_msg *msg);
+int osmo_trxc_setslot_build(char *buf, size_t buf_size, const struct
osmo_trxc_setslot *ss);
diff --git a/libosmo-trx/src/trxc.c b/libosmo-trx/src/trxc.c
index bd038b5..07219d4 100644
--- a/libosmo-trx/src/trxc.c
+++ b/libosmo-trx/src/trxc.c
@@ -44,6 +44,14 @@
{ 0, NULL }
};
+const struct value_string osmo_trxc_vamos_comb_names[] = {
+ { OSMO_TRXC_VAMOS_COMB_VFF, "VFF" },
+ { OSMO_TRXC_VAMOS_COMB_VHH, "VHH" },
+ { OSMO_TRXC_VAMOS_COMB_VFH, "VFH" },
+ { OSMO_TRXC_VAMOS_COMB_HVHH, "HVHH" },
+ { 0, NULL }
+};
+
/*! Parse a TRXC message ("CMD <verb> [<params>]", "RSP <verb> <status>
* [<params>]" or "IND <verb> <params>") from a zero-terminated buffer.
* \param[out] msg parsed message
@@ -193,3 +201,86 @@
return -EMSGSIZE;
return rc;
}
+
+/*! Parse SETSLOT parameters ("<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]")
+ * from an already-parsed TRXC message's msg->params.
+ * \returns 0 on success; negative on error */
+int osmo_trxc_setslot_parse(struct osmo_trxc_setslot *ss, const struct
osmo_trxc_msg *msg)
+{
+ char params[OSMO_TRXC_PARAMS_LEN_MAX];
+ char *saveptr, *tok;
+ unsigned int tn;
+ int comb;
+
+ memset(ss, 0, sizeof(*ss));
+
+ OSMO_STRLCPY_ARRAY(params, msg->params);
+
+ tok = strtok_r(params, " ", &saveptr);
+ if (tok == NULL || sscanf(tok, "%u", &tn) != 1)
+ return -EINVAL;
+ if (tn > 7)
+ return -ERANGE;
+ ss->tn = tn;
+
+ tok = strtok_r(NULL, " ", &saveptr);
+ if (tok == NULL)
+ return -EINVAL;
+ comb = get_string_value(osmo_trxc_vamos_comb_names, tok);
+ if (comb >= 0) {
+ ss->vamos = true;
+ ss->vamos_comb = comb;
+ } else {
+ if (sscanf(tok, "%d", &comb) != 1)
+ return -EINVAL;
+ if (comb < OSMO_TRXC_CHAN_COMB_UNUSED || comb >
OSMO_TRXC_CHAN_COMB_PDTCH)
+ return -ERANGE;
+ ss->vamos = false;
+ ss->chan_comb = comb;
+ }
+
+ while ((tok = strtok_r(NULL, " ", &saveptr)) != NULL) {
+ unsigned int tsc, tsc_set;
+
+ if (ss->num_tsc >= OSMO_TRXC_SETSLOT_TSC_MAX)
+ return -E2BIG;
+ if (sscanf(tok, "C%u/S%u", &tsc, &tsc_set) != 2)
+ return -EINVAL;
+ ss->tsc[ss->num_tsc].tsc = tsc;
+ ss->tsc[ss->num_tsc].tsc_set = tsc_set;
+ ss->num_tsc++;
+ }
+
+ return 0;
+}
+
+/*! Serialize SETSLOT parameters ("<tn> <chan_comb> [C<tsc>/S<tsc_set> ...]")
+ * into the given buffer (zero-terminated), for use as msg->params.
+ * \returns length of the string (excl. '\0') on success; negative on error */
+int osmo_trxc_setslot_build(char *buf, size_t buf_size, const struct
osmo_trxc_setslot *ss)
+{
+ unsigned int i;
+ int rc, len;
+
+ if (ss->tn > 7)
+ return -ERANGE;
+
+ if (ss->vamos)
+ rc = snprintf(buf, buf_size, "%u %s", ss->tn,
+ osmo_trxc_vamos_comb_name(ss->vamos_comb));
+ else
+ rc = snprintf(buf, buf_size, "%u %d", ss->tn, ss->chan_comb);
+ if (rc < 0 || (size_t)rc >= buf_size)
+ return -EMSGSIZE;
+ len = rc;
+
+ for (i = 0; i < ss->num_tsc; i++) {
+ rc = snprintf(buf + len, buf_size - len, " C%u/S%u",
+ ss->tsc[i].tsc, ss->tsc[i].tsc_set);
+ if (rc < 0 || (size_t)rc >= buf_size - (size_t)len)
+ return -EMSGSIZE;
+ len += rc;
+ }
+
+ return len;
+}
diff --git a/tests/libosmo-trx/trxc_test.c b/tests/libosmo-trx/trxc_test.c
index 93eea83..b4653cd 100644
--- a/tests/libosmo-trx/trxc_test.c
+++ b/tests/libosmo-trx/trxc_test.c
@@ -194,6 +194,79 @@
OSMO_ASSERT(rc < 0);
}
+static void test_setslot_parse_one(const char *params)
+{
+ struct osmo_trxc_msg msg = { .type = OSMO_TRXC_MT_CMD, .cmd = "SETSLOT"
};
+ struct osmo_trxc_setslot ss;
+ char buf[OSMO_TRXC_MSG_BUF_SIZE];
+ int rc;
+
+ snprintf(msg.params, sizeof(msg.params), "%s", params);
+
+ rc = osmo_trxc_setslot_parse(&ss, &msg);
+ if (rc < 0) {
+ printf("'%s' -> rc=%d\n", params, rc);
+ return;
+ }
+
+ printf("'%s' -> tn=%u vamos=%d comb=%s num_tsc=%u",
+ params, ss.tn, ss.vamos,
+ ss.vamos ? osmo_trxc_vamos_comb_name(ss.vamos_comb) :
"(numeric)",
+ ss.num_tsc);
+ if (!ss.vamos)
+ printf(" chan_comb=%d", ss.chan_comb);
+ for (unsigned int i = 0; i < ss.num_tsc; i++)
+ printf(" C%u/S%u", ss.tsc[i].tsc, ss.tsc[i].tsc_set);
+ printf("\n");
+
+ /* re-encode and compare against the original params */
+ rc = osmo_trxc_setslot_build(buf, sizeof(buf), &ss);
+ OSMO_ASSERT(rc > 0 && rc == (int)strlen(buf));
+ printf("\tre-encoded: '%s'\n", buf);
+ OSMO_ASSERT(strcmp(buf, params) == 0);
+}
+
+static void test_setslot(void)
+{
+ static const char * const good[] = {
+ "0 0",
+ "7 13",
+ "4 1 C7/S1", /* manual example */
+ "0 VFF C0/S1 C0/S2", /* manual example */
+ "3 VHH C1/S3 C1/S4", /* manual example */
+ "1 VFH C2/S1 C2/S4", /* manual example */
+ "2 HVHH C0/S1 C0/S1 C0/S2", /* manual example */
+ };
+ static const char * const bad[] = {
+ "8 0", /* tn out of range */
+ "0 14", /* chan_comb out of range */
+ "0 -1", /* chan_comb out of range */
+ "0", /* missing chan_comb */
+ "", /* missing everything */
+ "x 0", /* tn not numeric */
+ "0 x", /* chan_comb not numeric, not a known
VAMOS name */
+ "0 0 bogus", /* trailing token not a
C<tsc>/S<tsc_set> */
+ "0 HVHH C0/S1 C0/S1 C0/S2 C0/S3", /* too many TSC overrides */
+ };
+ struct osmo_trxc_msg msg = { .type = OSMO_TRXC_MT_CMD, .cmd = "SETSLOT"
};
+ struct osmo_trxc_setslot ss;
+ int rc;
+
+ printf("=== %s ===\n", __func__);
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(good); i++)
+ test_setslot_parse_one(good[i]);
+ for (unsigned int i = 0; i < ARRAY_SIZE(bad); i++)
+ test_setslot_parse_one(bad[i]);
+
+ /* build() range check */
+ memset(&ss, 0, sizeof(ss));
+ ss.tn = 8;
+ rc = osmo_trxc_setslot_build(msg.params, sizeof(msg.params), &ss);
+ printf("build with out of range tn: rc=%d\n", rc);
+ OSMO_ASSERT(rc < 0);
+}
+
int main(int argc, char **argv)
{
test_msg_parse();
@@ -201,6 +274,7 @@
test_params_scan();
test_long_params();
test_clk_ind();
+ test_setslot();
printf("Done\n");
return 0;
diff --git a/tests/libosmo-trx/trxc_test.ok b/tests/libosmo-trx/trxc_test.ok
index 845d4da..30b47ff 100644
--- a/tests/libosmo-trx/trxc_test.ok
+++ b/tests/libosmo-trx/trxc_test.ok
@@ -52,4 +52,29 @@
'IND KCOLC 123' -> rc=-22
'CMD CLOCK 123' -> rc=-22
build with out of range fn: rc=-34
+=== test_setslot ===
+'0 0' -> tn=0 vamos=0 comb=(numeric) num_tsc=0 chan_comb=0
+ re-encoded: '0 0'
+'7 13' -> tn=7 vamos=0 comb=(numeric) num_tsc=0 chan_comb=13
+ re-encoded: '7 13'
+'4 1 C7/S1' -> tn=4 vamos=0 comb=(numeric) num_tsc=1 chan_comb=1 C7/S1
+ re-encoded: '4 1 C7/S1'
+'0 VFF C0/S1 C0/S2' -> tn=0 vamos=1 comb=VFF num_tsc=2 C0/S1 C0/S2
+ re-encoded: '0 VFF C0/S1 C0/S2'
+'3 VHH C1/S3 C1/S4' -> tn=3 vamos=1 comb=VHH num_tsc=2 C1/S3 C1/S4
+ re-encoded: '3 VHH C1/S3 C1/S4'
+'1 VFH C2/S1 C2/S4' -> tn=1 vamos=1 comb=VFH num_tsc=2 C2/S1 C2/S4
+ re-encoded: '1 VFH C2/S1 C2/S4'
+'2 HVHH C0/S1 C0/S1 C0/S2' -> tn=2 vamos=1 comb=HVHH num_tsc=3 C0/S1 C0/S1
C0/S2
+ re-encoded: '2 HVHH C0/S1 C0/S1 C0/S2'
+'8 0' -> rc=-34
+'0 14' -> rc=-34
+'0 -1' -> rc=-34
+'0' -> rc=-22
+'' -> rc=-22
+'x 0' -> rc=-22
+'0 x' -> rc=-22
+'0 0 bogus' -> rc=-22
+'0 HVHH C0/S1 C0/S1 C0/S2 C0/S3' -> rc=-7
+build with out of range tn: rc=-34
Done
--
To view, visit https://gerrit.osmocom.org/c/osmo-trx/+/43107?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-trx
Gerrit-Branch: master
Gerrit-Change-Id: I17a1176b1418edd0caf750d50acda0482d4ad04a
Gerrit-Change-Number: 43107
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <[email protected]>