aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-09-09 22:32:45 +0200
committerHarald Welte <laforge@gnumonks.org>2011-09-09 22:32:45 +0200
commit9508fb80a4c8284daf52b1beb154a86df7d5ee07 (patch)
tree9b65c7c2e712d031136705329a36ab4b72b5416d /src/common
parent4ccca1ce36067d5f52d2feb7c2c6f37510618530 (diff)
Introduce new amr.[ch] for AMR related functions
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/amr.c115
-rw-r--r--src/common/rsl.c100
3 files changed, 125 insertions, 92 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 8726b005..75cd7401 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -4,4 +4,4 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS)
noinst_LIBRARIES = libbts.a
libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
- rsl.c vty.c paging.c measurement.c
+ rsl.c vty.c paging.c measurement.c amr.c
diff --git a/src/common/amr.c b/src/common/amr.c
new file mode 100644
index 00000000..eeb6e7f2
--- /dev/null
+++ b/src/common/amr.c
@@ -0,0 +1,115 @@
+#include <stdint.h>
+#include <errno.h>
+
+#include <osmocom/core/logging.h>
+
+#include <osmo-bts/logging.h>
+#include <osmo-bts/amr.h>
+
+void amr_log_mr_conf(int ss, int logl, const char *pfx,
+ struct amr_multirate_conf *amr_mrc)
+{
+ int i;
+
+ LOGP(ss, logl, "%s AMR MR Conf: num_modes=%u",
+ pfx, amr_mrc->num_modes);
+
+ for (i = 0; i < amr_mrc->num_modes; i++)
+ LOGPC(ss, logl, ", mode[%u] = %u/%u/%u",
+ i, amr_mrc->mode[i].mode, amr_mrc->mode[i].threshold,
+ amr_mrc->mode[i].hysteresis);
+ LOGPC(ss, logl, "\n");
+}
+
+
+/* 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,
+ const uint8_t *mr_conf, unsigned int len)
+{
+ uint8_t mr_version = mr_conf[0] >> 5;
+ uint8_t num_codecs = 0;
+ int i, j = 0;
+
+ if (mr_version != 1) {
+ LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknonw\n",
+ mr_version);
+ goto ret_einval;
+ }
+
+ /* check number of active codecs */
+ for (i = 0; i < 8; i++) {
+ if (mr_conf[1] & (1 << i))
+ num_codecs++;
+ }
+
+ /* check for minimum length */
+ if (num_codecs == 0 ||
+ (num_codecs == 1 && len < 2) ||
+ (num_codecs == 2 && len < 4) ||
+ (num_codecs == 3 && len < 5) ||
+ (num_codecs == 4 && len < 6) ||
+ (num_codecs > 4)) {
+ LOGP(DRSL, LOGL_ERROR, "AMR Multirate with %u modes len=%u "
+ "not possible\n", num_codecs, len);
+ goto ret_einval;
+ }
+
+ /* copy the first two octets of the IE */
+ amr_mrc->gsm48_ie[0] = mr_conf[0];
+ amr_mrc->gsm48_ie[1] = mr_conf[1];
+
+ amr_mrc->num_modes = num_codecs;
+
+ for (i = 0; i < 8; i++) {
+ if (mr_conf[1] & (1 << i)) {
+ amr_mrc->mode[j++].mode = i;
+ }
+ }
+
+ if (num_codecs >= 2) {
+ amr_mrc->mode[0].threshold = mr_conf[1] & 0x3F;
+ amr_mrc->mode[0].hysteresis = mr_conf[2] >> 4;
+ }
+ if (num_codecs >= 3) {
+ amr_mrc->mode[1].threshold =
+ ((mr_conf[2] & 0xF) << 2) | (mr_conf[3] >> 6);
+ amr_mrc->mode[1].hysteresis = (mr_conf[3] >> 2) & 0x7;
+ }
+ if (num_codecs >= 4) {
+ amr_mrc->mode[3].threshold =
+ ((mr_conf[3] & 0x3) << 4) | (mr_conf[4] >> 4);
+ amr_mrc->mode[3].hysteresis = mr_conf[4] & 0xF;
+ }
+
+ return num_codecs;
+
+ret_einval:
+ return -EINVAL;
+}
+
+
+unsigned int amr_get_initial_mode(struct gsm_lchan *lchan)
+{
+ struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr;
+
+ if (lchan->mr_conf.icmi) {
+ /* initial mode given, coding in TS 05.09 3.4.1 */
+ return amr_mrc->mode[lchan->mr_conf.smod].mode;
+ } else {
+ /* implicit rule according to TS 05.09 Chapter 3.4.3 */
+ switch (amr_mrc->num_modes) {
+ case 2:
+ case 3:
+ /* return the most robust */
+ return amr_mrc->mode[0].mode;
+ case 4:
+ /* return the second-most robust */
+ return amr_mrc->mode[1].mode;
+ case 1:
+ default:
+ /* return the only mode we have */
+ return amr_mrc->mode[0].mode;
+ }
+ }
+}
diff --git a/src/common/rsl.c b/src/common/rsl.c
index db39f812..9dee4f75 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -38,6 +38,7 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/rsl.h>
#include <osmo-bts/oml.h>
+#include <osmo-bts/amr.h>
#include <osmo-bts/signal.h>
#include <osmo-bts/bts_model.h>
#include <osmo-bts/measurement.h>
@@ -121,89 +122,6 @@ static void lchan_tchmode_from_cmode(struct gsm_lchan *lchan,
* support
*/
-static void log_mr_conf(int ss, int logl, const char *pfx,
- struct amr_multirate_conf *amr_mrc)
-{
- int i;
-
- LOGP(ss, logl, "%s AMR MR Conf: num_modes=%u",
- pfx, amr_mrc->num_modes);
-
- for (i = 0; i < amr_mrc->num_modes; i++)
- LOGPC(ss, logl, ", mode[%u] = %u/%u/%u",
- i, amr_mrc->mode[i].mode, amr_mrc->mode[i].threshold,
- amr_mrc->mode[i].hysteresis);
- LOGPC(ss, logl, "\n");
-}
-
-
-/* parse a GSM 04.08 MultiRate Config IE (10.5.2.21aa) in a more
- * comfortable internal data structure */
-static int parse_mr_conf(struct amr_multirate_conf *amr_mrc,
- const uint8_t *mr_conf, unsigned int len)
-{
- uint8_t mr_version = mr_conf[0] >> 5;
- uint8_t num_codecs = 0;
- int i, j = 0;
-
- if (mr_version != 1) {
- LOGP(DRSL, LOGL_ERROR, "AMR Multirate Version %u unknonw\n",
- mr_version);
- goto ret_einval;
- }
-
- /* check number of active codecs */
- for (i = 0; i < 8; i++) {
- if (mr_conf[1] & (1 << i))
- num_codecs++;
- }
-
- /* check for minimum length */
- if (num_codecs == 0 ||
- (num_codecs == 1 && len < 2) ||
- (num_codecs == 2 && len < 4) ||
- (num_codecs == 3 && len < 5) ||
- (num_codecs == 4 && len < 6) ||
- (num_codecs > 4)) {
- LOGP(DRSL, LOGL_ERROR, "AMR Multirate with %u modes len=%u "
- "not possible\n", num_codecs, len);
- goto ret_einval;
- }
-
- /* copy the first two octets of the IE */
- amr_mrc->gsm48_ie[0] = mr_conf[0];
- amr_mrc->gsm48_ie[1] = mr_conf[1];
-
- amr_mrc->num_modes = num_codecs;
-
- for (i = 0; i < 8; i++) {
- if (mr_conf[1] & (1 << i)) {
- amr_mrc->mode[j++].mode = i;
- }
- }
-
- if (num_codecs >= 2) {
- amr_mrc->mode[0].threshold = mr_conf[1] & 0x3F;
- amr_mrc->mode[0].hysteresis = mr_conf[2] >> 4;
- }
- if (num_codecs >= 3) {
- amr_mrc->mode[1].threshold =
- ((mr_conf[2] & 0xF) << 2) | (mr_conf[3] >> 6);
- amr_mrc->mode[1].hysteresis = (mr_conf[3] >> 2) & 0x7;
- }
- if (num_codecs >= 4) {
- amr_mrc->mode[3].threshold =
- ((mr_conf[3] & 0x3) << 4) | (mr_conf[4] >> 4);
- amr_mrc->mode[3].hysteresis = mr_conf[4] & 0xF;
- }
-
- return num_codecs;
-
-ret_einval:
- return -EINVAL;
-}
-
-
#warning merge lchan_lookup with OpenBSC
/* determine logical channel based on TRX and channel number IE */
struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
@@ -765,10 +683,10 @@ static int rsl_rx_chan_activ(struct msgb *msg)
}
memcpy(&lchan->mr_conf, TLVP_VAL(&tp, RSL_IE_MR_CONFIG),
TLVP_LEN(&tp, RSL_IE_MR_CONFIG));
- parse_mr_conf(&lchan->tch.amr_mr, TLVP_VAL(&tp, RSL_IE_MR_CONFIG),
- TLVP_LEN(&tp, RSL_IE_MR_CONFIG));
- log_mr_conf(DRTP, LOGL_DEBUG, gsm_lchan_name(lchan),
- &lchan->tch.amr_mr);
+ amr_parse_mr_conf(&lchan->tch.amr_mr, TLVP_VAL(&tp, RSL_IE_MR_CONFIG),
+ TLVP_LEN(&tp, RSL_IE_MR_CONFIG));
+ amr_log_mr_conf(DRTP, LOGL_DEBUG, gsm_lchan_name(lchan),
+ &lchan->tch.amr_mr);
}
/* 9.3.53 MultiRate Control */
/* 9.3.54 Supported Codec Types */
@@ -1004,10 +922,10 @@ static int rsl_rx_mode_modif(struct msgb *msg)
}
memcpy(&lchan->mr_conf, TLVP_VAL(&tp, RSL_IE_MR_CONFIG),
TLVP_LEN(&tp, RSL_IE_MR_CONFIG));
- parse_mr_conf(&lchan->tch.amr_mr, TLVP_VAL(&tp, RSL_IE_MR_CONFIG),
- TLVP_LEN(&tp, RSL_IE_MR_CONFIG));
- log_mr_conf(DRTP, LOGL_DEBUG, gsm_lchan_name(lchan),
- &lchan->tch.amr_mr);
+ amr_parse_mr_conf(&lchan->tch.amr_mr, TLVP_VAL(&tp, RSL_IE_MR_CONFIG),
+ TLVP_LEN(&tp, RSL_IE_MR_CONFIG));
+ amr_log_mr_conf(DRTP, LOGL_DEBUG, gsm_lchan_name(lchan),
+ &lchan->tch.amr_mr);
}
/* 9.3.53 MultiRate Control */
/* 9.3.54 Supported Codec Types */