From 9943c5bbac1e0ce99bd597f3e4ae665ce42118c5 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 29 Jul 2009 15:41:29 +0200 Subject: generalize channel activation / channel mode modify * we only need one piece of code to calculate rsl_ie_chan_mode from our run-time data structures (gsm_lchan) * add some more channel modes for TCH/H and data * use enum's to make the compiler warn us about unhandled enum values * make sure the caller determines the (signalling,speech,data) mode --- openbsc/include/openbsc/abis_rsl.h | 15 +++- openbsc/include/openbsc/gsm_04_08.h | 18 +++-- openbsc/include/openbsc/gsm_data.h | 5 +- openbsc/src/abis_rsl.c | 142 +++++++++++++++++------------------- openbsc/src/gsm_04_08.c | 1 + 5 files changed, 93 insertions(+), 88 deletions(-) diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index 9e4d59078..a2a01d321 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -266,16 +266,23 @@ struct rsl_ie_chan_mode { } __attribute__ ((packed)); #define RSL_CMOD_DTXu 0x01 /* uplink */ #define RSL_CMOD_DTXd 0x02 /* downlink */ -#define RSL_CMOD_SPD_SPEECH 0x01 -#define RSL_CMOD_SPD_DATA 0x02 -#define RSL_CMOD_SPD_SIGN 0x03 +enum rsl_cmod_spd { + RSL_CMOD_SPD_SPEECH = 0x01, + RSL_CMOD_SPD_DATA = 0x02, + RSL_CMOD_SPD_SIGN = 0x03, +}; #define RSL_CMOD_CRT_SDCCH 0x01 #define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */ #define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */ /* FIXME: More CRT types */ +/* Speech */ #define RSL_CMOD_SP_GSM1 0x01 #define RSL_CMOD_SP_GSM2 0x11 #define RSL_CMOD_SP_GSM3 0x21 +/* Data */ +#define RSL_CMOD_SP_NT_14k5 0x58 +#define RSL_CMOD_SP_NT_12k0 0x50 +#define RSL_CMOD_SP_NT_6k0 0x51 /* Chapter 9.3.5 */ struct rsl_ie_chan_ident { @@ -459,7 +466,7 @@ int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr, u_int8_t bs_power, u_int8_t ms_power, u_int8_t ta); int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, - u_int8_t ta, u_int8_t mode); + u_int8_t ta); int rsl_chan_mode_modify_req(struct gsm_lchan *ts); int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len, u_int8_t *ms_ident, u_int8_t chan_needed); diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index a885d5ae7..c93540b14 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -48,14 +48,16 @@ struct gsm48_chan_mode_modify { u_int8_t mode; } __attribute__ ((packed)); -#define GSM48_CMODE_SIGN 0x00 -#define GSM48_CMODE_SPEECH_V1 0x01 -#define GSM48_CMODE_SPEECH_EFR 0x21 -#define GSM48_CMODE_SPEECH_AMR 0x41 -#define GSM48_CMODE_DATA_14k5 0x0f -#define GSM48_CMODE_DATA_12k0 0x03 -#define GSM48_CMODE_DATA_6k0 0x0b -#define GSM48_CMODE_DATA_3k6 0x23 +enum gsm48_chan_mode { + GSM48_CMODE_SIGN = 0x00, + GSM48_CMODE_SPEECH_V1 = 0x01, + GSM48_CMODE_SPEECH_EFR = 0x21, + GSM48_CMODE_SPEECH_AMR = 0x41, + GSM48_CMODE_DATA_14k5 = 0x0f, + GSM48_CMODE_DATA_12k0 = 0x03, + GSM48_CMODE_DATA_6k0 = 0x0b, + GSM48_CMODE_DATA_3k6 = 0x23, +}; /* Chapter 9.1.18 */ struct gsm48_imm_ass { diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index e6dffa8f2..84e3c79e1 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -41,6 +41,7 @@ enum gsm_chreq_reason_t { #include #include +#include #include #include @@ -165,8 +166,10 @@ struct gsm_lchan { u_int8_t nr; /* The logical channel type */ enum gsm_chan_t type; + /* RSL channel mode */ + enum rsl_cmod_spd rsl_cmode; /* If TCH, traffic channel mode */ - enum gsm_chan_t tch_mode; + enum gsm48_chan_mode tch_mode; /* Power levels for MS and BTS */ u_int8_t bs_power; u_int8_t ms_power; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 2c28a5e9a..eb43bd58f 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -530,6 +530,62 @@ int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm) return abis_rsl_sendmsg(msg); } +static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm, + struct gsm_lchan *lchan) +{ + memset(cm, 0, sizeof(cm)); + + /* FIXME: what to do with data calls ? */ + cm->dtx_dtu = 0x00; + + /* set TCH Speech/Data */ + cm->spd_ind = lchan->rsl_cmode; + + switch (lchan->type) { + case GSM_LCHAN_SDCCH: + cm->chan_rt = RSL_CMOD_CRT_SDCCH; + break; + case GSM_LCHAN_TCH_F: + cm->chan_rt = RSL_CMOD_CRT_TCH_Bm; + break; + case GSM_LCHAN_TCH_H: + cm->chan_rt = RSL_CMOD_CRT_TCH_Lm; + break; + case GSM_LCHAN_NONE: + case GSM_LCHAN_UNKNOWN: + default: + return -EINVAL; + } + + switch (lchan->tch_mode) { + case GSM48_CMODE_SIGN: + cm->chan_rate = 0; + break; + case GSM48_CMODE_SPEECH_V1: + cm->chan_rate = RSL_CMOD_SP_GSM1; + break; + case GSM48_CMODE_SPEECH_EFR: + cm->chan_rate = RSL_CMOD_SP_GSM2; + break; + case GSM48_CMODE_SPEECH_AMR: + cm->chan_rate = RSL_CMOD_SP_GSM3; + break; + case GSM48_CMODE_DATA_14k5: + cm->chan_rate = RSL_CMOD_SP_NT_14k5; + break; + case GSM48_CMODE_DATA_12k0: + cm->chan_rate = RSL_CMOD_SP_NT_12k0; + break; + case GSM48_CMODE_DATA_6k0: + cm->chan_rate = RSL_CMOD_SP_NT_6k0; + break; + default: + return -EINVAL; + } + + return 0; +} + /* Chapter 8.4.1 */ #if 0 int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr, @@ -567,45 +623,20 @@ int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr, #endif int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, - u_int8_t ta, u_int8_t mode) + u_int8_t ta) { struct abis_rsl_dchan_hdr *dh; struct msgb *msg; + int rc; u_int8_t chan_nr = lchan2chan_nr(lchan); u_int16_t arfcn = lchan->ts->trx->arfcn; struct rsl_ie_chan_mode cm; struct rsl_ie_chan_ident ci; - memset(&cm, 0, sizeof(cm)); - /* FIXME: what to do with data calls ? */ - cm.dtx_dtu = 0x00; - switch (lchan->type) { - case GSM_LCHAN_SDCCH: - cm.spd_ind = RSL_CMOD_SPD_SIGN; - cm.chan_rt = RSL_CMOD_CRT_SDCCH; - cm.chan_rate = 0x00; - break; - case GSM_LCHAN_TCH_F: - cm.chan_rt = RSL_CMOD_CRT_TCH_Bm; - switch (mode) { - case RSL_CMOD_SPD_SIGN: - cm.spd_ind = RSL_CMOD_SPD_SIGN; - cm.chan_rate = 0x00; - break; - case RSL_CMOD_SPD_SPEECH: - cm.spd_ind = RSL_CMOD_SPD_SPEECH; - cm.chan_rate = RSL_CMOD_SP_GSM2; - break; - } - break; - case GSM_LCHAN_TCH_H: - DEBUGP(DRSL, "Unimplemented TCH_H activation\n"); - return -1; - case GSM_LCHAN_UNKNOWN: - case GSM_LCHAN_NONE: - return -1; - } + rc = channel_mode_from_lchan(&cm, lchan); + if (rc < 0) + return rc; memset(&ci, 0, sizeof(ci)); ci.chan_desc.iei = 0x64; @@ -642,54 +673,14 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *lchan) { struct abis_rsl_dchan_hdr *dh; struct msgb *msg; + int rc; u_int8_t chan_nr = lchan2chan_nr(lchan); struct rsl_ie_chan_mode cm; - memset(&cm, 0, sizeof(cm)); - - /* FIXME: what to do with data calls ? */ - cm.dtx_dtu = 0x00; - switch (lchan->type) { - /* todo more modes */ - case GSM_LCHAN_TCH_F: - cm.spd_ind = RSL_CMOD_SPD_SPEECH; - cm.chan_rt = RSL_CMOD_CRT_TCH_Bm; - switch(lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - cm.chan_rate = RSL_CMOD_SP_GSM1; - break; - case GSM48_CMODE_SPEECH_EFR: - cm.chan_rate = RSL_CMOD_SP_GSM2; - break; - case GSM48_CMODE_SPEECH_AMR: - cm.chan_rate = RSL_CMOD_SP_GSM3; - break; - default: - DEBUGP(DRSL, "Unimplemented channel modification\n"); - return -1; - } - break; - case GSM_LCHAN_TCH_H: - cm.spd_ind = RSL_CMOD_SPD_SPEECH; - cm.chan_rt = RSL_CMOD_CRT_TCH_Lm; - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - cm.chan_rate = RSL_CMOD_SP_GSM1; - break; - /* Half-rate has no V2 */ - case GSM48_CMODE_SPEECH_AMR: - cm.chan_rate = RSL_CMOD_SP_GSM3; - break; - default: - DEBUGP(DRSL, "Unimplemented channel modification\n"); - return -1; - } - break; - default: - DEBUGP(DRSL, "Unimplemented channel modification\n"); - return -1; - } + rc = channel_mode_from_lchan(&cm, lchan); + if (rc < 0) + return rc; msg = rsl_msgb_alloc(); dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh)); @@ -1099,7 +1090,8 @@ static int rsl_rx_chan_rqd(struct msgb *msg) subch = lchan->nr; lchan->ms_power = lchan->bs_power = 0x0f; /* 30dB reduction */ - rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, RSL_CMOD_SPD_SIGN); + lchan->rsl_cmode = RSL_CMOD_SPD_SIGN; + rsl_chan_activate_lchan(lchan, 0x00, rqd_ta); /* create IMMEDIATE ASSIGN 04.08 messge */ memset(&ia, 0, sizeof(ia)); diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index a7577d249..078e95f3b 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1746,6 +1746,7 @@ static int gsm0408_rcv_rr(struct msgb *msg) DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n"); /* We've successfully modified the MS side of the channel, * now go on to modify the BTS side of the channel */ + msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH; rc = rsl_chan_mode_modify_req(msg->lchan); break; case GSM48_MT_RR_STATUS: -- cgit v1.2.3