From a6bcc7471642f4076b0aa31ae04647f1499e9bb4 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 16 Nov 2009 22:49:24 +0100 Subject: [gsm48] When picking AMR we need to supply the multirate config On channel mode modify and assignment command when using the a multirate code the multirate configuration must be present in the packet. Add a parameter and add a warning when using it in a broken way. --- openbsc/include/openbsc/gsm_04_08.h | 22 ++++++++++++++++++++-- openbsc/src/gsm_04_08.c | 2 +- openbsc/src/gsm_04_08_utils.c | 35 +++++++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 3e9557b1d..5bd860be9 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -33,6 +33,23 @@ struct gsm48_chan_desc { }; } __attribute__ ((packed)); +/* Chapter 10.5.2.21aa */ +struct gsm48_multi_rate_conf { + u_int8_t smod : 2, + spare: 1, + icmi : 1, + nscb : 1, + ver : 3; + u_int8_t m4_75 : 1, + m5_15 : 1, + m5_90 : 1, + m6_70 : 1, + m7_40 : 1, + m7_95 : 1, + m10_2 : 1, + m12_2 : 1; +} __attribute__((packed)); + /* Chapter 10.5.2.30 */ struct gsm48_req_ref { u_int8_t ra; @@ -411,6 +428,7 @@ struct gsm48_imsi_detach_ind { #define GSM_MI_TYPE_TMSI 0x04 #define GSM_MI_ODD 0x08 +#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */ #define GSM48_IE_MOBILE_ID 0x17 #define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */ #define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */ @@ -741,7 +759,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 gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_class, struct gsm48_multi_rate_conf *conf); int bsc_upqueue(struct gsm_network *net); @@ -759,7 +777,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_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode, struct gsm48_multi_rate_conf *conf); 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 6a4abfc3a..7a8bcbdea 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -3139,7 +3139,7 @@ static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg) { struct gsm_mncc *mode = arg; - return gsm48_lchan_modify(trans->lchan, mode->lchan_mode); + return gsm48_lchan_modify(trans->lchan, mode->lchan_mode, NULL); } static struct downstate { diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 08aadf99d..053e999b7 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -504,7 +504,8 @@ int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv) } /* Chapter 9.1.2: Assignment Command */ -int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command) +int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command, + struct gsm48_multi_rate_conf *conf) { struct msgb *msg = gsm48_msgb_alloc(); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); @@ -533,11 +534,24 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command) ass->chan_desc.h0.arfcn_low = arfcn & 0xff; ass->power_command = power_command; + /* in case of multi rate we need to attach a config */ + if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) { + if (!conf) { + DEBUGP(DRR, "BUG: Using multirate codec without multirate config.\n"); + } else { + u_int8_t *data = msgb_put(msg, 4); + data[0] = GSM48_IE_MUL_RATE_CFG; + data[1] = 0x2; + memcpy(&data[2], conf, 2); + } + } + 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) +int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode, + struct gsm48_multi_rate_conf *conf) { struct msgb *msg = gsm48_msgb_alloc(); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); @@ -561,14 +575,27 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode) cmm->chan_desc.h0.arfcn_low = arfcn & 0xff; cmm->mode = mode; + /* in case of multi rate we need to attach a config */ + if (mode == GSM48_CMODE_SPEECH_AMR) { + if (!conf) { + DEBUGP(DRR, "BUG: Using multirate codec without multirate config.\n"); + } else { + u_int8_t *data = msgb_put(msg, 4); + data[0] = GSM48_IE_MUL_RATE_CFG; + data[1] = 0x2; + memcpy(&data[2], conf, 2); + } + } + return gsm48_sendmsg(msg, NULL); } -int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode) +int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode, + struct gsm48_multi_rate_conf *conf) { int rc; - rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode); + rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode, conf); if (rc < 0) return rc; -- cgit v1.2.3