diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/amr.c | 43 | ||||
-rw-r--r-- | src/common/msg_utils.c | 26 |
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 |