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]>

Reply via email to