aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/amr.c43
-rw-r--r--src/common/msg_utils.c26
2 files changed, 62 insertions, 7 deletions
diff --git a/src/common/amr.c b/src/common/amr.c
index 56ed4302..b5d2c371 100644
--- a/src/common/amr.c
+++ b/src/common/amr.c
@@ -22,7 +22,8 @@ void amr_log_mr_conf(int ss, int logl, const char *pfx,
LOGPC(ss, logl, "\n");
}
-int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc, uint8_t cmi)
+static inline int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc,
+ uint8_t cmi)
{
unsigned int i;
for (i = 0; i < amr_mrc->num_modes; i++) {
@@ -32,6 +33,46 @@ int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc, uint8_t cmi)
return -EINVAL;
}
+static inline uint8_t set_cmr_mode_idx(const struct amr_multirate_conf *amr_mrc,
+ uint8_t cmr)
+{
+ int rc;
+
+ /* Codec Mode Request is in upper 4 bits of RTP payload header,
+ * and we simply copy the CMR into the CMC */
+ if (cmr == 0xF) {
+ /* FIXME: we need some state about the last codec mode */
+ return 0;
+ }
+
+ rc = get_amr_mode_idx(amr_mrc, cmr);
+ if (rc < 0) {
+ /* FIXME: we need some state about the last codec mode */
+ LOGP(DRTP, LOGL_INFO, "RTP->L1: overriding CMR %u\n", cmr);
+ return 0;
+ }
+ return rc;
+}
+
+static inline uint8_t set_cmi_mode_idx(const struct amr_multirate_conf *amr_mrc,
+ uint8_t cmi)
+{
+ int rc = get_amr_mode_idx(amr_mrc, cmi);
+ if (rc < 0) {
+ LOGP(DRTP, LOGL_ERROR, "AMR CMI %u not part of AMR MR set\n",
+ cmi);
+ return 0;
+ }
+ return rc;
+}
+
+void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc,
+ uint8_t cmi, uint8_t cmr)
+{
+ data[0] = set_cmi_mode_idx(amr_mrc, cmi);
+ data[1] = set_cmr_mode_idx(amr_mrc, cmr);
+}
+
/* parse a GSM 04.08 MultiRate Config IE (10.5.2.21aa) in a more
* comfortable internal data structure */
int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc,
diff --git a/src/common/msg_utils.c b/src/common/msg_utils.c
index f5a48a3d..5c6bbbea 100644
--- a/src/common/msg_utils.c
+++ b/src/common/msg_utils.c
@@ -20,6 +20,7 @@
#include <osmo-bts/msg_utils.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/oml.h>
+#include <osmo-bts/amr.h>
#include <osmocom/gsm/protocol/ipaccess.h>
#include <osmocom/gsm/protocol/gsm_12_21.h>
@@ -99,17 +100,30 @@ void lchan_set_marker(bool t, struct gsm_lchan *lchan)
}
/* store the last SID frame in lchan context */
-void save_last_sid(struct gsm_lchan *lchan, uint8_t *l1_payload, size_t length,
- uint32_t fn, bool update)
+/*! \brief Store the last SID frame in lchan context
+ * \param[in] lchan Logical channel on which we check scheduling
+ * \param[in] l1_payload buffer with SID data
+ * \param[in] length length of l1_payload
+ * \param[in] fn Frame Number for which we check scheduling
+ * \param[in] update 0 if SID_FIRST, 1 if SID_UPDATE, -1 if not AMR SID
+ * \param[in] cmr Codec Mode Request (AMR-specific, ignored otherwise)
+ * \param[in] cmi Codec Mode Indication (AMR-specific, ignored otherwise)
+ */
+void save_last_sid(struct gsm_lchan *lchan, const uint8_t *l1_payload,
+ size_t length, uint32_t fn, int update, uint8_t cmr,
+ int8_t cmi)
{
- size_t copy_len = OSMO_MIN(length + 1,
- ARRAY_SIZE(lchan->tch.last_sid.buf));
+ size_t amr = (update < 0) ? 0 : 2,
+ copy_len = OSMO_MIN(length + 1, ARRAY_SIZE(lchan->tch.last_sid.buf));
- lchan->tch.last_sid.len = copy_len;
+ lchan->tch.last_sid.len = copy_len + amr;
lchan->tch.last_sid.fn = fn;
lchan->tch.last_sid.is_update = update;
- memcpy(lchan->tch.last_sid.buf, l1_payload, copy_len);
+ if (amr)
+ amr_set_mode_pref(lchan->tch.last_sid.buf, &lchan->tch.amr_mr,
+ cmi, cmr);
+ memcpy(lchan->tch.last_sid.buf + amr, l1_payload, copy_len);
}
/*! \brief Check if enough time has passed since last SID (if any) to repeat it