aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/abis_rsl.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/abis_rsl.c')
-rw-r--r--openbsc/src/abis_rsl.c175
1 files changed, 92 insertions, 83 deletions
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 56c3f711b..1a2c58b16 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -321,6 +321,7 @@ static const char *rsl_err_vals[0xff] = {
[RSL_ERR_TALKER_ACC_FAIL] = "Talker Access Failure",
[RSL_ERR_OM_INTERVENTION] = "O&M Intervention",
[RSL_ERR_NORMAL_UNSPEC] = "Normal event, unspecified",
+ [RSL_ERR_T_MSRFPCI_EXP] = "Siemens: T_MSRFPCI Expired",
[RSL_ERR_EQUIPMENT_FAIL] = "Equipment Failure",
[RSL_ERR_RR_UNAVAIL] = "Radio Resource not available",
[RSL_ERR_TERR_CH_FAIL] = "Terrestrial Channel Failure",
@@ -530,6 +531,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 +624,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;
@@ -637,40 +669,19 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
return abis_rsl_sendmsg(msg);
}
-/* Chapter 8.4.9 */
+/* Chapter 8.4.9: Modify channel mode on BTS side */
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;
- 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));
@@ -1079,8 +1090,10 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
arfcn = lchan->ts->trx->arfcn;
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->ms_power = ms_pwr_ctl_lvl(bts, 20 /* dBm == 100mW */);
+ lchan->bs_power = 0x0f; /* 30dB reduction */
+ 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));
@@ -1177,7 +1190,7 @@ static int rsl_rx_rll_err_ind(struct msgb *msg)
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
u_int8_t *rlm_cause = rllh->data;
- DEBUGPC(DRLL, "cause=0x%02x", rlm_cause[1]);
+ DEBUGPC(DRLL, "ERROR INDICATION cause=0x%02x\n", rlm_cause[1]);
if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED)
return rsl_chan_release(msg->lchan);
@@ -1221,30 +1234,27 @@ static int abis_rsl_rx_rll(struct msgb *msg)
}
break;
case RSL_MT_REL_IND:
- DEBUGPC(DRLL, "RELEASE INDICATION ");
+ DEBUGPC(DRLL, "RELEASE INDICATION\n");
break;
case RSL_MT_REL_CONF:
- DEBUGPC(DRLL, "RELEASE CONFIRMATION ");
+ DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
break;
case RSL_MT_ERROR_IND:
- DEBUGPC(DRLL, "ERROR INDICATION ");
rc = rsl_rx_rll_err_ind(msg);
break;
case RSL_MT_UNIT_DATA_IND:
- DEBUGPC(DRLL, "unimplemented Abis RLL message type 0x%02x ",
+ DEBUGPC(DRLL, "unimplemented Abis RLL message type 0x%02x\n",
rllh->c.msg_type);
break;
default:
- DEBUGPC(DRLL, "unknown Abis RLL message type 0x%02x ",
+ DEBUGPC(DRLL, "unknown Abis RLL message type 0x%02x\n",
rllh->c.msg_type);
}
- DEBUGPC(DRLL, "\n");
return rc;
}
static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
{
-#if 0
switch (tch_mode) {
case GSM48_CMODE_SPEECH_V1:
return 0x00;
@@ -1254,12 +1264,9 @@ static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
return 0x02;
/* FIXME: Type1 half-rate and type3 half-rate */
}
+ DEBUGPC(DRSL, "Cannot determine ip.access speech mode for "
+ "tch_mode == 0x%02x\n", tch_mode);
return 0;
-#else
- /* hard-code EFR for now, since tch_mode is not correct at this
- * point in time */
- return 0x01;
-#endif
}
/* ip.access specific RSL extensions */
@@ -1267,19 +1274,20 @@ int rsl_ipacc_bind(struct gsm_lchan *lchan)
{
struct msgb *msg = rsl_msgb_alloc();
struct abis_rsl_dchan_hdr *dh;
- u_int8_t speech_mode_s;
+ u_int8_t speech_mode;
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, RSL_MT_IPAC_BIND);
dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
dh->chan_nr = lchan2chan_nr(lchan);
- speech_mode_s = ipa_smod_s_for_tch_mode(lchan->tch_mode);
/* 0x1- == receive-only, 0x-1 == EFR codec */
- msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, 0x10 | speech_mode_s);
+ speech_mode = 0x10 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
+ msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
- DEBUGPC(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND\n",
- gsm_ts_name(lchan->ts), dh->chan_nr);
+ DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND "
+ "speech_mode=0x%02x\n", gsm_ts_name(lchan->ts),
+ dh->chan_nr, speech_mode);
msg->trx = lchan->ts->trx;
@@ -1292,7 +1300,7 @@ int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
struct msgb *msg = rsl_msgb_alloc();
struct abis_rsl_dchan_hdr *dh;
u_int8_t *att_f8, *att_ip, *att_port;
- u_int8_t speech_mode_s;
+ u_int8_t speech_mode;
struct in_addr ia;
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
@@ -1300,11 +1308,14 @@ int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
dh->chan_nr = lchan2chan_nr(lchan);
+ /* 0x0- == both directions, 0x-1 == EFR codec */
+ speech_mode = 0x00 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
+
ia.s_addr = htonl(ip);
- DEBUGP(DRSL, "IPAC_CONNECT channel=%s chan_nr=0x%02x "
- "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d\n",
+ DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_CONNECT "
+ "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d speech_mode=0x%02x\n",
gsm_ts_name(lchan->ts), dh->chan_nr,
- inet_ntoa(ia), port, rtp_payload2, conn_id);
+ inet_ntoa(ia), port, rtp_payload2, conn_id, speech_mode);
att_f8 = msgb_put(msg, sizeof(conn_id)+1);
att_f8[0] = RSL_IE_IPAC_CONN_ID;
@@ -1324,9 +1335,7 @@ int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
att_port[1] = port >> 8;
att_port[2] = port & 0xff;
- speech_mode_s = ipa_smod_s_for_tch_mode(lchan->tch_mode);
- /* 0x0- == both directions, 0x-1 == EFR codec */
- msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, 0x00 | speech_mode_s);
+ msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
if (rtp_payload2)
msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);