From e81a6109f9e94ec5dcceb44a7ef1ea8cc52e7cb1 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 22 Oct 2009 11:47:45 +0200 Subject: [PATCH 1/3] [gsm48] Add generation of ASSIGNMENT COMMAND to the 0408 utils Add code to generate an assignment command for a given lchan. It is expected that the lchan is modified already and the mode will be picked up from their. Currently only the mandantory items are supported. --- openbsc/include/openbsc/gsm_04_08.h | 10 +++++++++ openbsc/src/abis_rsl.c | 1 + openbsc/src/gsm_04_08_utils.c | 32 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 8c944e6ac..ae13581f2 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -59,6 +59,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 +736,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); 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_utils.c b/openbsc/src/gsm_04_08_utils.c index ef9e59c77..358212f17 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -482,3 +482,35 @@ 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); +} From ff3f260e4fdc8445c7460cb8af1b23fb397467b2 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 22 Oct 2009 15:13:00 +0200 Subject: [PATCH 2/3] [gsm48] Move RR CHANNEL MODIFY to gsm_04_08_utils.c Be able to send RR CHANNEL MODIFY from the BSC/MSC code as well. Move the method that knows about the IPAccess RTP and issues the "bind" to the utils tool --- openbsc/include/openbsc/gsm_04_08.h | 2 ++ openbsc/src/gsm_04_08.c | 45 ++--------------------------- openbsc/src/gsm_04_08_utils.c | 45 +++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index ae13581f2..2afc9c5fd 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -754,4 +754,6 @@ 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); + #endif diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 23739657d..a29d0362b 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) { @@ -3167,22 +3139,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 +3201,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 358212f17..598775c03 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -514,3 +514,48 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t 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; +} + From f520e6439a917777a4a456fea7eb0f214e027c67 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 22 Oct 2009 15:23:11 +0200 Subject: [PATCH 3/3] [gsm48] Handle the RR CHAN MODIFY ACK in the gsm04_08_utils Move the handling code to the gsm_04_08_utils.c and add a note that the method value needs to be checked. --- openbsc/include/openbsc/gsm_04_08.h | 7 +++++- openbsc/src/gsm_04_08.c | 6 +---- openbsc/src/gsm_04_08_utils.c | 36 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 2afc9c5fd..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; @@ -755,5 +759,6 @@ 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/gsm_04_08.c b/openbsc/src/gsm_04_08.c index a29d0362b..12cc36245 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1587,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); diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 598775c03..2545f33a6 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -559,3 +559,39 @@ int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode) 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); +}