blob: 6785be2e809fc7fa6d2cd919a61e74b202dd7173 [file] [log] [blame]
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001/* GSM Radio Signalling Link messages on the A-bis interface
Harald Welte59b04682009-06-10 05:40:52 +08002 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Weltea22d36b2010-03-04 10:33:10 +01004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freythere38af682011-12-27 22:24:17 +01005 * (C) 2012 by Holger Hans Peter Freyther
Harald Welte59b04682009-06-10 05:40:52 +08006 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Welte59b04682009-06-10 05:40:52 +080012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte0e3e88e2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Welte59b04682009-06-10 05:40:52 +080018 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte59b04682009-06-10 05:40:52 +080021 *
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <errno.h>
Harald Welte59b04682009-06-10 05:40:52 +080027#include <netinet/in.h>
28#include <arpa/inet.h>
29
30#include <openbsc/gsm_data.h>
31#include <openbsc/gsm_04_08.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010032#include <osmocom/gsm/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080033#include <openbsc/abis_rsl.h>
34#include <openbsc/chan_alloc.h>
Harald Welteed9a5ab2009-08-09 13:47:35 +020035#include <openbsc/bsc_rll.h>
Harald Welte59b04682009-06-10 05:40:52 +080036#include <openbsc/debug.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010037#include <osmocom/gsm/tlv.h>
Harald Welte59b04682009-06-10 05:40:52 +080038#include <openbsc/paging.h>
39#include <openbsc/signal.h>
Harald Weltec20bd1d2009-11-29 19:07:28 +010040#include <openbsc/meas_rep.h>
Harald Welte50517742009-12-20 15:42:44 +010041#include <openbsc/rtp_proxy.h>
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +020042#include <osmocom/abis/e1_input.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010043#include <osmocom/gsm/rsl.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010044#include <osmocom/core/talloc.h>
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080045
Harald Welte59b04682009-06-10 05:40:52 +080046#define RSL_ALLOC_SIZE 1024
47#define RSL_ALLOC_HEADROOM 128
48
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080049static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
50
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010051static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
52 struct gsm_meas_rep *resp)
53{
54 struct lchan_signal_data sig;
55 sig.lchan = lchan;
56 sig.mr = resp;
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +020057 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010058}
59
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +010060static void do_lchan_free(struct gsm_lchan *lchan)
61{
62 /* we have an error timer pending to release that */
63 if (lchan->state != LCHAN_S_REL_ERR)
64 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
65 lchan_free(lchan);
66}
67
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020068static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080069{
70 /* mask off the transparent bit ? */
71 msg_type &= 0xfe;
72
73 if ((msg_type & 0xf0) == 0x00)
74 return ABIS_RSL_MDISC_RLL;
75 if ((msg_type & 0xf0) == 0x10) {
76 if (msg_type >= 0x19 && msg_type <= 0x22)
77 return ABIS_RSL_MDISC_TRX;
78 else
79 return ABIS_RSL_MDISC_COM_CHAN;
80 }
81 if ((msg_type & 0xe0) == 0x20)
82 return ABIS_RSL_MDISC_DED_CHAN;
83
84 return ABIS_RSL_MDISC_LOC;
85}
86
87static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020088 uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080089{
90 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
91 dh->c.msg_type = msg_type;
92 dh->ie_chan = RSL_IE_CHAN_NR;
93}
94
Harald Welte59b04682009-06-10 05:40:52 +080095/* determine logical channel based on TRX and channel number IE */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020096struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte59b04682009-06-10 05:40:52 +080097{
98 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020099 uint8_t ts_nr = chan_nr & 0x07;
100 uint8_t cbits = chan_nr >> 3;
101 uint8_t lch_idx;
Harald Welte59b04682009-06-10 05:40:52 +0800102 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
103
104 if (cbits == 0x01) {
105 lch_idx = 0; /* TCH/F */
Harald Welte37884ed2009-10-24 10:25:50 +0200106 if (ts->pchan != GSM_PCHAN_TCH_F &&
107 ts->pchan != GSM_PCHAN_PDCH &&
108 ts->pchan != GSM_PCHAN_TCH_F_PDCH)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100109 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800110 chan_nr, ts->pchan);
111 } else if ((cbits & 0x1e) == 0x02) {
112 lch_idx = cbits & 0x1; /* TCH/H */
113 if (ts->pchan != GSM_PCHAN_TCH_H)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100114 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800115 chan_nr, ts->pchan);
116 } else if ((cbits & 0x1c) == 0x04) {
117 lch_idx = cbits & 0x3; /* SDCCH/4 */
118 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100119 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800120 chan_nr, ts->pchan);
121 } else if ((cbits & 0x18) == 0x08) {
122 lch_idx = cbits & 0x7; /* SDCCH/8 */
123 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100124 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800125 chan_nr, ts->pchan);
126 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
127 lch_idx = 0;
128 if (ts->pchan != GSM_PCHAN_CCCH &&
129 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100130 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800131 chan_nr, ts->pchan);
132 /* FIXME: we should not return first sdcch4 !!! */
133 } else {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100134 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +0800135 return NULL;
136 }
137
138 lchan = &ts->lchan[lch_idx];
Harald Welte51d2a592010-03-26 21:28:59 +0800139 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther1a95fa82010-06-28 15:47:12 +0800140 if (lchan->conn)
141 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800142
143 return lchan;
144}
145
Harald Welte59b04682009-06-10 05:40:52 +0800146/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200147uint64_t str_to_imsi(const char *imsi_str)
Harald Welte59b04682009-06-10 05:40:52 +0800148{
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200149 uint64_t ret;
Harald Welte59b04682009-06-10 05:40:52 +0800150
151 ret = strtoull(imsi_str, NULL, 10);
152
153 return ret;
154}
155
Harald Welte59b04682009-06-10 05:40:52 +0800156static struct msgb *rsl_msgb_alloc(void)
157{
Harald Welte9cfc9352009-06-26 19:39:35 +0200158 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
159 "RSL");
Harald Welte59b04682009-06-10 05:40:52 +0800160}
161
162#define MACBLOCK_SIZE 23
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200163static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800164{
165 memcpy(out, in, len);
166
167 if (len < MACBLOCK_SIZE)
168 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
169}
170
Harald Welted2dd9de2009-08-30 15:37:11 +0900171/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200172static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welted2dd9de2009-08-30 15:37:11 +0900173{
174 *out++ = lchan->encr.alg_id & 0xff;
175 if (lchan->encr.key_len)
176 memcpy(out, lchan->encr.key, lchan->encr.key_len);
177 return lchan->encr.key_len + 1;
178}
179
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200180static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Weltef1a168d2009-07-28 17:58:09 +0200181{
Harald Welte59b04682009-06-10 05:40:52 +0800182 int i;
183
Harald Weltede4477a2009-12-24 12:20:20 +0100184 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Weltef1a168d2009-07-28 17:58:09 +0200185 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200186 for (i = 1; i < cause_len-1; i++)
Harald Weltede4477a2009-12-24 12:20:20 +0100187 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte59b04682009-06-10 05:40:52 +0800188}
189
Harald Welte32951ea2011-08-10 23:26:33 +0200190static void lchan_act_tmr_cb(void *data)
191{
192 struct gsm_lchan *lchan = data;
193
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100194 LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200195 gsm_lchan_name(lchan));
196
Daniel Willmann2731e732011-08-11 04:44:12 +0200197 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
198 lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200199}
200
201static void lchan_deact_tmr_cb(void *data)
202{
203 struct gsm_lchan *lchan = data;
204
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100205 LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200206 gsm_lchan_name(lchan));
207
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100208 do_lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200209}
210
211
Harald Welte59b04682009-06-10 05:40:52 +0800212/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200213int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
214 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800215{
216 struct abis_rsl_dchan_hdr *dh;
217 struct msgb *msg = rsl_msgb_alloc();
218
219 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
220 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
221 dh->chan_nr = RSL_CHAN_BCCH;
222
223 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
224 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
225
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200226 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800227
228 return abis_rsl_sendmsg(msg);
229}
230
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200231int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
232 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800233{
234 struct abis_rsl_common_hdr *ch;
235 struct msgb *msg = rsl_msgb_alloc();
236
237 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
238 ch->msg_discr = ABIS_RSL_MDISC_TRX;
239 ch->msg_type = RSL_MT_SACCH_FILL;
240
241 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
242 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
243
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200244 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800245
246 return abis_rsl_sendmsg(msg);
247}
248
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200249int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
250 const uint8_t *data, int len)
Harald Welte10b7d8f2011-01-13 23:16:03 +0100251{
252 struct abis_rsl_dchan_hdr *dh;
253 struct msgb *msg = rsl_msgb_alloc();
Harald Weltee6d51f92011-06-25 10:02:33 +0200254 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte10b7d8f2011-01-13 23:16:03 +0100255
256 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
257 init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
258 dh->chan_nr = chan_nr;
259
260 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
261 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
262
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200263 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte10b7d8f2011-01-13 23:16:03 +0100264
265 return abis_rsl_sendmsg(msg);
266}
267
Harald Welte91afe4c2009-06-20 18:15:19 +0200268int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
269{
270 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200271 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200272 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200273
274 db = abs(db);
275 if (db > 30)
276 return -EINVAL;
277
Harald Welteed831842009-06-27 03:09:08 +0200278 msg = rsl_msgb_alloc();
279
Harald Welte91afe4c2009-06-20 18:15:19 +0200280 lchan->bs_power = db/2;
281 if (fpc)
282 lchan->bs_power |= 0x10;
283
284 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
285 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
286 dh->chan_nr = chan_nr;
287
288 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
289
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200290 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200291
292 return abis_rsl_sendmsg(msg);
293}
294
Harald Welte91afe4c2009-06-20 18:15:19 +0200295int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
296{
297 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200298 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200299 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200300 int ctl_lvl;
301
Harald Weltec4dcda02009-08-09 14:45:18 +0200302 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Welte91afe4c2009-06-20 18:15:19 +0200303 if (ctl_lvl < 0)
304 return ctl_lvl;
305
Harald Welteed831842009-06-27 03:09:08 +0200306 msg = rsl_msgb_alloc();
307
Harald Welte91afe4c2009-06-20 18:15:19 +0200308 lchan->ms_power = ctl_lvl;
309
310 if (fpc)
311 lchan->ms_power |= 0x20;
312
313 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
314 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
315 dh->chan_nr = chan_nr;
316
317 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
318
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200319 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200320
321 return abis_rsl_sendmsg(msg);
322}
323
Harald Welte39274f42009-07-29 15:41:29 +0200324static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
325 struct gsm_lchan *lchan)
326{
327 memset(cm, 0, sizeof(cm));
328
329 /* FIXME: what to do with data calls ? */
Holger Hans Peter Freyther21d63ff2010-09-06 09:25:48 +0800330 if (lchan->ts->trx->bts->network->dtx_enabled)
331 cm->dtx_dtu = 0x03;
332 else
333 cm->dtx_dtu = 0x00;
Harald Welte39274f42009-07-29 15:41:29 +0200334
335 /* set TCH Speech/Data */
336 cm->spd_ind = lchan->rsl_cmode;
337
Harald Welte951e3512009-11-27 08:55:16 +0100338 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
339 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100340 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte951e3512009-11-27 08:55:16 +0100341 "but tch_mode != signalling\n");
342
Harald Welte39274f42009-07-29 15:41:29 +0200343 switch (lchan->type) {
344 case GSM_LCHAN_SDCCH:
345 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
346 break;
347 case GSM_LCHAN_TCH_F:
348 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
349 break;
350 case GSM_LCHAN_TCH_H:
351 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
352 break;
353 case GSM_LCHAN_NONE:
354 case GSM_LCHAN_UNKNOWN:
355 default:
356 return -EINVAL;
357 }
358
359 switch (lchan->tch_mode) {
360 case GSM48_CMODE_SIGN:
361 cm->chan_rate = 0;
362 break;
363 case GSM48_CMODE_SPEECH_V1:
364 cm->chan_rate = RSL_CMOD_SP_GSM1;
365 break;
366 case GSM48_CMODE_SPEECH_EFR:
367 cm->chan_rate = RSL_CMOD_SP_GSM2;
368 break;
369 case GSM48_CMODE_SPEECH_AMR:
370 cm->chan_rate = RSL_CMOD_SP_GSM3;
371 break;
372 case GSM48_CMODE_DATA_14k5:
Harald Welte39274f42009-07-29 15:41:29 +0200373 case GSM48_CMODE_DATA_12k0:
Harald Welte39274f42009-07-29 15:41:29 +0200374 case GSM48_CMODE_DATA_6k0:
Harald Weltee75a47d2012-08-24 15:33:56 +0200375 switch (lchan->csd_mode) {
376 case LCHAN_CSD_M_NT:
377 /* non-transparent CSD with RLP */
378 switch (lchan->tch_mode) {
379 case GSM48_CMODE_DATA_14k5:
380 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
381 break;
382 case GSM48_CMODE_DATA_12k0:
383 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
384 break;
385 case GSM48_CMODE_DATA_6k0:
386 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
387 break;
388 default:
389 return -EINVAL;
390 }
391 break;
392 /* transparent data services below */
393 case LCHAN_CSD_M_T_1200_75:
394 cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
395 break;
396 case LCHAN_CSD_M_T_600:
397 cm->chan_rate = RSL_CMOD_CSD_T_600;
398 break;
399 case LCHAN_CSD_M_T_1200:
400 cm->chan_rate = RSL_CMOD_CSD_T_1200;
401 break;
402 case LCHAN_CSD_M_T_2400:
403 cm->chan_rate = RSL_CMOD_CSD_T_2400;
404 break;
405 case LCHAN_CSD_M_T_9600:
406 cm->chan_rate = RSL_CMOD_CSD_T_9600;
407 break;
408 case LCHAN_CSD_M_T_14400:
409 cm->chan_rate = RSL_CMOD_CSD_T_14400;
410 break;
411 case LCHAN_CSD_M_T_29000:
412 cm->chan_rate = RSL_CMOD_CSD_T_29000;
413 break;
414 case LCHAN_CSD_M_T_32000:
415 cm->chan_rate = RSL_CMOD_CSD_T_32000;
416 break;
417 default:
418 return -EINVAL;
419 }
Harald Welte39274f42009-07-29 15:41:29 +0200420 default:
421 return -EINVAL;
422 }
423
424 return 0;
425}
426
Harald Welte59b04682009-06-10 05:40:52 +0800427/* Chapter 8.4.1 */
428#if 0
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200429int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
430 uint8_t act_type,
Harald Welte59b04682009-06-10 05:40:52 +0800431 struct rsl_ie_chan_mode *chan_mode,
432 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200433 uint8_t bs_power, uint8_t ms_power,
434 uint8_t ta)
Harald Welte59b04682009-06-10 05:40:52 +0800435{
436 struct abis_rsl_dchan_hdr *dh;
437 struct msgb *msg = rsl_msgb_alloc();
438
439 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
440 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
441 dh->chan_nr = chan_nr;
442
443 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
444 /* For compatibility with Phase 1 */
445 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200446 (uint8_t *) chan_mode);
Harald Welte59b04682009-06-10 05:40:52 +0800447 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200448 (uint8_t *) chan_ident);
Harald Welte59b04682009-06-10 05:40:52 +0800449#if 0
450 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200451 (uint8_t *) &encr_info);
Harald Welte59b04682009-06-10 05:40:52 +0800452#endif
453 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
454 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
455 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
456
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200457 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800458
459 return abis_rsl_sendmsg(msg);
460}
461#endif
462
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200463int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
464 uint8_t ta, uint8_t ho_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800465{
466 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200467 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200468 int rc;
Harald Weltedea24e92010-06-29 17:53:45 +0200469 uint8_t *len;
Harald Welte59b04682009-06-10 05:40:52 +0800470
Harald Weltee6d51f92011-06-25 10:02:33 +0200471 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800472 struct rsl_ie_chan_mode cm;
laforgef723cf02010-06-20 21:38:19 +0200473 struct gsm48_chan_desc cd;
Harald Welte59b04682009-06-10 05:40:52 +0800474
Harald Welte39274f42009-07-29 15:41:29 +0200475 rc = channel_mode_from_lchan(&cm, lchan);
476 if (rc < 0)
477 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800478
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800479 memset(&cd, 0, sizeof(cd));
laforgef723cf02010-06-20 21:38:19 +0200480 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800481
Harald Welteed831842009-06-27 03:09:08 +0200482 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800483 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
484 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
485 dh->chan_nr = chan_nr;
486
487 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte59b04682009-06-10 05:40:52 +0800488 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200489 (uint8_t *) &cm);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800490
491 /*
492 * The Channel Identification is needed for Phase1 phones
493 * and it contains the GSM48 Channel Description and the
494 * Mobile Allocation. The GSM 08.58 asks for the Mobile
495 * Allocation to have a length of zero. We are using the
496 * msgb_l3len to calculate the length of both messages.
497 */
laforgef723cf02010-06-20 21:38:19 +0200498 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Weltedea24e92010-06-29 17:53:45 +0200499 len = msgb_put(msg, 1);
Dieter Spaar18a55f62011-07-27 23:40:33 +0200500 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther4cab4422010-06-30 12:06:20 +0800501
502 if (lchan->ts->hopping.enabled)
503 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
504 lchan->ts->hopping.ma_data);
505 else
506 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800507
508 /* update the calculated size */
509 msg->l3h = len + 1;
510 *len = msgb_l3len(msg);
511
Harald Welted2dd9de2009-08-30 15:37:11 +0900512 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200513 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900514 rc = build_encr_info(encr_info, lchan);
515 if (rc > 0)
516 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
517 }
518
Harald Welteb90d7bd2009-12-17 00:31:10 +0100519 switch (act_type) {
520 case RSL_ACT_INTER_ASYNC:
521 case RSL_ACT_INTER_SYNC:
522 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
523 break;
524 default:
525 break;
526 }
527
Harald Welte59b04682009-06-10 05:40:52 +0800528 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
529 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
530 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
531
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100532 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
533 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200534 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100535
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200536 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800537
538 return abis_rsl_sendmsg(msg);
539}
540
Harald Welte8e770492009-07-29 11:38:15 +0200541/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welte59b04682009-06-10 05:40:52 +0800542int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
543{
544 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200545 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200546 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800547
Harald Weltee6d51f92011-06-25 10:02:33 +0200548 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800549 struct rsl_ie_chan_mode cm;
550
Harald Welte39274f42009-07-29 15:41:29 +0200551 rc = channel_mode_from_lchan(&cm, lchan);
552 if (rc < 0)
553 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800554
Harald Welteed831842009-06-27 03:09:08 +0200555 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800556 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
557 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
558 dh->chan_nr = chan_nr;
559
560 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200561 (uint8_t *) &cm);
Harald Welted2dd9de2009-08-30 15:37:11 +0900562
563 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200564 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900565 rc = build_encr_info(encr_info, lchan);
566 if (rc > 0)
567 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
568 }
569
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100570 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
571 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200572 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100573 }
574
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200575 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dd9de2009-08-30 15:37:11 +0900576
577 return abis_rsl_sendmsg(msg);
578}
579
580/* Chapter 8.4.6: Send the encryption command with given L3 info */
581int rsl_encryption_cmd(struct msgb *msg)
582{
583 struct abis_rsl_dchan_hdr *dh;
584 struct gsm_lchan *lchan = msg->lchan;
Harald Weltee6d51f92011-06-25 10:02:33 +0200585 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200586 uint8_t encr_info[MAX_A5_KEY_LEN+2];
587 uint8_t l3_len = msg->len;
Harald Welted2dd9de2009-08-30 15:37:11 +0900588 int rc;
589
590 /* First push the L3 IE tag and length */
591 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
592
593 /* then the link identifier (SAPI0, main sign link) */
594 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
595
596 /* then encryption information */
597 rc = build_encr_info(encr_info, lchan);
598 if (rc <= 0)
599 return rc;
600 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
601
602 /* and finally the DCHAN header */
603 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
604 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
605 dh->chan_nr = chan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800606
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200607 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800608
609 return abis_rsl_sendmsg(msg);
610}
611
Harald Welte85a163c2009-08-10 11:43:22 +0200612/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteafe3c232009-07-19 18:36:49 +0200613int rsl_deact_sacch(struct gsm_lchan *lchan)
614{
615 struct abis_rsl_dchan_hdr *dh;
616 struct msgb *msg = rsl_msgb_alloc();
617
618 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
619 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
Harald Weltee6d51f92011-06-25 10:02:33 +0200620 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteafe3c232009-07-19 18:36:49 +0200621
622 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200623 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteafe3c232009-07-19 18:36:49 +0200624
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100625 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteafe3c232009-07-19 18:36:49 +0200626
627 return abis_rsl_sendmsg(msg);
628}
629
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800630static void error_timeout_cb(void *data)
631{
632 struct gsm_lchan *lchan = data;
633 if (lchan->state != LCHAN_S_REL_ERR) {
634 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
635 gsm_lchan_name(lchan), lchan->state);
636 return;
637 }
638
639 /* go back to the none state */
640 LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800641 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800642}
643
Harald Welte08011e22011-03-04 13:41:31 +0100644static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
645
Harald Welte85a163c2009-08-10 11:43:22 +0200646/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800647static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte59b04682009-06-10 05:40:52 +0800648{
649 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800650 struct msgb *msg;
Harald Welte08011e22011-03-04 13:41:31 +0100651 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800652
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800653 if (lchan->state == LCHAN_S_REL_ERR) {
654 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
655 gsm_lchan_name(lchan));
656 return -1;
657 }
658
659 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800660 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
661 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltee6d51f92011-06-25 10:02:33 +0200662 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800663
664 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200665 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800666
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800667 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
668
669 if (error) {
670 /*
671 * the nanoBTS sends RLL release indications after the channel release. This can
672 * be a problem when we have reassigned the channel to someone else and then can
673 * not figure out who used this channel.
674 */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200675 struct e1inp_sign_link *sign_link = msg->dst;
676
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800677 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800678 lchan->error_timer.data = lchan;
679 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200680 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200681 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800682 }
Harald Welte59b04682009-06-10 05:40:52 +0800683
Harald Welte32951ea2011-08-10 23:26:33 +0200684 /* Start another timer or assume the BTS sends a ACK/NACK? */
685 lchan->act_timer.cb = lchan_deact_tmr_cb;
686 lchan->act_timer.data = lchan;
687 osmo_timer_schedule(&lchan->act_timer, 4, 0);
688
Harald Welte08011e22011-03-04 13:41:31 +0100689 rc = abis_rsl_sendmsg(msg);
690
Harald Welte85a163c2009-08-10 11:43:22 +0200691 /* BTS will respond by RF CHAN REL ACK */
Harald Welte6bddd822011-01-14 23:18:59 +0100692#ifdef HSL_SR_1_0
Harald Welte08011e22011-03-04 13:41:31 +0100693 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
694 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
695 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte6bddd822011-01-14 23:18:59 +0100696#endif
Harald Welte08011e22011-03-04 13:41:31 +0100697
698 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800699}
700
Harald Welte9773f6c2011-01-14 14:16:16 +0100701static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
702{
703
704 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
705
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100706 /* Stop all pending timers */
Harald Welte32951ea2011-08-10 23:26:33 +0200707 osmo_timer_del(&lchan->act_timer);
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100708 osmo_timer_del(&lchan->T3111);
Harald Welte32951ea2011-08-10 23:26:33 +0200709
Harald Welte9773f6c2011-01-14 14:16:16 +0100710 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
711 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
712 gsm_lchan_name(lchan),
713 gsm_lchans_name(lchan->state));
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100714 do_lchan_free(lchan);
Harald Welte9773f6c2011-01-14 14:16:16 +0100715
716 return 0;
717}
718
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200719int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
720 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte59b04682009-06-10 05:40:52 +0800721{
722 struct abis_rsl_dchan_hdr *dh;
723 struct msgb *msg = rsl_msgb_alloc();
724
725 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
726 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
727 dh->chan_nr = RSL_CHAN_PCH_AGCH;
728
729 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
730 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
731 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
732
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200733 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800734
735 return abis_rsl_sendmsg(msg);
736}
737
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200738int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte59b04682009-06-10 05:40:52 +0800739{
740 int i, len = strlen(str_in);
741
742 for (i = 0; i < len; i++) {
743 int num = str_in[i] - 0x30;
744 if (num < 0 || num > 9)
745 return -1;
746 if (i % 2 == 0)
747 bcd_out[i/2] = num;
748 else
749 bcd_out[i/2] |= (num << 4);
750 }
751
752 return 0;
753}
754
755/* Chapter 8.5.6 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200756int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte59b04682009-06-10 05:40:52 +0800757{
758 struct msgb *msg = rsl_msgb_alloc();
759 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200760 uint8_t buf[MACBLOCK_SIZE];
Harald Welte59b04682009-06-10 05:40:52 +0800761
762 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
763 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
764 dh->chan_nr = RSL_CHAN_PCH_AGCH;
765
766 switch (bts->type) {
767 case GSM_BTS_TYPE_BS11:
768 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
769 break;
770 default:
771 /* If phase 2, construct a FULL_IMM_ASS_INFO */
772 pad_macblock(buf, val, len);
773 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
774 break;
775 }
776
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200777 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800778
779 return abis_rsl_sendmsg(msg);
780}
781
Harald Welte4684e632009-08-10 09:51:40 +0200782/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte12090752009-08-10 10:07:33 +0200783int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte4684e632009-08-10 09:51:40 +0200784{
785 struct msgb *msg = rsl_msgb_alloc();
786 struct abis_rsl_dchan_hdr *dh;
787
788 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
789 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte874a5b42009-08-10 11:26:14 +0200790 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +0200791 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200792 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte4684e632009-08-10 09:51:40 +0200793
Harald Weltede4477a2009-12-24 12:20:20 +0100794 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200795 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte874a5b42009-08-10 11:26:14 +0200796
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200797 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte874a5b42009-08-10 11:26:14 +0200798
Harald Welte4684e632009-08-10 09:51:40 +0200799 return abis_rsl_sendmsg(msg);
800}
801
802
Harald Welte59b04682009-06-10 05:40:52 +0800803/* Send "DATA REQUEST" message with given L3 Info payload */
804/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200805int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800806{
Harald Welte59b04682009-06-10 05:40:52 +0800807 if (msg->lchan == NULL) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100808 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte59b04682009-06-10 05:40:52 +0800809 return -EINVAL;
810 }
811
Harald Weltee6d51f92011-06-25 10:02:33 +0200812 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100813 link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800814
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200815 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800816
817 return abis_rsl_sendmsg(msg);
818}
819
Harald Welteed9a5ab2009-08-09 13:47:35 +0200820/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
821/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200822int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteed9a5ab2009-08-09 13:47:35 +0200823{
Harald Weltea22d36b2010-03-04 10:33:10 +0100824 struct msgb *msg;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200825
Harald Weltee6d51f92011-06-25 10:02:33 +0200826 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100827 link_id, 0);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200828 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200829
Harald Welte17091bd2012-04-26 19:42:19 +0200830 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
831 gsm_lchan_name(lchan), link_id);
832
Harald Welteed9a5ab2009-08-09 13:47:35 +0200833 return abis_rsl_sendmsg(msg);
834}
835
Harald Welte0f2e3c12009-08-08 13:15:07 +0200836/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
837 This is what higher layers should call. The BTS then responds with
838 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
839 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
840 lchan_free() */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100841int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
842 enum rsl_rel_mode release_mode)
Harald Welte0f2e3c12009-08-08 13:15:07 +0200843{
Harald Welte0f2e3c12009-08-08 13:15:07 +0200844
Harald Weltea22d36b2010-03-04 10:33:10 +0100845 struct msgb *msg;
846
Harald Weltee6d51f92011-06-25 10:02:33 +0200847 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100848 link_id, 0);
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800849 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100850 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welte0f2e3c12009-08-08 13:15:07 +0200851
Harald Weltec88a4432009-12-29 10:44:17 +0100852 /* FIXME: start some timer in case we don't receive a REL ACK ? */
853
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200854 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte0f2e3c12009-08-08 13:15:07 +0200855
Harald Welte17091bd2012-04-26 19:42:19 +0200856 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100857 gsm_lchan_name(lchan), link_id, release_mode);
Harald Welte17091bd2012-04-26 19:42:19 +0200858
Harald Welte0f2e3c12009-08-08 13:15:07 +0200859 return abis_rsl_sendmsg(msg);
860}
861
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200862int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
863{
864 lchan->state = state;
865 return 0;
866}
867
Harald Welte59b04682009-06-10 05:40:52 +0800868/* Chapter 8.4.2: Channel Activate Acknowledge */
869static int rsl_rx_chan_act_ack(struct msgb *msg)
870{
871 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
872
873 /* BTS has confirmed channel activation, we now need
874 * to assign the activated channel to the MS */
875 if (rslh->ie_chan != RSL_IE_CHAN_NR)
876 return -EINVAL;
Harald Welte6720a432009-11-29 22:45:52 +0100877
Harald Welte32951ea2011-08-10 23:26:33 +0200878 osmo_timer_del(&msg->lchan->act_timer);
879
Harald Weltec88a4432009-12-29 10:44:17 +0100880 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welteab2534c2009-12-29 10:52:38 +0100881 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
882 gsm_lchan_name(msg->lchan),
883 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200884 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welte4baa9c52009-12-21 13:27:11 +0100885
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +0800886 if (msg->lchan->rqd_ref) {
887 rsl_send_imm_assignment(msg->lchan);
888 talloc_free(msg->lchan->rqd_ref);
889 msg->lchan->rqd_ref = NULL;
890 msg->lchan->rqd_ta = 0;
891 }
892
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100893 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100894
Harald Welte59b04682009-06-10 05:40:52 +0800895 return 0;
896}
897
898/* Chapter 8.4.3: Channel Activate NACK */
899static int rsl_rx_chan_act_nack(struct msgb *msg)
900{
901 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
902 struct tlv_parsed tp;
903
Harald Welte32951ea2011-08-10 23:26:33 +0200904 osmo_timer_del(&msg->lchan->act_timer);
905
Daniel Willmann9e9d44c2011-08-11 04:54:23 +0200906 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100907 gsm_lchan_name(msg->lchan));
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100908
Harald Welte59b04682009-06-10 05:40:52 +0800909 /* BTS has rejected channel activation ?!? */
910 if (dh->ie_chan != RSL_IE_CHAN_NR)
911 return -EINVAL;
912
913 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100914 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200915 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100916 print_rsl_cause(LOGL_ERROR, cause,
Harald Weltef1a168d2009-07-28 17:58:09 +0200917 TLVP_LEN(&tp, RSL_IE_CAUSE));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100918 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200919 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Daniel Willmann245ee032011-08-11 04:47:11 +0200920 else
921 rsl_rf_chan_release(msg->lchan, 1);
922
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100923 } else
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200924 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200925
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100926 LOGPC(DRSL, LOGL_ERROR, "\n");
927
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100928 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100929
Harald Weltecddb9802009-08-09 19:50:08 +0200930 lchan_free(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800931 return 0;
932}
933
934/* Chapter 8.4.4: Connection Failure Indication */
935static int rsl_rx_conn_fail(struct msgb *msg)
936{
937 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
938 struct tlv_parsed tp;
939
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100940 /* FIXME: print which channel */
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100941 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100942 gsm_lchan_name(msg->lchan));
Harald Welte59b04682009-06-10 05:40:52 +0800943
944 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
945
Harald Weltef1a168d2009-07-28 17:58:09 +0200946 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +0100947 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +0200948 TLVP_LEN(&tp, RSL_IE_CAUSE));
949
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100950 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte59b04682009-06-10 05:40:52 +0800951 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200952 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800953 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800954}
955
Harald Weltec20bd1d2009-11-29 19:07:28 +0100956static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
957 const char *prefix)
958{
Harald Welte0e4fa782009-12-16 16:52:07 +0100959 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
960 prefix, rxlev2dbm(mru->full.rx_lev),
961 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Weltec20bd1d2009-11-29 19:07:28 +0100962 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
963 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
964}
965
Harald Welte50290cc2012-07-02 17:12:08 +0200966static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Weltec20bd1d2009-11-29 19:07:28 +0100967{
Harald Welte0e4fa782009-12-16 16:52:07 +0100968 int i;
Harald Welte50290cc2012-07-02 17:12:08 +0200969 char *name = "";
Harald Welte0e4fa782009-12-16 16:52:07 +0100970
Harald Welte50290cc2012-07-02 17:12:08 +0200971 if (lchan && lchan->conn && lchan->conn->subscr)
972 name = subscr_name(lchan->conn->subscr);
973
974 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100975
976 if (mr->flags & MEAS_REP_F_DL_DTX)
977 DEBUGPC(DMEAS, "DTXd ");
978
979 print_meas_rep_uni(&mr->ul, "ul");
980 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
981 if (mr->flags & MEAS_REP_F_MS_TO)
982 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
983
984 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte0e4fa782009-12-16 16:52:07 +0100985 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100986 DEBUGPC(DMEAS, "L1_FPC=%u ",
987 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
988 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
989 }
990
991 if (mr->flags & MEAS_REP_F_UL_DTX)
992 DEBUGPC(DMEAS, "DTXu ");
993 if (mr->flags & MEAS_REP_F_BA1)
994 DEBUGPC(DMEAS, "BA1 ");
995 if (!(mr->flags & MEAS_REP_F_DL_VALID))
996 DEBUGPC(DMEAS, "NOT VALID ");
997 else
998 print_meas_rep_uni(&mr->dl, "dl");
999
1000 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte0b833f82009-12-19 18:33:05 +01001001 if (mr->num_cell == 7)
1002 return;
Harald Welte0e4fa782009-12-16 16:52:07 +01001003 for (i = 0; i < mr->num_cell; i++) {
1004 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte350c2d32009-12-25 23:02:22 +01001005 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1006 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte0e4fa782009-12-16 16:52:07 +01001007 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001008}
1009
Harald Welte59b04682009-06-10 05:40:52 +08001010static int rsl_rx_meas_res(struct msgb *msg)
1011{
1012 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1013 struct tlv_parsed tp;
Harald Weltef9476812009-12-15 21:36:05 +01001014 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001015 uint8_t len;
1016 const uint8_t *val;
Harald Weltec20bd1d2009-11-29 19:07:28 +01001017 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001018
Harald Welte4baa9c52009-12-21 13:27:11 +01001019 /* check if this channel is actually active */
1020 /* FIXME: maybe this check should be way more generic/centralized */
Harald Weltec88a4432009-12-29 10:44:17 +01001021 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freyther67a2e292010-07-29 14:50:57 +08001022 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Weltec88a4432009-12-29 10:44:17 +01001023 gsm_lchan_name(msg->lchan));
Harald Welte4baa9c52009-12-21 13:27:11 +01001024 return 0;
Harald Weltec88a4432009-12-29 10:44:17 +01001025 }
Harald Welte4baa9c52009-12-21 13:27:11 +01001026
Harald Weltef9476812009-12-15 21:36:05 +01001027 memset(mr, 0, sizeof(*mr));
Harald Welteaa0efa12009-12-16 23:29:34 +01001028 mr->lchan = msg->lchan;
Harald Welte4efcc542009-11-30 19:16:47 +01001029
Harald Welte59b04682009-06-10 05:40:52 +08001030 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1031
Harald Weltec20bd1d2009-11-29 19:07:28 +01001032 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1033 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1034 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1035 return -EIO;
1036
1037 /* Mandatory Parts */
Harald Weltef9476812009-12-15 21:36:05 +01001038 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001039
1040 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1041 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1042 if (len >= 3) {
1043 if (val[0] & 0x40)
Harald Weltef9476812009-12-15 21:36:05 +01001044 mr->flags |= MEAS_REP_F_DL_DTX;
1045 mr->ul.full.rx_lev = val[0] & 0x3f;
1046 mr->ul.sub.rx_lev = val[1] & 0x3f;
1047 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1048 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte59b04682009-06-10 05:40:52 +08001049 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001050
Harald Weltef9476812009-12-15 21:36:05 +01001051 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001052
1053 /* Optional Parts */
Harald Welte59b04682009-06-10 05:40:52 +08001054 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Weltef9476812009-12-15 21:36:05 +01001055 mr->ms_timing_offset =
Harald Weltec20bd1d2009-11-29 19:07:28 +01001056 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1057
Harald Weltea1467eb2009-06-20 18:44:35 +02001058 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001059 struct e1inp_sign_link *sign_link = msg->dst;
1060
Harald Weltec20bd1d2009-11-29 19:07:28 +01001061 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001062 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001063 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001064 if (val[0] & 0x04)
Harald Weltef9476812009-12-15 21:36:05 +01001065 mr->flags |= MEAS_REP_F_FPC;
1066 mr->ms_l1.ta = val[1];
Andreas Eversbergfe56cf82011-12-24 11:49:05 +01001067 /* BS11 and Nokia reports TA shifted by 2 bits */
1068 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1069 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001070 mr->ms_l1.ta >>= 2;
Harald Weltea1467eb2009-06-20 18:44:35 +02001071 }
Harald Welte59b04682009-06-10 05:40:52 +08001072 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001073 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001074 rc = gsm48_parse_meas_rep(mr, msg);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001075 if (rc < 0)
1076 return rc;
1077 }
1078
Harald Welte50290cc2012-07-02 17:12:08 +02001079 print_meas_rep(msg->lchan, mr);
Harald Welte59b04682009-06-10 05:40:52 +08001080
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001081 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Welte4efcc542009-11-30 19:16:47 +01001082
Harald Welte59b04682009-06-10 05:40:52 +08001083 return 0;
1084}
1085
Harald Welte6720a432009-11-29 22:45:52 +01001086/* Chapter 8.4.7 */
1087static int rsl_rx_hando_det(struct msgb *msg)
1088{
1089 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1090 struct tlv_parsed tp;
1091
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001092 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welte6720a432009-11-29 22:45:52 +01001093
1094 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1095
1096 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1097 DEBUGPC(DRSL, "access delay = %u\n",
1098 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1099 else
1100 DEBUGPC(DRSL, "\n");
1101
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001102 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +01001103
1104 return 0;
1105}
1106
Harald Welte59b04682009-06-10 05:40:52 +08001107static int abis_rsl_rx_dchan(struct msgb *msg)
1108{
1109 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1110 int rc = 0;
1111 char *ts_name;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001112 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001113
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001114 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001115 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001116
Harald Welte59b04682009-06-10 05:40:52 +08001117 switch (rslh->c.msg_type) {
1118 case RSL_MT_CHAN_ACTIV_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001119 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001120 rc = rsl_rx_chan_act_ack(msg);
1121 break;
1122 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001123 rc = rsl_rx_chan_act_nack(msg);
1124 break;
1125 case RSL_MT_CONN_FAIL:
1126 rc = rsl_rx_conn_fail(msg);
1127 break;
1128 case RSL_MT_MEAS_RES:
1129 rc = rsl_rx_meas_res(msg);
1130 break;
Harald Welte6720a432009-11-29 22:45:52 +01001131 case RSL_MT_HANDO_DET:
1132 rc = rsl_rx_hando_det(msg);
1133 break;
Harald Welte59b04682009-06-10 05:40:52 +08001134 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte9773f6c2011-01-14 14:16:16 +01001135 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001136 break;
1137 case RSL_MT_MODE_MODIFY_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001138 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001139 break;
1140 case RSL_MT_MODE_MODIFY_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001141 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001142 break;
Harald Welteaed946e2009-10-24 10:29:22 +02001143 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001144 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001145 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001146 break;
1147 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001148 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001149 break;
1150 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001151 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001152 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001153 break;
1154 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001155 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001156 break;
Harald Welte59b04682009-06-10 05:40:52 +08001157 case RSL_MT_PHY_CONTEXT_CONF:
1158 case RSL_MT_PREPROC_MEAS_RES:
1159 case RSL_MT_TALKER_DET:
1160 case RSL_MT_LISTENER_DET:
1161 case RSL_MT_REMOTE_CODEC_CONF_REP:
1162 case RSL_MT_MR_CODEC_MOD_ACK:
1163 case RSL_MT_MR_CODEC_MOD_NACK:
1164 case RSL_MT_MR_CODEC_MOD_PER:
Harald Weltede4477a2009-12-24 12:20:20 +01001165 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1166 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001167 break;
1168 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001169 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1170 ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001171 return -EINVAL;
1172 }
1173
1174 return rc;
1175}
1176
1177static int rsl_rx_error_rep(struct msgb *msg)
1178{
1179 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Weltef1a168d2009-07-28 17:58:09 +02001180 struct tlv_parsed tp;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001181 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001182
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001183 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Weltef1a168d2009-07-28 17:58:09 +02001184
1185 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1186
1187 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001188 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001189 TLVP_LEN(&tp, RSL_IE_CAUSE));
1190
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001191 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001192
1193 return 0;
1194}
1195
1196static int abis_rsl_rx_trx(struct msgb *msg)
1197{
1198 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001199 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001200 int rc = 0;
1201
1202 switch (rslh->msg_type) {
1203 case RSL_MT_ERROR_REPORT:
1204 rc = rsl_rx_error_rep(msg);
1205 break;
1206 case RSL_MT_RF_RES_IND:
1207 /* interference on idle channels of TRX */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001208 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001209 break;
1210 case RSL_MT_OVERLOAD:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001211 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001212 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001213 gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001214 break;
Dieter Spaar49c843e2011-07-28 00:01:50 +02001215 case 0x42: /* Nokia specific: SI End ACK */
1216 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1217 break;
1218 case 0x43: /* Nokia specific: SI End NACK */
1219 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1220 break;
Harald Welte59b04682009-06-10 05:40:52 +08001221 default:
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001222 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001223 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001224 return -EINVAL;
1225 }
1226 return rc;
1227}
1228
Harald Welte427dbc42009-08-10 00:26:10 +02001229/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1230static void t3101_expired(void *data)
1231{
1232 struct gsm_lchan *lchan = data;
1233
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001234 rsl_rf_chan_release(lchan, 1);
Harald Welte427dbc42009-08-10 00:26:10 +02001235}
1236
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001237/* If T3111 expires, we will send the RF Channel Request */
1238static void t3111_expired(void *data)
1239{
1240 struct gsm_lchan *lchan = data;
1241
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001242 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001243}
1244
laforge50312e82010-06-21 12:08:52 +02001245#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1246
Harald Weltea00fdd72010-12-23 14:39:29 +01001247/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1248static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1249 unsigned int num_req_refs,
1250 struct gsm48_req_ref *rqd_refs,
1251 uint8_t wait_ind)
1252{
1253 uint8_t buf[GSM_MACBLOCK_LEN];
1254 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1255
1256 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1257 memset(iar, 0, sizeof(*iar));
1258 iar->proto_discr = GSM48_PDISC_RR;
1259 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1260 iar->page_mode = GSM48_PM_SAME;
1261
1262 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1263 iar->wait_ind1 = wait_ind;
1264
1265 if (num_req_refs >= 2)
1266 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1267 else
1268 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1269 iar->wait_ind2 = wait_ind;
1270
1271 if (num_req_refs >= 3)
1272 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1273 else
1274 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1275 iar->wait_ind3 = wait_ind;
1276
1277 if (num_req_refs >= 4)
1278 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1279 else
1280 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1281 iar->wait_ind4 = wait_ind;
1282
1283 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1284}
1285
Harald Welte59b04682009-06-10 05:40:52 +08001286/* MS has requested a channel on the RACH */
1287static int rsl_rx_chan_rqd(struct msgb *msg)
1288{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001289 struct e1inp_sign_link *sign_link = msg->dst;
1290 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001291 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1292 struct gsm48_req_ref *rqd_ref;
Harald Welte59b04682009-06-10 05:40:52 +08001293 enum gsm_chan_t lctype;
1294 enum gsm_chreq_reason_t chreq_reason;
1295 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001296 uint8_t rqd_ta;
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001297 int is_lu;
Harald Welte59b04682009-06-10 05:40:52 +08001298
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001299 uint16_t arfcn;
Holger Hans Peter Freytherefd75b52012-02-03 20:10:13 +01001300 uint8_t subch;
Harald Welte59b04682009-06-10 05:40:52 +08001301
1302 /* parse request reference to be used in immediate assign */
1303 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1304 return -EINVAL;
1305
1306 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1307
1308 /* parse access delay and use as TA */
1309 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1310 return -EINVAL;
1311 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1312
1313 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1314 * request reference RA */
Holger Hans Peter Freytherf0f37f12010-09-06 09:36:02 +08001315 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1316 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte59b04682009-06-10 05:40:52 +08001317
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001318 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte3edc5a92009-12-22 00:41:05 +01001319
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001320 /*
1321 * We want LOCATION UPDATES to succeed and will assign a TCH
1322 * if we have no SDCCH available.
1323 */
1324 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1325
Harald Welte59b04682009-06-10 05:40:52 +08001326 /* check availability / allocate channel */
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001327 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte59b04682009-06-10 05:40:52 +08001328 if (!lchan) {
Harald Welte (local)e0bb5fa2009-12-27 13:48:09 +01001329 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)02204d02009-12-27 18:05:25 +01001330 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001331 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Weltea00fdd72010-12-23 14:39:29 +01001332 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1333 if (bts->network->T3122)
1334 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte59b04682009-06-10 05:40:52 +08001335 return -ENOMEM;
1336 }
1337
Harald Weltec88a4432009-12-29 10:44:17 +01001338 if (lchan->state != LCHAN_S_NONE)
1339 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welteab2534c2009-12-29 10:52:38 +01001340 "in state %s\n", gsm_lchan_name(lchan),
1341 gsm_lchans_name(lchan->state));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +01001342
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001343 /* save the RACH data as we need it after the CHAN ACT ACK */
1344 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1345 if (!lchan->rqd_ref) {
1346 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1347 lchan_free(lchan);
1348 return -ENOMEM;
1349 }
1350
Holger Hans Peter Freyther161cec12011-12-29 23:33:04 +01001351 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001352 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1353 lchan->rqd_ta = rqd_ta;
1354
Harald Welte59b04682009-06-10 05:40:52 +08001355 arfcn = lchan->ts->trx->arfcn;
1356 subch = lchan->nr;
1357
Harald Welted2dd9de2009-08-30 15:37:11 +09001358 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)cbd46102009-08-13 10:14:26 +02001359 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte9a229e12009-08-10 00:45:40 +02001360 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte39274f42009-07-29 15:41:29 +02001361 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte77234e12009-08-28 23:28:28 +09001362 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001363
Harald Welte32951ea2011-08-10 23:26:33 +02001364 /* Start another timer or assume the BTS sends a ACK/NACK? */
1365 lchan->act_timer.cb = lchan_act_tmr_cb;
1366 lchan->act_timer.data = lchan;
1367 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1368
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001369 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1370 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1371 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1372 rqd_ref->ra, rqd_ta);
1373
1374 /* BS11 requires TA shifted by 2 bits */
1375 if (bts->type == GSM_BTS_TYPE_BS11)
1376 rqd_ta <<= 2;
Harald Welteb90d7bd2009-12-17 00:31:10 +01001377 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001378
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001379 return 0;
1380}
1381
1382static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1383{
1384 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001385 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001386 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1387
Harald Welte59b04682009-06-10 05:40:52 +08001388 /* create IMMEDIATE ASSIGN 04.08 messge */
laforgee06d5982010-06-20 15:18:46 +02001389 memset(ia, 0, sizeof(*ia));
laforge50312e82010-06-21 12:08:52 +02001390 /* we set ia->l2_plen once we know the length of the MA below */
laforgee06d5982010-06-20 15:18:46 +02001391 ia->proto_discr = GSM48_PDISC_RR;
1392 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1393 ia->page_mode = GSM48_PM_SAME;
1394 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea42a93f2010-06-14 22:26:10 +02001395
Harald Welte59b04682009-06-10 05:40:52 +08001396 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001397 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1398 ia->timing_advance = lchan->rqd_ta;
Harald Weltea42a93f2010-06-14 22:26:10 +02001399 if (!lchan->ts->hopping.enabled) {
laforgee06d5982010-06-20 15:18:46 +02001400 ia->mob_alloc_len = 0;
Harald Weltea42a93f2010-06-14 22:26:10 +02001401 } else {
laforgee06d5982010-06-20 15:18:46 +02001402 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1403 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea42a93f2010-06-14 22:26:10 +02001404 }
Harald Welte07f32182010-06-28 18:41:27 +02001405 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1406 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte59b04682009-06-10 05:40:52 +08001407
Harald Welte427dbc42009-08-10 00:26:10 +02001408 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1409 lchan->T3101.cb = t3101_expired;
1410 lchan->T3101.data = lchan;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001411 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001412
1413 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001414 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte59b04682009-06-10 05:40:52 +08001415}
1416
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001417/* current load on the CCCH */
Harald Welte59b04682009-06-10 05:40:52 +08001418static int rsl_rx_ccch_load(struct msgb *msg)
1419{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001420 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001421 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001422 struct ccch_signal_data sd;
1423
1424 sd.bts = sign_link->trx->bts;
1425 sd.rach_slot_count = -1;
1426 sd.rach_busy_count = -1;
1427 sd.rach_access_count = -1;
Harald Welte59b04682009-06-10 05:40:52 +08001428
1429 switch (rslh->data[0]) {
1430 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001431 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1432 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte008a4922010-04-19 10:24:07 +02001433 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001434 sd.pg_buf_space = 50;
Harald Welte008a4922010-04-19 10:24:07 +02001435 }
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001436 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1437 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001438 break;
1439 case RSL_IE_RACH_LOAD:
1440 if (msg->data_len >= 7) {
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001441 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1442 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1443 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1444 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001445 }
1446 break;
1447 default:
1448 break;
1449 }
1450
1451 return 0;
1452}
1453
1454static int abis_rsl_rx_cchan(struct msgb *msg)
1455{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001456 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001457 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1458 int rc = 0;
1459
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001460 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +08001461
1462 switch (rslh->c.msg_type) {
1463 case RSL_MT_CHAN_RQD:
1464 /* MS has requested a channel on the RACH */
1465 rc = rsl_rx_chan_rqd(msg);
1466 break;
1467 case RSL_MT_CCCH_LOAD_IND:
1468 /* current load on the CCCH */
1469 rc = rsl_rx_ccch_load(msg);
1470 break;
1471 case RSL_MT_DELETE_IND:
1472 /* CCCH overloaded, IMM_ASSIGN was dropped */
1473 case RSL_MT_CBCH_LOAD_IND:
1474 /* current load on the CBCH */
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001475 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1476 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001477 break;
1478 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001479 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1480 "0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001481 return -EINVAL;
1482 }
1483
1484 return rc;
1485}
1486
1487static int rsl_rx_rll_err_ind(struct msgb *msg)
1488{
1489 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001490 uint8_t *rlm_cause = rllh->data;
Harald Welte59b04682009-06-10 05:40:52 +08001491
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001492 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001493 gsm_lchan_name(msg->lchan),
Harald Welteb30935e2010-03-25 12:13:02 +08001494 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteed9a5ab2009-08-09 13:47:35 +02001495
1496 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001497
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001498 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001499 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001500 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001501 }
Harald Welte692f5852009-07-04 09:40:05 +02001502
Harald Welte59b04682009-06-10 05:40:52 +08001503 return 0;
1504}
1505
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001506static void rsl_handle_release(struct gsm_lchan *lchan)
1507{
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001508 int sapi;
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001509 struct gsm_bts *bts;
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001510
1511 /* maybe we have only brought down one RLL */
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001512 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001513 return;
1514
1515 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1516 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1517 continue;
Harald Welte497aa982010-12-24 12:51:07 +01001518 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001519 gsm_lchan_name(lchan), sapi);
1520 return;
1521 }
1522
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001523
1524
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001525 /* wait a bit to send the RF Channel Release */
1526 lchan->T3111.cb = t3111_expired;
1527 lchan->T3111.data = lchan;
1528 bts = lchan->ts->trx->bts;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001529 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001530}
1531
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001532/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte59b04682009-06-10 05:40:52 +08001533 0x02, 0x06,
1534 0x01, 0x20,
1535 0x02, 0x00,
1536 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1537
1538static int abis_rsl_rx_rll(struct msgb *msg)
1539{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001540 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001541 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1542 int rc = 0;
1543 char *ts_name;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001544 uint8_t sapi = rllh->link_id & 7;
Harald Welte59b04682009-06-10 05:40:52 +08001545
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001546 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001547 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltede4477a2009-12-24 12:20:20 +01001548 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte59b04682009-06-10 05:40:52 +08001549
1550 switch (rllh->c.msg_type) {
1551 case RSL_MT_DATA_IND:
1552 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001553 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001554 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1555 rllh->data[0] == RSL_IE_L3_INFO) {
1556 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001557 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001558 }
1559 break;
1560 case RSL_MT_EST_IND:
1561 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte427dbc42009-08-10 00:26:10 +02001562 /* lchan is established, stop T3101 */
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001563 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001564 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001565 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001566 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1567 rllh->data[0] == RSL_IE_L3_INFO) {
1568 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001569 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001570 }
1571 break;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001572 case RSL_MT_EST_CONF:
Harald Welte61402172009-08-09 14:13:58 +02001573 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001574 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001575 rll_indication(msg->lchan, rllh->link_id,
1576 BSC_RLLR_IND_EST_CONF);
1577 break;
Harald Welte59b04682009-06-10 05:40:52 +08001578 case RSL_MT_REL_IND:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001579 /* BTS informs us of having received DISC from MS */
Harald Welteb6601442009-08-04 02:50:21 +02001580 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001581 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001582 rll_indication(msg->lchan, rllh->link_id,
1583 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001584 rsl_handle_release(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001585 break;
1586 case RSL_MT_REL_CONF:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001587 /* BTS informs us of having received UA from MS,
1588 * in response to DISC that we've sent earlier */
Harald Welteb6601442009-08-04 02:50:21 +02001589 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001590 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001591 rsl_handle_release(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001592 break;
1593 case RSL_MT_ERROR_IND:
Harald Welte59b04682009-06-10 05:40:52 +08001594 rc = rsl_rx_rll_err_ind(msg);
1595 break;
1596 case RSL_MT_UNIT_DATA_IND:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001597 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1598 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001599 break;
1600 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001601 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1602 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001603 }
Harald Welte59b04682009-06-10 05:40:52 +08001604 return rc;
1605}
1606
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001607static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Welte98d79f92009-07-28 18:11:56 +02001608{
Harald Welteb284b472009-12-02 01:58:23 +05301609 switch (lchan->tch_mode) {
Harald Welte98d79f92009-07-28 18:11:56 +02001610 case GSM48_CMODE_SPEECH_V1:
Harald Welteb284b472009-12-02 01:58:23 +05301611 switch (lchan->type) {
1612 case GSM_LCHAN_TCH_F:
1613 return 0x00;
1614 case GSM_LCHAN_TCH_H:
1615 return 0x03;
1616 default:
1617 break;
1618 }
Harald Welte98d79f92009-07-28 18:11:56 +02001619 case GSM48_CMODE_SPEECH_EFR:
Harald Welteb284b472009-12-02 01:58:23 +05301620 switch (lchan->type) {
1621 case GSM_LCHAN_TCH_F:
1622 return 0x01;
1623 /* there's no half-rate EFR */
1624 default:
1625 break;
1626 }
Harald Welte98d79f92009-07-28 18:11:56 +02001627 case GSM48_CMODE_SPEECH_AMR:
Harald Welteb284b472009-12-02 01:58:23 +05301628 switch (lchan->type) {
1629 case GSM_LCHAN_TCH_F:
1630 return 0x02;
1631 case GSM_LCHAN_TCH_H:
1632 return 0x05;
1633 default:
1634 break;
1635 }
1636 default:
1637 break;
Harald Welte98d79f92009-07-28 18:11:56 +02001638 }
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001639 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welteb284b472009-12-02 01:58:23 +05301640 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001641 return 0;
Harald Welte98d79f92009-07-28 18:11:56 +02001642}
1643
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001644static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munaut1338a552009-12-20 22:06:40 +01001645{
1646 switch (lchan->tch_mode) {
1647 case GSM48_CMODE_SPEECH_V1:
1648 switch (lchan->type) {
1649 case GSM_LCHAN_TCH_F:
1650 return RTP_PT_GSM_FULL;
1651 case GSM_LCHAN_TCH_H:
1652 return RTP_PT_GSM_HALF;
1653 default:
1654 break;
1655 }
1656 case GSM48_CMODE_SPEECH_EFR:
1657 switch (lchan->type) {
1658 case GSM_LCHAN_TCH_F:
1659 return RTP_PT_GSM_EFR;
1660 /* there's no half-rate EFR */
1661 default:
1662 break;
1663 }
1664 case GSM48_CMODE_SPEECH_AMR:
1665 switch (lchan->type) {
1666 case GSM_LCHAN_TCH_F:
Sylvain Munaut1338a552009-12-20 22:06:40 +01001667 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freytherd78bee82011-07-21 10:24:46 +02001668 return RTP_PT_AMR;
Sylvain Munaut1338a552009-12-20 22:06:40 +01001669 default:
1670 break;
1671 }
1672 default:
1673 break;
1674 }
1675 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1676 "tch_mode == 0x%02x\n & lchan_type == %d",
1677 lchan->tch_mode, lchan->type);
1678 return 0;
1679}
1680
Harald Welte59b04682009-06-10 05:40:52 +08001681/* ip.access specific RSL extensions */
Harald Weltebffa4992009-12-19 16:42:06 +01001682static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1683{
1684 struct in_addr ip;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001685 uint16_t port, conn_id;
Harald Weltebffa4992009-12-19 16:42:06 +01001686
1687 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001688 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001689 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1690 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1691 }
1692
1693 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001694 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001695 port = ntohs(port);
1696 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1697 lchan->abis_ip.bound_port = port;
1698 }
1699
1700 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001701 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Weltebffa4992009-12-19 16:42:06 +01001702 conn_id = ntohs(conn_id);
1703 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1704 lchan->abis_ip.conn_id = conn_id;
1705 }
1706
1707 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1708 lchan->abis_ip.rtp_payload2 =
1709 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1710 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1711 lchan->abis_ip.rtp_payload2);
1712 }
1713
1714 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1715 lchan->abis_ip.speech_mode =
1716 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1717 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1718 lchan->abis_ip.speech_mode);
1719 }
1720
1721 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001722 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001723 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1724 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1725 }
1726
1727 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001728 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001729 port = ntohs(port);
1730 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1731 lchan->abis_ip.connect_port = port;
1732 }
1733}
1734
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001735int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte59b04682009-06-10 05:40:52 +08001736{
1737 struct msgb *msg = rsl_msgb_alloc();
1738 struct abis_rsl_dchan_hdr *dh;
1739
1740 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001741 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte59b04682009-06-10 05:40:52 +08001742 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001743 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001744
Harald Welte98d79f92009-07-28 18:11:56 +02001745 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001746 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001747 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001748 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001749 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001750
Sylvain Munaut1338a552009-12-20 22:06:40 +01001751 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1752 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1753 lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001754
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001755 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001756
1757 return abis_rsl_sendmsg(msg);
1758}
1759
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001760int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1761 uint8_t rtp_payload2)
Harald Welte59b04682009-06-10 05:40:52 +08001762{
1763 struct msgb *msg = rsl_msgb_alloc();
1764 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001765 uint32_t *att_ip;
Harald Welte98d79f92009-07-28 18:11:56 +02001766 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +08001767
1768 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001769 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte59b04682009-06-10 05:40:52 +08001770 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001771 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001772
Harald Weltebffa4992009-12-19 16:42:06 +01001773 /* we need to store these now as MDCX_ACK does not return them :( */
1774 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1775 lchan->abis_ip.connect_port = port;
1776 lchan->abis_ip.connect_ip = ip;
1777
Harald Weltefb4a9e92009-07-29 12:12:18 +02001778 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001779 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001780 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltefb4a9e92009-07-29 12:12:18 +02001781
Harald Welte98d79f92009-07-28 18:11:56 +02001782 ia.s_addr = htonl(ip);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001783 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1784 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1785 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1786 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001787
Harald Weltebffa4992009-12-19 16:42:06 +01001788 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1789 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001790 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Weltebffa4992009-12-19 16:42:06 +01001791 *att_ip = ia.s_addr;
1792 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1793 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001794 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001795 if (rtp_payload2)
1796 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001797
1798 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001799
1800 return abis_rsl_sendmsg(msg);
1801}
1802
Harald Welte9947d9f2009-12-20 16:51:09 +01001803/* tell BTS to connect RTP stream to our local RTP socket */
1804int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1805{
1806 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1807 int rc;
1808
1809 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1810 ntohs(rs->rtp.sin_local.sin_port),
1811 /* FIXME: use RTP payload of bound socket, not BTS*/
1812 lchan->abis_ip.rtp_payload2);
1813
1814 return rc;
1815}
1816
Harald Welte6f40df02010-12-23 12:59:52 +01001817int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welteaed946e2009-10-24 10:29:22 +02001818{
1819 struct msgb *msg = rsl_msgb_alloc();
1820 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001821 uint8_t msg_type;
Harald Welte2b361522010-03-28 14:42:09 +08001822
1823 if (act)
1824 msg_type = RSL_MT_IPAC_PDCH_ACT;
1825 else
1826 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welteaed946e2009-10-24 10:29:22 +02001827
1828 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte2b361522010-03-28 14:42:09 +08001829 init_dchan_hdr(dh, msg_type);
Harald Welteaed946e2009-10-24 10:29:22 +02001830 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +02001831 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welteaed946e2009-10-24 10:29:22 +02001832
Harald Welte6f40df02010-12-23 12:59:52 +01001833 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte2b361522010-03-28 14:42:09 +08001834 act ? "" : "DE");
Harald Welteaed946e2009-10-24 10:29:22 +02001835
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001836 msg->dst = ts->trx->rsl_link;
Harald Welteaed946e2009-10-24 10:29:22 +02001837
1838 return abis_rsl_sendmsg(msg);
1839}
1840
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001841static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001842{
1843 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1844 struct tlv_parsed tv;
Harald Welte87504212009-12-02 01:56:49 +05301845 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001846
1847 /* the BTS has acknowledged a local bind, it now tells us the IP
1848 * address and port number to which it has bound the given logical
1849 * channel */
1850
1851 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1852 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1853 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welteb9498952009-07-12 09:45:05 +02001854 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001855 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte59b04682009-06-10 05:40:52 +08001856 return -EINVAL;
1857 }
Harald Welte50517742009-12-20 15:42:44 +01001858
Harald Weltebffa4992009-12-19 16:42:06 +01001859 ipac_parse_rtp(lchan, &tv);
Harald Welte50517742009-12-20 15:42:44 +01001860
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001861 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001862
1863 return 0;
1864}
1865
Harald Weltebffa4992009-12-19 16:42:06 +01001866static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1867{
1868 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1869 struct tlv_parsed tv;
1870 struct gsm_lchan *lchan = msg->lchan;
1871
1872 /* the BTS has acknowledged a remote connect request and
1873 * it now tells us the IP address and port number to which it has
1874 * connected the given logical channel */
1875
1876 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1877 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001878 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001879
1880 return 0;
1881}
1882
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001883static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001884{
1885 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1886 struct tlv_parsed tv;
1887
1888 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte59b04682009-06-10 05:40:52 +08001889
Harald Weltef1a168d2009-07-28 17:58:09 +02001890 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001891 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001892 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte59b04682009-06-10 05:40:52 +08001893
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001894 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welteba4e58d2009-07-28 18:02:05 +02001895
Harald Welte59b04682009-06-10 05:40:52 +08001896 return 0;
1897}
1898
1899static int abis_rsl_rx_ipacc(struct msgb *msg)
1900{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001901 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001902 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltede4477a2009-12-24 12:20:20 +01001903 char *ts_name;
Harald Welte59b04682009-06-10 05:40:52 +08001904 int rc = 0;
1905
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001906 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001907 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001908
1909 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001910 case RSL_MT_IPAC_CRCX_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001911 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001912 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001913 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001914 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001915 /* somehow the BTS was unable to bind the lchan to its local
1916 * port?!? */
Harald Weltede4477a2009-12-24 12:20:20 +01001917 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001918 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001919 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte59b04682009-06-10 05:40:52 +08001920 /* the BTS tells us that a connect operation was successful */
Harald Weltede4477a2009-12-24 12:20:20 +01001921 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Weltebffa4992009-12-19 16:42:06 +01001922 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001923 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001924 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001925 /* somehow the BTS was unable to connect the lchan to a remote
1926 * port */
Harald Weltede4477a2009-12-24 12:20:20 +01001927 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001928 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001929 case RSL_MT_IPAC_DLCX_IND:
Harald Weltede4477a2009-12-24 12:20:20 +01001930 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001931 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001932 break;
1933 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001934 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001935 rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001936 break;
1937 }
1938 DEBUGPC(DRSL, "\n");
1939
1940 return rc;
1941}
1942
1943
1944/* Entry-point where L2 RSL from BTS enters */
1945int abis_rsl_rcvmsg(struct msgb *msg)
1946{
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001947 struct abis_rsl_common_hdr *rslh;
Harald Welte59b04682009-06-10 05:40:52 +08001948 int rc = 0;
1949
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001950 if (!msg) {
1951 DEBUGP(DRSL, "Empty RSL msg?..\n");
1952 return -1;
1953 }
1954
1955 if (msgb_l2len(msg) < sizeof(*rslh)) {
1956 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltece807262012-05-31 20:22:34 +02001957 msgb_free(msg);
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001958 return -1;
1959 }
1960
1961 rslh = msgb_l2(msg);
1962
Harald Welte59b04682009-06-10 05:40:52 +08001963 switch (rslh->msg_discr & 0xfe) {
1964 case ABIS_RSL_MDISC_RLL:
1965 rc = abis_rsl_rx_rll(msg);
1966 break;
1967 case ABIS_RSL_MDISC_DED_CHAN:
1968 rc = abis_rsl_rx_dchan(msg);
1969 break;
1970 case ABIS_RSL_MDISC_COM_CHAN:
1971 rc = abis_rsl_rx_cchan(msg);
1972 break;
1973 case ABIS_RSL_MDISC_TRX:
1974 rc = abis_rsl_rx_trx(msg);
1975 break;
1976 case ABIS_RSL_MDISC_LOC:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001977 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte59b04682009-06-10 05:40:52 +08001978 rslh->msg_discr);
1979 break;
1980 case ABIS_RSL_MDISC_IPACCESS:
1981 rc = abis_rsl_rx_ipacc(msg);
1982 break;
1983 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001984 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
1985 "0x%02x\n", rslh->msg_discr);
Harald Weltece807262012-05-31 20:22:34 +02001986 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08001987 }
1988 msgb_free(msg);
1989 return rc;
1990}
1991
Holger Hans Peter Freytherb67f4082010-07-21 15:54:32 +08001992int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
1993 uint8_t cb_command, const uint8_t *data, int len)
1994{
1995 struct abis_rsl_dchan_hdr *dh;
1996 struct msgb *cb_cmd;
1997
1998 cb_cmd = rsl_msgb_alloc();
1999 if (!cb_cmd)
2000 return -1;
2001
2002 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2003 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2004 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2005
2006 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2007 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2008
2009 cb_cmd->trx = bts->c0;
2010
2011 return abis_rsl_sendmsg(cb_cmd);
2012}
Dieter Spaar49c843e2011-07-28 00:01:50 +02002013
2014int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2015{
2016 struct abis_rsl_common_hdr *ch;
2017 struct msgb *msg = rsl_msgb_alloc();
2018
2019 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2020 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2021 ch->msg_type = 0x40; /* Nokia SI Begin */
2022
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002023 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002024
2025 return abis_rsl_sendmsg(msg);
2026}
2027
2028int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2029{
2030 struct abis_rsl_common_hdr *ch;
2031 struct msgb *msg = rsl_msgb_alloc();
2032
2033 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2034 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2035 ch->msg_type = 0x41; /* Nokia SI End */
2036
2037 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2038
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002039 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002040
2041 return abis_rsl_sendmsg(msg);
2042}
2043
2044int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2045{
2046 struct abis_rsl_common_hdr *ch;
2047 struct msgb *msg = rsl_msgb_alloc();
2048
2049 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2050 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2051 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2052
2053 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2054 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2055
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002056 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002057
2058 return abis_rsl_sendmsg(msg);
2059}
Holger Hans Peter Freythere38af682011-12-27 22:24:17 +01002060
2061/**
2062 * Release all allocated SAPIs starting from @param start and
2063 * release them with the given release mode. Once the release
2064 * confirmation arrives it will be attempted to release the
2065 * the RF channel.
2066 */
2067int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
2068 enum rsl_rel_mode release_mode)
2069{
2070 int no_sapi = 1;
2071 int sapi;
2072
2073 for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
2074 uint8_t link_id;
2075 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
2076 continue;
2077
2078 link_id = sapi;
2079 if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
2080 link_id |= 0x40;
2081 rsl_release_request(lchan, link_id, release_mode);
2082 no_sapi = 0;
2083 }
2084
2085 return no_sapi;
2086}