aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2009-11-16 22:49:24 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2009-11-17 18:20:17 +0100
commita6bcc7471642f4076b0aa31ae04647f1499e9bb4 (patch)
treee9633ec4183200a352d2d578b870cae385dfc93d /openbsc
parent135a7c65cd3bf127d0e9a2613da5699b74f9be0f (diff)
[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.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h22
-rw-r--r--openbsc/src/gsm_04_08.c2
-rw-r--r--openbsc/src/gsm_04_08_utils.c35
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;