aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO-RELEASE1
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08.h3
-rw-r--r--src/gsm/gsm48.c21
-rw-r--r--src/gsm/libosmogsm.map1
-rw-r--r--tests/gsm0408/gsm0408_test.c24
5 files changed, 49 insertions, 1 deletions
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 547b5a90..9af92c17 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -9,3 +9,4 @@
#library what description / commit summary line
core osmo_tdef_get() change val_if_not_present arg from unsigned long to long to allow passing -1
core struct osmo_tdef fields min_val,max_val added, ABI break (arrays of structs used in programs)
+gsm API added osmo_gsm48_rfpowercap2powerclass()
diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h
index 6a6c7f3f..b5317d50 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -10,6 +10,7 @@
#include <osmocom/core/endian.h>
struct gsm_lchan;
+enum gsm_band;
/* Chapter 10.5.1.5 */
struct gsm48_classmark1 {
@@ -73,7 +74,7 @@ const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm);
char *osmo_gsm48_classmark_a5_name_buf(char *buf, size_t buf_len, const struct osmo_gsm48_classmark *cm);
char *osmo_gsm48_classmark_a5_name_c(const void *ctx, const struct osmo_gsm48_classmark *cm);
void osmo_gsm48_classmark_update(struct osmo_gsm48_classmark *dst, const struct osmo_gsm48_classmark *src);
-
+int8_t osmo_gsm48_rfpowercap2powerclass(enum gsm_band band, uint8_t rf_power_cap);
/* Chapter 10.5.2.1b.3 */
#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_1024 {
diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c
index 2d6deb56..17b0829d 100644
--- a/src/gsm/gsm48.c
+++ b/src/gsm/gsm48.c
@@ -1390,4 +1390,25 @@ int osmo_gsm48_classmark_supports_a5(const struct osmo_gsm48_classmark *cm, uint
}
}
+/*! Decode power class from Classmark1/2 RF power capability field.
+ * \param[in] rf_power_cap The RF power capability field (3 bits).
+ * \param[in] band the band of the arfcn from where the classmark was received
+ * \return the MS power class on success, negative on error.
+ */
+int8_t osmo_gsm48_rfpowercap2powerclass(enum gsm_band band, uint8_t rf_power_cap)
+{
+ switch (band) {
+ case GSM_BAND_1800:
+ case GSM_BAND_1900:
+ if (rf_power_cap > 2)
+ return -1;
+ return rf_power_cap + 1;
+ default:
+ if (rf_power_cap > 4)
+ return -1;
+ return rf_power_cap + 1;
+ }
+}
+
+
/*! @} */
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 724fe5b1..a0e3b324 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -646,6 +646,7 @@ osmo_gsm48_classmark_a5_name;
osmo_gsm48_classmark_a5_name_buf;
osmo_gsm48_classmark_a5_name_c;
osmo_gsm48_classmark_update;
+osmo_gsm48_rfpowercap2powerclass;
cbsp_msg_type_names;
cbsp_iei_names;
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
index db1d45ad..2488024a 100644
--- a/tests/gsm0408/gsm0408_test.c
+++ b/tests/gsm0408/gsm0408_test.c
@@ -26,6 +26,7 @@
#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/gsm48_arfcn_range_encode.h>
+#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/mncc.h>
#include <osmocom/core/backtrace.h>
#include <osmocom/core/utils.h>
@@ -1132,6 +1133,28 @@ static void test_si_range_helpers()
VERIFY(f0, ==, 1);
}
+static void test_power_ctrl()
+{
+ int8_t rc8;
+
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_850, 0x00);
+ VERIFY(rc8, ==, 1);
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0x02);
+ VERIFY(rc8, ==, 3);
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_1800, 0x02);
+ VERIFY(rc8, ==, 3);
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_1900, 0x02);
+ VERIFY(rc8, ==, 3);
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_1900, 0x04);
+ VERIFY(rc8, <, 0);
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0x04);
+ VERIFY(rc8, ==, 5);
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0x05);
+ VERIFY(rc8, <, 0);
+ rc8 = osmo_gsm48_rfpowercap2powerclass(GSM_BAND_900, 0xf2);
+ VERIFY(rc8, <, 0);
+}
+
int main(int argc, char **argv)
{
test_bearer_cap();
@@ -1147,6 +1170,7 @@ int main(int argc, char **argv)
test_arfcn_filter();
test_print_encoding();
test_range_encoding();
+ test_power_ctrl();
return EXIT_SUCCESS;
}