From e723eac5a35d61829d9471b97a029c921c04a258 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 15 Nov 2009 12:56:12 +0100 Subject: [telnet] Remove unused variables from the telnet interface These became unused when the interface was switched to use the vty module. It is about time to remove these. --- openbsc/include/openbsc/telnet_interface.h | 7 ------- openbsc/src/telnet_interface.c | 1 - 2 files changed, 8 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/telnet_interface.h b/openbsc/include/openbsc/telnet_interface.h index 97357d794..d3381e0a4 100644 --- a/openbsc/include/openbsc/telnet_interface.h +++ b/openbsc/include/openbsc/telnet_interface.h @@ -35,13 +35,6 @@ struct telnet_connection { struct gsm_network *network; struct bsc_fd fd; struct vty *vty; - - int bts; - - int command; - char *imsi; - char commands[1024]; - int read; }; diff --git a/openbsc/src/telnet_interface.c b/openbsc/src/telnet_interface.c index d7c905518..128c34e94 100644 --- a/openbsc/src/telnet_interface.c +++ b/openbsc/src/telnet_interface.c @@ -165,7 +165,6 @@ static int telnet_new_connection(struct bsc_fd *fd, unsigned int what) { connection->fd.fd = new_connection; connection->fd.when = BSC_FD_READ; connection->fd.cb = client_data; - connection->bts = 0; bsc_register_fd(&connection->fd); llist_add_tail(&connection->entry, &active_connections); -- cgit v1.2.3 From c7df7c6e42f6c952c2db1a634eb3530c8d33149d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 15 Nov 2009 13:50:39 +0100 Subject: [ipaccess] Fix spelling in the comment --- openbsc/src/input/ipaccess.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c index 34d9462b9..2d9f51ef9 100644 --- a/openbsc/src/input/ipaccess.c +++ b/openbsc/src/input/ipaccess.c @@ -543,7 +543,7 @@ static int rsl_listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what) /* Some BTS has connected to us, but we don't know yet which line * (as created by the OML link) to associate it with. Thus, we - * aloocate a temporary bfd until we have received ID from BTS */ + * allocate a temporary bfd until we have received ID from BTS */ bfd->fd = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len); if (bfd->fd < 0) { -- cgit v1.2.3 From 057fec5336312cf737885be24fb959b8fcb03ef2 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 16 Nov 2009 19:53:08 +0100 Subject: ipaccess-config.c: Spelling fix in the config mode --- openbsc/src/ipaccess-config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/ipaccess-config.c b/openbsc/src/ipaccess-config.c index 1b2aa5e34..c50a46581 100644 --- a/openbsc/src/ipaccess-config.c +++ b/openbsc/src/ipaccess-config.c @@ -279,7 +279,7 @@ static void print_help(void) printf(" -o --oml-ip ip\n"); printf(" -r --restart\n"); printf(" -n flags/mask\tSet NVRAM attributes.\n"); - printf(" -l --listen testnr \tPerform speciified test number\n"); + printf(" -l --listen testnr \tPerform specified test number\n"); printf(" -h --help this text\n"); printf(" -s --stream-id ID\n"); } -- cgit v1.2.3 From 0fef39a8ac17484f42840a898e06923c4989db38 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 16 Nov 2009 15:37:05 +0100 Subject: [rsl] Improve error message when the lchan allocation is failing --- openbsc/src/abis_rsl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index acd41dd63..de0f4845b 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1139,7 +1139,8 @@ static int rsl_rx_chan_rqd(struct msgb *msg) /* check availability / allocate channel */ lchan = lchan_alloc(bts, lctype); if (!lchan) { - fprintf(stderr, "CHAN RQD: no resources\n"); + DEBUGP(DRSL, "CHAN RQD: no resources for %u 0x%x\n", + lctype, rqd_ref->ra); /* FIXME: send some kind of reject ?!? */ return -ENOMEM; } -- cgit v1.2.3 From f7d752f7acc0ccee32959ad0586cbbb54b1efaf8 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 16 Nov 2009 17:12:38 +0100 Subject: [si] Make it possible to set the NECI value... Allow to configure the NECI value... and change code that is relying on the NECI value. --- openbsc/include/openbsc/gsm_04_08.h | 4 ++-- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/abis_rsl.c | 4 ++-- openbsc/src/bsc_init.c | 4 ++++ openbsc/src/gsm_04_08_utils.c | 8 ++++---- openbsc/src/vty_interface.c | 12 ++++++++++++ 6 files changed, 25 insertions(+), 8 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 186a53f97..4a3bdc187 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -724,8 +724,8 @@ void gsm0408_set_reject_cause(int cause); int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id); void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc, u_int16_t mnc, u_int16_t lac); -enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra); -enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra); +enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci); +enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci); int gsm48_tx_mm_info(struct gsm_lchan *lchan); int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 3040525c2..c1b7b05ac 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -410,6 +410,7 @@ struct gsm_network { char *name_short; enum gsm_auth_policy auth_policy; int a5_encryption; + int neci; /* layer 4 */ int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg); diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index de0f4845b..2d006030f 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1133,8 +1133,8 @@ static int rsl_rx_chan_rqd(struct msgb *msg) /* determine channel type (SDCCH/TCH_F/TCH_H) based on * request reference RA */ - lctype = get_ctype_by_chreq(bts, rqd_ref->ra); - chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra); + lctype = get_ctype_by_chreq(bts, rqd_ref->ra, bts->network->neci); + chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra, bts->network->neci); /* check availability / allocate channel */ lchan = lchan_alloc(bts, lctype); diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c index bb1e382f0..d11cde578 100644 --- a/openbsc/src/bsc_init.c +++ b/openbsc/src/bsc_init.c @@ -956,6 +956,10 @@ static void patch_si_tables(struct gsm_bts *bts) type_4->cell_sel_par.ms_txpwr_max_ccch = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power); + /* Set NECI to influence channel request */ + type_3->cell_sel_par.neci = bts->network->neci; + type_4->cell_sel_par.neci = bts->network->neci; + if (bts->cell_barred) { type_1->rach_control.cell_bar = 1; type_2->rach_control.cell_bar = 1; diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 2545f33a6..0e242b778 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -302,13 +302,13 @@ static const enum gsm_chreq_reason_t reason_by_chreq[] = { [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG, }; -enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra) +enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci) { int i; /* FIXME: determine if we set NECI = 0 in the BTS SI4 */ for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) { - const struct chreq *chr = &chreq_type_neci0[i]; + const struct chreq *chr = neci ? &chreq_type_neci1[i] : &chreq_type_neci0[i]; if ((ra & chr->mask) == chr->val) return ctype_by_chreq[chr->type]; } @@ -316,13 +316,13 @@ enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra) return GSM_LCHAN_SDCCH; } -enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra) +enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci) { int i; /* FIXME: determine if we set NECI = 0 in the BTS SI4 */ for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) { - const struct chreq *chr = &chreq_type_neci0[i]; + const struct chreq *chr = neci ? &chreq_type_neci1[i] : &chreq_type_neci0[i]; if ((ra & chr->mask) == chr->val) return reason_by_chreq[chr->type]; } diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 894146b6f..54c9d5c68 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -87,6 +87,8 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net) gsm_auth_policy_name(net->auth_policy), VTY_NEWLINE); vty_out(vty, " Encryption: A5/%u%s", net->a5_encryption, VTY_NEWLINE); + vty_out(vty, " NECI (TCH/H): %u%s", net->neci, + VTY_NEWLINE); } DEFUN(show_net, show_net_cmd, "show network", @@ -789,6 +791,15 @@ DEFUN(cfg_net_encryption, return CMD_SUCCESS; } +DEFUN(cfg_net_neci, + cfg_net_neci_cmd, + "neci (0|1)", + "Set if NECI of cell selection is to be set") +{ + gsmnet->neci = atoi(argv[0]); + return CMD_SUCCESS; +} + /* per-BTS configuration */ DEFUN(cfg_bts, cfg_bts_cmd, @@ -1228,6 +1239,7 @@ int bsc_vty_init(struct gsm_network *net) install_element(GSMNET_NODE, &cfg_net_name_long_cmd); install_element(GSMNET_NODE, &cfg_net_auth_policy_cmd); install_element(GSMNET_NODE, &cfg_net_encryption_cmd); + install_element(GSMNET_NODE, &cfg_net_neci_cmd); install_element(GSMNET_NODE, &cfg_bts_cmd); install_node(&bts_node, config_write_bts); -- cgit v1.2.3 From 1059deb7829e93bbe5baf156d6cfbd1eea36ece0 Mon Sep 17 00:00:00 2001 From: "Andreas.Eversberg" Date: Tue, 17 Nov 2009 09:55:26 +0100 Subject: Fix configuration file generation Assign the encryption status to the right variable. Signed-off-by: Holger Freyther --- openbsc/src/vty_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 54c9d5c68..a7188a414 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -786,7 +786,7 @@ DEFUN(cfg_net_encryption, "encryption a5 (0|1|2)", "Enable or disable encryption (A5) for this network\n") { - gsmnet->auth_policy = atoi(argv[0]); + gsmnet->a5_encryption= atoi(argv[0]); return CMD_SUCCESS; } -- cgit v1.2.3 From fe9da827fd29b8e153a43d44865a37ff36ae446d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 17 Nov 2009 10:16:46 +0100 Subject: [paging] In expiration handling remove the request before doing the callback Not doing this could lead to a double deletion due the paging request being removed during the callback and afterwards as well. Change the code to save the callback data, remove the request, do the callback. A patch was proposed by Andreas Eversberg and this one is based on it. --- openbsc/src/paging.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index 87c7e7d38..69902e8b1 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -197,6 +197,8 @@ static void paging_T3113_expired(void *data) { struct gsm_paging_request *req = (struct gsm_paging_request *)data; struct paging_signal_data sig_data; + void *cbfn_param; + gsm_cbfn *cbfn; DEBUGP(DPAG, "T3113 expired for request %p (%s)\n", req, req->subscr->imsi); @@ -205,11 +207,15 @@ static void paging_T3113_expired(void *data) sig_data.bts = req->bts; sig_data.lchan = NULL; - dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data); - if (req->cbfn) - req->cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, NULL, NULL, - req->cbfn_param); + /* must be destroyed before calling cbfn, to prevent double free */ + cbfn_param = req->cbfn_param; + cbfn = req->cbfn; paging_remove_request(&req->bts->paging, req); + + dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data); + if (cbfn) + cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, NULL, NULL, + cbfn_param); } static int _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, -- cgit v1.2.3 From 843b44d261c5d1087face85cc95a68fcf2efad24 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 17 Nov 2009 16:38:25 +0100 Subject: [neci] Use the correct length when going over the array Use the correct length when going over the array instead of using the neci0 values. Remove the fixme from the method as well as the issue has been addressed by adding a parameter to the method. --- openbsc/src/gsm_04_08_utils.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 0e242b778..e95de79fa 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -305,10 +305,20 @@ static const enum gsm_chreq_reason_t reason_by_chreq[] = { enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci) { int i; - /* FIXME: determine if we set NECI = 0 in the BTS SI4 */ + int length; + const struct chreq *chreq; - for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) { - const struct chreq *chr = neci ? &chreq_type_neci1[i] : &chreq_type_neci0[i]; + if (neci) { + chreq = chreq_type_neci1; + length = ARRAY_SIZE(chreq_type_neci1); + } else { + chreq = chreq_type_neci0; + length = ARRAY_SIZE(chreq_type_neci0); + } + + + for (i = 0; i < length; i++) { + const struct chreq *chr = &chreq[i]; if ((ra & chr->mask) == chr->val) return ctype_by_chreq[chr->type]; } @@ -319,10 +329,19 @@ enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci) enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci) { int i; - /* FIXME: determine if we set NECI = 0 in the BTS SI4 */ + int length; + const struct chreq *chreq; + + if (neci) { + chreq = chreq_type_neci1; + length = ARRAY_SIZE(chreq_type_neci1); + } else { + chreq = chreq_type_neci0; + length = ARRAY_SIZE(chreq_type_neci0); + } - for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) { - const struct chreq *chr = neci ? &chreq_type_neci1[i] : &chreq_type_neci0[i]; + for (i = 0; i < length; i++) { + const struct chreq *chr = &chreq[i]; if ((ra & chr->mask) == chr->val) return reason_by_chreq[chr->type]; } -- cgit v1.2.3 From 135a7c65cd3bf127d0e9a2613da5699b74f9be0f Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 17 Nov 2009 16:46:46 +0100 Subject: [neci] Separate handling of chan requested for paging any Allow to handle the channel requested differently based on the NECI value for the "paging any" case. This will allow to open a TCH/H, TCH/F depending on the neci mode. --- openbsc/include/openbsc/gsm_04_08.h | 3 ++- openbsc/src/gsm_04_08_utils.c | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 4a3bdc187..3e9557b1d 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -634,7 +634,8 @@ enum chreq_type { CHREQ_T_VOICE_CALL_TCH_H, CHREQ_T_DATA_CALL_TCH_H, CHREQ_T_LOCATION_UPD, - CHREQ_T_PAG_R_ANY, + CHREQ_T_PAG_R_ANY_NECI0, + CHREQ_T_PAG_R_ANY_NECI1, CHREQ_T_PAG_R_TCH_F, CHREQ_T_PAG_R_TCH_FH, }; diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index e95de79fa..08aadf99d 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -255,7 +255,7 @@ static const struct chreq chreq_type_neci1[] = { { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H }, { 0x00, 0xf0, CHREQ_T_LOCATION_UPD }, { 0x10, 0xf0, CHREQ_T_SDCCH }, - { 0x80, 0xe0, CHREQ_T_PAG_R_ANY }, + { 0x80, 0xe0, CHREQ_T_PAG_R_ANY_NECI1 }, { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F }, { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH }, }; @@ -267,7 +267,7 @@ static const struct chreq chreq_type_neci0[] = { { 0xe0, 0xe0, CHREQ_T_TCH_F }, { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H }, { 0x00, 0xe0, CHREQ_T_LOCATION_UPD }, - { 0x80, 0xe0, CHREQ_T_PAG_R_ANY }, + { 0x80, 0xe0, CHREQ_T_PAG_R_ANY_NECI0 }, { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F }, { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH }, }; @@ -282,7 +282,8 @@ static const enum gsm_chan_t ctype_by_chreq[] = { [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H, [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H, [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH, - [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH, + [CHREQ_T_PAG_R_ANY_NECI1] = GSM_LCHAN_SDCCH, + [CHREQ_T_PAG_R_ANY_NECI0] = GSM_LCHAN_SDCCH, [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F, [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F, }; @@ -297,7 +298,8 @@ static const enum gsm_chreq_reason_t reason_by_chreq[] = { [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER, [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER, [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD, - [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG, + [CHREQ_T_PAG_R_ANY_NECI1] = GSM_CHREQ_REASON_PAG, + [CHREQ_T_PAG_R_ANY_NECI0] = GSM_CHREQ_REASON_PAG, [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG, [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG, }; -- cgit v1.2.3 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(-) (limited to 'openbsc') 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