aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2009-10-27 09:41:24 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2009-10-27 09:41:24 +0100
commit304222b6149b0d809dd9fb1d820494374768d92f (patch)
tree55c177c49c9a104cd680a039685186692476cfe2 /openbsc
parent55aac6e868d4f3b565bba310598104c53c53da0a (diff)
parentf520e6439a917777a4a456fea7eb0f214e027c67 (diff)
Merge branch 'holger/merge-on-waves-msc'
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h19
-rw-r--r--openbsc/src/abis_rsl.c1
-rw-r--r--openbsc/src/gsm_04_08.c51
-rw-r--r--openbsc/src/gsm_04_08_utils.c113
4 files changed, 136 insertions, 48 deletions
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 8c944e6ac..186a53f97 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -42,7 +42,11 @@ struct gsm48_req_ref {
t3_low:3;
} __attribute__ ((packed));
-/* Chapter 9.1.5 */
+/*
+ * Chapter 9.1.5/9.1.6
+ *
+ * For 9.1.6 the chan_desc has the meaning of 10.5.2.5a
+ */
struct gsm48_chan_mode_modify {
struct gsm48_chan_desc chan_desc;
u_int8_t mode;
@@ -59,6 +63,15 @@ enum gsm48_chan_mode {
GSM48_CMODE_DATA_3k6 = 0x23,
};
+/* Chapter 9.1.2 */
+struct gsm48_ass_cmd {
+ /* Semantic is from 10.5.2.5a */
+ struct gsm48_chan_desc chan_desc;
+ u_int8_t power_command;
+ u_int8_t data[0];
+} __attribute__((packed));
+
+
/* Chapter 9.1.18 */
struct gsm48_imm_ass {
u_int8_t l2_plen;
@@ -727,6 +740,7 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan);
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
u_int8_t apdu_len, const u_int8_t *apdu);
+int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_class);
int bsc_upqueue(struct gsm_network *net);
@@ -744,4 +758,7 @@ int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv);
int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr);
+int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode);
+int gsm48_rx_rr_modif_ack(struct msgb *msg);
+
#endif
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 6b328bb28..a4764f5fb 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -239,6 +239,7 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
return lchan;
}
+/* See Table 10.5.25 of GSM04.08 */
u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
{
struct gsm_bts_trx_ts *ts = lchan->ts;
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 23739657d..12cc36245 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -1087,34 +1087,6 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
return gsm0408_authorize(lchan, msg);
}
-/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
-int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
-{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- struct gsm48_chan_mode_modify *cmm =
- (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
- u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
-
- DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
-
- lchan->tch_mode = mode;
- msg->lchan = lchan;
- gh->proto_discr = GSM48_PDISC_RR;
- gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
-
- /* fill the channel information element, this code
- * should probably be shared with rsl_rx_chan_rqd() */
- cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
- cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
- cmm->chan_desc.h0.h = 0;
- cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
- cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
- cmm->mode = mode;
-
- return gsm48_sendmsg(msg, NULL);
-}
-
#if 0
static u_int8_t to_bcd8(u_int8_t val)
{
@@ -1615,11 +1587,7 @@ static int gsm0408_rcv_rr(struct msgb *msg)
rc = gsm48_rx_rr_pag_resp(msg);
break;
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
- 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);
+ rc = gsm48_rx_rr_modif_ack(msg);
break;
case GSM48_MT_RR_STATUS:
rc = gsm48_rx_rr_status(msg);
@@ -3167,22 +3135,11 @@ static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
}
-static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
+static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
{
struct gsm_mncc *mode = arg;
- int rc;
- rc = gsm48_tx_chan_mode_modify(trans->lchan, mode->lchan_mode);
- if (rc < 0)
- return rc;
-
- /* FIXME: we not only need to do this after mode modify, but
- * also after channel activation */
- if (is_ipaccess_bts(trans->lchan->ts->trx->bts) &&
- mode->lchan_mode != GSM48_CMODE_SIGN)
- rc = rsl_ipacc_bind(trans->lchan);
-
- return rc;
+ return gsm48_lchan_modify(trans->lchan, mode->lchan_mode);
}
static struct downstate {
@@ -3240,7 +3197,7 @@ static struct downstate {
MNCC_REL_REQ, gsm48_cc_tx_release},
/* special */
{ALL_STATES,
- MNCC_LCHAN_MODIFY, gsm48_lchan_modify},
+ MNCC_LCHAN_MODIFY, _gsm48_lchan_modify},
};
#define DOWNSLLEN \
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index ef9e59c77..2545f33a6 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -482,3 +482,116 @@ int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
return rsl_encryption_cmd(msg);
}
+/* Chapter 9.1.2: Assignment Command */
+int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ struct gsm48_ass_cmd *ass =
+ (struct gsm48_ass_cmd *) msgb_put(msg, sizeof(*ass));
+ u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
+
+ DEBUGP(DRR, "-> ASSIGNMENT COMMAND tch_mode=0x%02x\n", lchan->tch_mode);
+
+ msg->lchan = lchan;
+ gh->proto_discr = GSM48_PDISC_RR;
+ gh->msg_type = GSM48_MT_RR_ASS_CMD;
+
+ /*
+ * fill the channel information element, this code
+ * should probably be shared with rsl_rx_chan_rqd(),
+ * gsm48_tx_chan_mode_modify. But beware that 10.5.2.5
+ * 10.5.2.5.a have slightly different semantic for
+ * the chan_desc. But as long as multi-slot configurations
+ * are not used we seem to be fine.
+ */
+ ass->chan_desc.chan_nr = lchan2chan_nr(lchan);
+ ass->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
+ ass->chan_desc.h0.h = 0;
+ ass->chan_desc.h0.arfcn_high = arfcn >> 8;
+ ass->chan_desc.h0.arfcn_low = arfcn & 0xff;
+ ass->power_command = power_command;
+
+ return gsm48_sendmsg(msg, NULL);
+}
+
+/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
+int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ struct gsm48_chan_mode_modify *cmm =
+ (struct gsm48_chan_mode_modify *) msgb_put(msg, sizeof(*cmm));
+ u_int16_t arfcn = lchan->ts->trx->arfcn & 0x3ff;
+
+ DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
+
+ lchan->tch_mode = mode;
+ msg->lchan = lchan;
+ gh->proto_discr = GSM48_PDISC_RR;
+ gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
+
+ /* fill the channel information element, this code
+ * should probably be shared with rsl_rx_chan_rqd() */
+ cmm->chan_desc.chan_nr = lchan2chan_nr(lchan);
+ cmm->chan_desc.h0.tsc = lchan->ts->trx->bts->tsc;
+ cmm->chan_desc.h0.h = 0;
+ cmm->chan_desc.h0.arfcn_high = arfcn >> 8;
+ cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
+ cmm->mode = mode;
+
+ return gsm48_sendmsg(msg, NULL);
+}
+
+int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode)
+{
+ int rc;
+
+ rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode);
+ if (rc < 0)
+ return rc;
+
+ /* FIXME: we not only need to do this after mode modify, but
+ * also after channel activation */
+ if (is_ipaccess_bts(lchan->ts->trx->bts) && lchan_mode != GSM48_CMODE_SIGN)
+ rc = rsl_ipacc_bind(lchan);
+
+ return rc;
+}
+
+int gsm48_rx_rr_modif_ack(struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ struct gsm48_chan_mode_modify *mod =
+ (struct gsm48_chan_mode_modify *) gh->data;
+
+ DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
+
+ if (mod->mode != msg->lchan->tch_mode) {
+ DEBUGP(DRR, "CHANNEL MODE change failed. Wanted: %d Got: %d\n",
+ msg->lchan->tch_mode, mod->mode);
+ return -1;
+ }
+
+ /* update the channel type */
+ switch (mod->mode) {
+ case GSM48_CMODE_SIGN:
+ msg->lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
+ break;
+ case GSM48_CMODE_SPEECH_V1:
+ case GSM48_CMODE_SPEECH_EFR:
+ case GSM48_CMODE_SPEECH_AMR:
+ msg->lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH;
+ break;
+ case GSM48_CMODE_DATA_14k5:
+ case GSM48_CMODE_DATA_12k0:
+ case GSM48_CMODE_DATA_6k0:
+ case GSM48_CMODE_DATA_3k6:
+ msg->lchan->rsl_cmode = RSL_CMOD_SPD_DATA;
+ break;
+ }
+
+ /* We've successfully modified the MS side of the channel,
+ * now go on to modify the BTS side of the channel */
+ return rsl_chan_mode_modify_req(msg->lchan);
+}