diff options
-rw-r--r-- | include/osmo-bts/bts.h | 3 | ||||
-rw-r--r-- | include/osmo-bts/gsm_data.h | 8 | ||||
-rw-r--r-- | src/common/bts.c | 30 | ||||
-rw-r--r-- | src/common/rsl.c | 6 | ||||
-rw-r--r-- | src/osmo-bts-octphy/l1_if.c | 9 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/main.c | 12 | ||||
-rw-r--r-- | src/osmo-bts-trx/main.c | 12 | ||||
-rw-r--r-- | tests/misc/misc_test.c | 26 |
8 files changed, 106 insertions, 0 deletions
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h index 9e16e050..2f63e37f 100644 --- a/include/osmo-bts/bts.h +++ b/include/osmo-bts/bts.h @@ -45,5 +45,8 @@ struct gsm_time *get_time(struct gsm_bts *bts); int bts_main(int argc, char **argv); +int bts_supports_cm(struct gsm_bts_role_bts *bts, + enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm); + #endif /* _BTS_H */ diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h index dcffcf65..853b4454 100644 --- a/include/osmo-bts/gsm_data.h +++ b/include/osmo-bts/gsm_data.h @@ -33,6 +33,11 @@ struct gsm_network { struct pcu_sock_state *pcu_state; }; +struct bts_cm { + enum gsm_phys_chan_config pchan; + enum gsm48_chan_mode cm; +}; + /* data structure for BTS related data specific to the BTS role */ struct gsm_bts_role_bts { struct { @@ -89,6 +94,7 @@ struct gsm_bts_role_bts { bool rtp_jitter_adaptive; struct { uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */ + const struct bts_cm *cm; /* Table with supp. ch rate/mode combinations */ } support; struct { uint8_t tc4_ctr; @@ -146,4 +152,6 @@ int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher); bool ts_is_pdch(const struct gsm_bts_trx_ts *ts); +int bts_model_check_cm_mode(enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm); + #endif /* _GSM_DATA_H */ diff --git a/src/common/bts.c b/src/common/bts.c index 6747f50b..31afba41 100644 --- a/src/common/bts.c +++ b/src/common/bts.c @@ -675,3 +675,33 @@ struct gsm_time *get_time(struct gsm_bts *bts) return &btsb->gsm_time; } + +int bts_supports_cm(struct gsm_bts_role_bts *bts, + enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm) +{ + const struct bts_cm *supported; + int i; + + supported = bts->support.cm; + + /* Check if we got a list with supported codec, if not, no list has + * been configured yet for that BTS. In that case we will just skip + * and accept any combination */ + if (supported == NULL) + return 1; + + for (i = 0;; i++) { + /* If we manage to find the given combination in the list, + * we know that the pchan/cm combination is supported */ + if (supported[i].pchan == pchan && supported[i].cm == cm) + return 1; + + /* When we hit the terminator, we know that the given + * pchan/cm combination is not supported because it + * is not in the list. */ + if (supported[i].pchan == _GSM_PCHAN_MAX) + return 0; + } + + return 0; +} diff --git a/src/common/rsl.c b/src/common/rsl.c index 3d0993c3..2eb0db1d 100644 --- a/src/common/rsl.c +++ b/src/common/rsl.c @@ -1278,6 +1278,7 @@ static int rsl_rx_mode_modif(struct msgb *msg) struct gsm_lchan *lchan = msg->lchan; struct rsl_ie_chan_mode *cm; struct tlv_parsed tp; + struct gsm_bts_role_bts *btsb = bts_role_bts(lchan->ts->trx->bts); rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); @@ -1289,6 +1290,11 @@ static int rsl_rx_mode_modif(struct msgb *msg) cm = (struct rsl_ie_chan_mode *) TLVP_VAL(&tp, RSL_IE_CHAN_MODE); lchan_tchmode_from_cmode(lchan, cm); + if (bts_supports_cm(btsb, lchan->ts->pchan, lchan->tch_mode) != 1) { + LOGP(DRSL, LOGL_ERROR, "invalid mode/codec instructed by BSC, check BSC configuration.\n"); + return rsl_tx_mode_modif_nack(lchan, RSL_ERR_SERV_OPT_UNAVAIL); + } + /* 9.3.7 Encryption Information */ if (TLVP_PRESENT(&tp, RSL_IE_ENCR_INFO)) { uint8_t len = TLVP_LEN(&tp, RSL_IE_ENCR_INFO); diff --git a/src/osmo-bts-octphy/l1_if.c b/src/osmo-bts-octphy/l1_if.c index fce34841..dde993d5 100644 --- a/src/osmo-bts-octphy/l1_if.c +++ b/src/osmo-bts-octphy/l1_if.c @@ -76,6 +76,14 @@ /* timeout until which we expect PHY to respond */ #define CMD_TIMEOUT 5 +/* Table with channel rate / and codec configuration that are supported + * by the hardware bts_supports_cm() */ +static const struct bts_cm bts_model_supported_cm[] = { + { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1}, + { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1}, + { _GSM_PCHAN_MAX, 0 } +}; + /* allocate a msgb for a Layer1 primitive */ struct msgb *l1p_msgb_alloc(void) { @@ -776,6 +784,7 @@ int bts_model_init(struct gsm_bts *bts) bts->variant = BTS_OSMO_OCTPHY; btsb = bts_role_bts(bts); btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); + btsb->support.cm = bts_model_supported_cm; /* FIXME: what is the nominal transmit power of the PHY/board? */ bts->c0->nominal_power = 15; diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index ce12d63d..f52ecdd5 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -55,6 +55,17 @@ #include "hw_misc.h" #include "oml_router.h" +/* Table with channel rate / and codec configuration that are supported + * by the hardware bts_supports_cm() */ +static const struct bts_cm bts_model_supported_cm[] = { + { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1}, + { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1}, + { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR}, + { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR}, + { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR}, + { _GSM_PCHAN_MAX, 0 } +}; + int bts_model_init(struct gsm_bts *bts) { struct gsm_bts_role_bts *btsb; @@ -65,6 +76,7 @@ int bts_model_init(struct gsm_bts *bts) bts->variant = BTS_OSMO_SYSMO; btsb = bts_role_bts(bts); btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3); + btsb->support.cm = bts_model_supported_cm; rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd); if (rc < 0) { diff --git a/src/osmo-bts-trx/main.c b/src/osmo-bts-trx/main.c index a1eb686d..973a611e 100644 --- a/src/osmo-bts-trx/main.c +++ b/src/osmo-bts-trx/main.c @@ -59,6 +59,17 @@ #include "l1_if.h" #include "trx_if.h" +/* Table with channel rate / and codec configuration that are supported + * by the hardware bts_supports_cm() */ +static const struct bts_cm bts_model_supported_cm[] = { + { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1}, + { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1}, + { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR}, + { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR}, + { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR}, + { _GSM_PCHAN_MAX, 0 } +}; + /* dummy, since no direct dsp support */ uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx) { @@ -101,6 +112,7 @@ int bts_model_init(struct gsm_bts *bts) bts->variant = BTS_OSMO_TRX; btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2); + btsb->support.cm = bts_model_supported_cm; /* FIXME: this needs to be overridden with the real hardrware * value */ diff --git a/tests/misc/misc_test.c b/tests/misc/misc_test.c index c2918fb4..00744a6b 100644 --- a/tests/misc/misc_test.c +++ b/tests/misc/misc_test.c @@ -157,6 +157,31 @@ static void test_sacch_get(void) } } +static const struct bts_cm bts_model_supported_cm[] = { + {GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1}, + {GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1}, + {GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR}, + {GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR}, + {_GSM_PCHAN_MAX, 0} +}; + +static void test_bts_supports_cm(void) +{ + struct gsm_bts_role_bts bts; + bts.support.cm = bts_model_supported_cm; + + OSMO_ASSERT(bts_supports_cm + (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1) == 1); + OSMO_ASSERT(bts_supports_cm + (&bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1) == 1); + OSMO_ASSERT(bts_supports_cm + (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR) == 0); + OSMO_ASSERT(bts_supports_cm + (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR) == 1); + OSMO_ASSERT(bts_supports_cm + (&bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR) == 1); +} + int main(int argc, char **argv) { bts_log_init(NULL); @@ -164,5 +189,6 @@ int main(int argc, char **argv) test_sacch_get(); test_msg_utils_ipa(); test_msg_utils_oml(); + test_bts_supports_cm(); return EXIT_SUCCESS; } |