blob: 42dad7fdec5497f8682fea7af9bc1f070f17106e [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 Freyther969a4052011-12-28 16:21:05 +010049enum sacch_deact {
50 SACCH_NONE,
51 SACCH_DEACTIVATE,
52};
53
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080054static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
55
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010056static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
57 struct gsm_meas_rep *resp)
58{
59 struct lchan_signal_data sig;
60 sig.lchan = lchan;
61 sig.mr = resp;
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +020062 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010063}
64
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +010065static void do_lchan_free(struct gsm_lchan *lchan)
66{
67 /* we have an error timer pending to release that */
68 if (lchan->state != LCHAN_S_REL_ERR)
69 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
70 lchan_free(lchan);
71}
72
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020073static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080074{
75 /* mask off the transparent bit ? */
76 msg_type &= 0xfe;
77
78 if ((msg_type & 0xf0) == 0x00)
79 return ABIS_RSL_MDISC_RLL;
80 if ((msg_type & 0xf0) == 0x10) {
81 if (msg_type >= 0x19 && msg_type <= 0x22)
82 return ABIS_RSL_MDISC_TRX;
83 else
84 return ABIS_RSL_MDISC_COM_CHAN;
85 }
86 if ((msg_type & 0xe0) == 0x20)
87 return ABIS_RSL_MDISC_DED_CHAN;
88
89 return ABIS_RSL_MDISC_LOC;
90}
91
92static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020093 uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080094{
95 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
96 dh->c.msg_type = msg_type;
97 dh->ie_chan = RSL_IE_CHAN_NR;
98}
99
Harald Welte59b04682009-06-10 05:40:52 +0800100/* determine logical channel based on TRX and channel number IE */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200101struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte59b04682009-06-10 05:40:52 +0800102{
103 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200104 uint8_t ts_nr = chan_nr & 0x07;
105 uint8_t cbits = chan_nr >> 3;
106 uint8_t lch_idx;
Harald Welte59b04682009-06-10 05:40:52 +0800107 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
108
109 if (cbits == 0x01) {
110 lch_idx = 0; /* TCH/F */
Harald Welte37884ed2009-10-24 10:25:50 +0200111 if (ts->pchan != GSM_PCHAN_TCH_F &&
112 ts->pchan != GSM_PCHAN_PDCH &&
113 ts->pchan != GSM_PCHAN_TCH_F_PDCH)
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 & 0x1e) == 0x02) {
117 lch_idx = cbits & 0x1; /* TCH/H */
118 if (ts->pchan != GSM_PCHAN_TCH_H)
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 & 0x1c) == 0x04) {
122 lch_idx = cbits & 0x3; /* SDCCH/4 */
123 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
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 & 0x18) == 0x08) {
127 lch_idx = cbits & 0x7; /* SDCCH/8 */
128 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100129 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800130 chan_nr, ts->pchan);
131 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
132 lch_idx = 0;
133 if (ts->pchan != GSM_PCHAN_CCCH &&
134 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100135 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800136 chan_nr, ts->pchan);
137 /* FIXME: we should not return first sdcch4 !!! */
138 } else {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100139 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +0800140 return NULL;
141 }
142
143 lchan = &ts->lchan[lch_idx];
Harald Welte51d2a592010-03-26 21:28:59 +0800144 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther1a95fa82010-06-28 15:47:12 +0800145 if (lchan->conn)
146 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800147
148 return lchan;
149}
150
Harald Welte59b04682009-06-10 05:40:52 +0800151/* 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 +0200152uint64_t str_to_imsi(const char *imsi_str)
Harald Welte59b04682009-06-10 05:40:52 +0800153{
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200154 uint64_t ret;
Harald Welte59b04682009-06-10 05:40:52 +0800155
156 ret = strtoull(imsi_str, NULL, 10);
157
158 return ret;
159}
160
Harald Welte59b04682009-06-10 05:40:52 +0800161static struct msgb *rsl_msgb_alloc(void)
162{
Harald Welte9cfc9352009-06-26 19:39:35 +0200163 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
164 "RSL");
Harald Welte59b04682009-06-10 05:40:52 +0800165}
166
167#define MACBLOCK_SIZE 23
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200168static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800169{
170 memcpy(out, in, len);
171
172 if (len < MACBLOCK_SIZE)
173 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
174}
175
Harald Welted2dd9de2009-08-30 15:37:11 +0900176/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200177static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welted2dd9de2009-08-30 15:37:11 +0900178{
179 *out++ = lchan->encr.alg_id & 0xff;
180 if (lchan->encr.key_len)
181 memcpy(out, lchan->encr.key, lchan->encr.key_len);
182 return lchan->encr.key_len + 1;
183}
184
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200185static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Weltef1a168d2009-07-28 17:58:09 +0200186{
Harald Welte59b04682009-06-10 05:40:52 +0800187 int i;
188
Harald Weltede4477a2009-12-24 12:20:20 +0100189 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Weltef1a168d2009-07-28 17:58:09 +0200190 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200191 for (i = 1; i < cause_len-1; i++)
Harald Weltede4477a2009-12-24 12:20:20 +0100192 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte59b04682009-06-10 05:40:52 +0800193}
194
Harald Welte32951ea2011-08-10 23:26:33 +0200195static void lchan_act_tmr_cb(void *data)
196{
197 struct gsm_lchan *lchan = data;
198
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100199 LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200200 gsm_lchan_name(lchan));
201
Daniel Willmann2731e732011-08-11 04:44:12 +0200202 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
203 lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200204}
205
206static void lchan_deact_tmr_cb(void *data)
207{
208 struct gsm_lchan *lchan = data;
209
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100210 LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200211 gsm_lchan_name(lchan));
212
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100213 do_lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200214}
215
216
Harald Welte59b04682009-06-10 05:40:52 +0800217/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200218int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
219 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800220{
221 struct abis_rsl_dchan_hdr *dh;
222 struct msgb *msg = rsl_msgb_alloc();
223
224 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
225 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
226 dh->chan_nr = RSL_CHAN_BCCH;
227
228 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
229 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
230
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200231 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800232
233 return abis_rsl_sendmsg(msg);
234}
235
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200236int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
237 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800238{
239 struct abis_rsl_common_hdr *ch;
240 struct msgb *msg = rsl_msgb_alloc();
241
242 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
243 ch->msg_discr = ABIS_RSL_MDISC_TRX;
244 ch->msg_type = RSL_MT_SACCH_FILL;
245
246 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
247 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
248
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200249 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800250
251 return abis_rsl_sendmsg(msg);
252}
253
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200254int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
255 const uint8_t *data, int len)
Harald Welte10b7d8f2011-01-13 23:16:03 +0100256{
257 struct abis_rsl_dchan_hdr *dh;
258 struct msgb *msg = rsl_msgb_alloc();
Harald Weltee6d51f92011-06-25 10:02:33 +0200259 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte10b7d8f2011-01-13 23:16:03 +0100260
261 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
262 init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
263 dh->chan_nr = chan_nr;
264
265 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
266 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
267
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200268 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte10b7d8f2011-01-13 23:16:03 +0100269
270 return abis_rsl_sendmsg(msg);
271}
272
Harald Welte91afe4c2009-06-20 18:15:19 +0200273int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
274{
275 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200276 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200277 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200278
279 db = abs(db);
280 if (db > 30)
281 return -EINVAL;
282
Harald Welteed831842009-06-27 03:09:08 +0200283 msg = rsl_msgb_alloc();
284
Harald Welte91afe4c2009-06-20 18:15:19 +0200285 lchan->bs_power = db/2;
286 if (fpc)
287 lchan->bs_power |= 0x10;
288
289 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
290 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
291 dh->chan_nr = chan_nr;
292
293 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
294
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200295 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200296
297 return abis_rsl_sendmsg(msg);
298}
299
Harald Welte91afe4c2009-06-20 18:15:19 +0200300int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
301{
302 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200303 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200304 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200305 int ctl_lvl;
306
Harald Weltec4dcda02009-08-09 14:45:18 +0200307 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Welte91afe4c2009-06-20 18:15:19 +0200308 if (ctl_lvl < 0)
309 return ctl_lvl;
310
Harald Welteed831842009-06-27 03:09:08 +0200311 msg = rsl_msgb_alloc();
312
Harald Welte91afe4c2009-06-20 18:15:19 +0200313 lchan->ms_power = ctl_lvl;
314
315 if (fpc)
316 lchan->ms_power |= 0x20;
317
318 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
319 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
320 dh->chan_nr = chan_nr;
321
322 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
323
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200324 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200325
326 return abis_rsl_sendmsg(msg);
327}
328
Harald Welte39274f42009-07-29 15:41:29 +0200329static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
330 struct gsm_lchan *lchan)
331{
332 memset(cm, 0, sizeof(cm));
333
334 /* FIXME: what to do with data calls ? */
Holger Hans Peter Freyther21d63ff2010-09-06 09:25:48 +0800335 if (lchan->ts->trx->bts->network->dtx_enabled)
336 cm->dtx_dtu = 0x03;
337 else
338 cm->dtx_dtu = 0x00;
Harald Welte39274f42009-07-29 15:41:29 +0200339
340 /* set TCH Speech/Data */
341 cm->spd_ind = lchan->rsl_cmode;
342
Harald Welte951e3512009-11-27 08:55:16 +0100343 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
344 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100345 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte951e3512009-11-27 08:55:16 +0100346 "but tch_mode != signalling\n");
347
Harald Welte39274f42009-07-29 15:41:29 +0200348 switch (lchan->type) {
349 case GSM_LCHAN_SDCCH:
350 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
351 break;
352 case GSM_LCHAN_TCH_F:
353 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
354 break;
355 case GSM_LCHAN_TCH_H:
356 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
357 break;
358 case GSM_LCHAN_NONE:
359 case GSM_LCHAN_UNKNOWN:
360 default:
361 return -EINVAL;
362 }
363
364 switch (lchan->tch_mode) {
365 case GSM48_CMODE_SIGN:
366 cm->chan_rate = 0;
367 break;
368 case GSM48_CMODE_SPEECH_V1:
369 cm->chan_rate = RSL_CMOD_SP_GSM1;
370 break;
371 case GSM48_CMODE_SPEECH_EFR:
372 cm->chan_rate = RSL_CMOD_SP_GSM2;
373 break;
374 case GSM48_CMODE_SPEECH_AMR:
375 cm->chan_rate = RSL_CMOD_SP_GSM3;
376 break;
377 case GSM48_CMODE_DATA_14k5:
Harald Welte39274f42009-07-29 15:41:29 +0200378 case GSM48_CMODE_DATA_12k0:
Harald Welte39274f42009-07-29 15:41:29 +0200379 case GSM48_CMODE_DATA_6k0:
Harald Weltee75a47d2012-08-24 15:33:56 +0200380 switch (lchan->csd_mode) {
381 case LCHAN_CSD_M_NT:
382 /* non-transparent CSD with RLP */
383 switch (lchan->tch_mode) {
384 case GSM48_CMODE_DATA_14k5:
385 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
386 break;
387 case GSM48_CMODE_DATA_12k0:
388 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
389 break;
390 case GSM48_CMODE_DATA_6k0:
391 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
392 break;
393 default:
394 return -EINVAL;
395 }
396 break;
397 /* transparent data services below */
398 case LCHAN_CSD_M_T_1200_75:
399 cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
400 break;
401 case LCHAN_CSD_M_T_600:
402 cm->chan_rate = RSL_CMOD_CSD_T_600;
403 break;
404 case LCHAN_CSD_M_T_1200:
405 cm->chan_rate = RSL_CMOD_CSD_T_1200;
406 break;
407 case LCHAN_CSD_M_T_2400:
408 cm->chan_rate = RSL_CMOD_CSD_T_2400;
409 break;
410 case LCHAN_CSD_M_T_9600:
411 cm->chan_rate = RSL_CMOD_CSD_T_9600;
412 break;
413 case LCHAN_CSD_M_T_14400:
414 cm->chan_rate = RSL_CMOD_CSD_T_14400;
415 break;
416 case LCHAN_CSD_M_T_29000:
417 cm->chan_rate = RSL_CMOD_CSD_T_29000;
418 break;
419 case LCHAN_CSD_M_T_32000:
420 cm->chan_rate = RSL_CMOD_CSD_T_32000;
421 break;
422 default:
423 return -EINVAL;
424 }
Harald Welte39274f42009-07-29 15:41:29 +0200425 default:
426 return -EINVAL;
427 }
428
429 return 0;
430}
431
Harald Welte59b04682009-06-10 05:40:52 +0800432/* Chapter 8.4.1 */
433#if 0
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200434int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
435 uint8_t act_type,
Harald Welte59b04682009-06-10 05:40:52 +0800436 struct rsl_ie_chan_mode *chan_mode,
437 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200438 uint8_t bs_power, uint8_t ms_power,
439 uint8_t ta)
Harald Welte59b04682009-06-10 05:40:52 +0800440{
441 struct abis_rsl_dchan_hdr *dh;
442 struct msgb *msg = rsl_msgb_alloc();
443
444 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
445 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
446 dh->chan_nr = chan_nr;
447
448 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
449 /* For compatibility with Phase 1 */
450 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200451 (uint8_t *) chan_mode);
Harald Welte59b04682009-06-10 05:40:52 +0800452 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200453 (uint8_t *) chan_ident);
Harald Welte59b04682009-06-10 05:40:52 +0800454#if 0
455 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200456 (uint8_t *) &encr_info);
Harald Welte59b04682009-06-10 05:40:52 +0800457#endif
458 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
459 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
460 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
461
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200462 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800463
464 return abis_rsl_sendmsg(msg);
465}
466#endif
467
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200468int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
469 uint8_t ta, uint8_t ho_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800470{
471 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200472 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200473 int rc;
Harald Weltedea24e92010-06-29 17:53:45 +0200474 uint8_t *len;
Harald Welte59b04682009-06-10 05:40:52 +0800475
Harald Weltee6d51f92011-06-25 10:02:33 +0200476 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800477 struct rsl_ie_chan_mode cm;
laforgef723cf02010-06-20 21:38:19 +0200478 struct gsm48_chan_desc cd;
Harald Welte59b04682009-06-10 05:40:52 +0800479
Harald Welte39274f42009-07-29 15:41:29 +0200480 rc = channel_mode_from_lchan(&cm, lchan);
481 if (rc < 0)
482 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800483
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800484 memset(&cd, 0, sizeof(cd));
laforgef723cf02010-06-20 21:38:19 +0200485 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800486
Harald Welteed831842009-06-27 03:09:08 +0200487 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800488 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
489 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
490 dh->chan_nr = chan_nr;
491
492 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte59b04682009-06-10 05:40:52 +0800493 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200494 (uint8_t *) &cm);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800495
496 /*
497 * The Channel Identification is needed for Phase1 phones
498 * and it contains the GSM48 Channel Description and the
499 * Mobile Allocation. The GSM 08.58 asks for the Mobile
500 * Allocation to have a length of zero. We are using the
501 * msgb_l3len to calculate the length of both messages.
502 */
laforgef723cf02010-06-20 21:38:19 +0200503 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Weltedea24e92010-06-29 17:53:45 +0200504 len = msgb_put(msg, 1);
Dieter Spaar18a55f62011-07-27 23:40:33 +0200505 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther4cab4422010-06-30 12:06:20 +0800506
507 if (lchan->ts->hopping.enabled)
508 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
509 lchan->ts->hopping.ma_data);
510 else
511 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800512
513 /* update the calculated size */
514 msg->l3h = len + 1;
515 *len = msgb_l3len(msg);
516
Harald Welted2dd9de2009-08-30 15:37:11 +0900517 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200518 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900519 rc = build_encr_info(encr_info, lchan);
520 if (rc > 0)
521 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
522 }
523
Harald Welteb90d7bd2009-12-17 00:31:10 +0100524 switch (act_type) {
525 case RSL_ACT_INTER_ASYNC:
526 case RSL_ACT_INTER_SYNC:
527 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
528 break;
529 default:
530 break;
531 }
532
Harald Welte59b04682009-06-10 05:40:52 +0800533 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
534 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
535 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
536
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100537 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
538 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200539 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100540
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200541 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800542
543 return abis_rsl_sendmsg(msg);
544}
545
Harald Welte8e770492009-07-29 11:38:15 +0200546/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welte59b04682009-06-10 05:40:52 +0800547int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
548{
549 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200550 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200551 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800552
Harald Weltee6d51f92011-06-25 10:02:33 +0200553 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800554 struct rsl_ie_chan_mode cm;
555
Harald Welte39274f42009-07-29 15:41:29 +0200556 rc = channel_mode_from_lchan(&cm, lchan);
557 if (rc < 0)
558 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800559
Harald Welteed831842009-06-27 03:09:08 +0200560 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800561 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
562 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
563 dh->chan_nr = chan_nr;
564
565 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200566 (uint8_t *) &cm);
Harald Welted2dd9de2009-08-30 15:37:11 +0900567
568 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200569 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900570 rc = build_encr_info(encr_info, lchan);
571 if (rc > 0)
572 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
573 }
574
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100575 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
576 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200577 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100578 }
579
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200580 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dd9de2009-08-30 15:37:11 +0900581
582 return abis_rsl_sendmsg(msg);
583}
584
585/* Chapter 8.4.6: Send the encryption command with given L3 info */
586int rsl_encryption_cmd(struct msgb *msg)
587{
588 struct abis_rsl_dchan_hdr *dh;
589 struct gsm_lchan *lchan = msg->lchan;
Harald Weltee6d51f92011-06-25 10:02:33 +0200590 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200591 uint8_t encr_info[MAX_A5_KEY_LEN+2];
592 uint8_t l3_len = msg->len;
Harald Welted2dd9de2009-08-30 15:37:11 +0900593 int rc;
594
595 /* First push the L3 IE tag and length */
596 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
597
598 /* then the link identifier (SAPI0, main sign link) */
599 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
600
601 /* then encryption information */
602 rc = build_encr_info(encr_info, lchan);
603 if (rc <= 0)
604 return rc;
605 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
606
607 /* and finally the DCHAN header */
608 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
609 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
610 dh->chan_nr = chan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800611
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200612 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800613
614 return abis_rsl_sendmsg(msg);
615}
616
Harald Welte85a163c2009-08-10 11:43:22 +0200617/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteafe3c232009-07-19 18:36:49 +0200618int rsl_deact_sacch(struct gsm_lchan *lchan)
619{
620 struct abis_rsl_dchan_hdr *dh;
621 struct msgb *msg = rsl_msgb_alloc();
622
623 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
624 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
Harald Weltee6d51f92011-06-25 10:02:33 +0200625 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteafe3c232009-07-19 18:36:49 +0200626
627 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200628 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteafe3c232009-07-19 18:36:49 +0200629
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100630 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteafe3c232009-07-19 18:36:49 +0200631
632 return abis_rsl_sendmsg(msg);
633}
634
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800635static void error_timeout_cb(void *data)
636{
637 struct gsm_lchan *lchan = data;
638 if (lchan->state != LCHAN_S_REL_ERR) {
639 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
640 gsm_lchan_name(lchan), lchan->state);
641 return;
642 }
643
644 /* go back to the none state */
645 LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800646 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800647}
648
Harald Welte08011e22011-03-04 13:41:31 +0100649static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
650
Harald Welte85a163c2009-08-10 11:43:22 +0200651/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +0100652static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error,
653 enum sacch_deact deact_sacch)
Harald Welte59b04682009-06-10 05:40:52 +0800654{
655 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800656 struct msgb *msg;
Harald Welte08011e22011-03-04 13:41:31 +0100657 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800658
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +0100659 /* Stop timers that should lead to a channel release */
660 osmo_timer_del(&lchan->T3109);
661
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800662 if (lchan->state == LCHAN_S_REL_ERR) {
663 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
664 gsm_lchan_name(lchan));
665 return -1;
666 }
667
668 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800669 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
670 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltee6d51f92011-06-25 10:02:33 +0200671 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800672
673 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200674 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800675
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800676 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
677
678 if (error) {
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200679 struct e1inp_sign_link *sign_link = msg->dst;
680
Holger Hans Peter Freyther701a6472011-12-28 12:11:40 +0100681 /*
682 * FIXME: GSM 04.08 gives us two options for the abnormal
683 * chanel release. This can be either like in the non-existent
684 * sub-lcuase 3.5.1 or for the main signalling link deactivate
685 * the SACCH, start timer T3109 and consider the channel as
686 * released.
687 *
688 * This code is doing the later for all raido links and not
689 * only the main link. Right now all SAPIs are released on the
690 * local end, the SACCH will be de-activated and right now the
691 * T3111 will be started. First T3109 should be started and then
692 * the T3111.
693 *
694 * TODO: Move this out of the function.
695 */
696
697 /*
698 * sacch de-activate and "local end release"
699 */
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +0100700 if (deact_sacch == SACCH_DEACTIVATE)
701 rsl_deact_sacch(lchan);
Holger Hans Peter Freyther701a6472011-12-28 12:11:40 +0100702 rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END);
703
704 /*
705 * TODO: start T3109 now.
706 */
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800707 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800708 lchan->error_timer.data = lchan;
709 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200710 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200711 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800712 }
Harald Welte59b04682009-06-10 05:40:52 +0800713
Harald Welte32951ea2011-08-10 23:26:33 +0200714 /* Start another timer or assume the BTS sends a ACK/NACK? */
715 lchan->act_timer.cb = lchan_deact_tmr_cb;
716 lchan->act_timer.data = lchan;
717 osmo_timer_schedule(&lchan->act_timer, 4, 0);
718
Harald Welte08011e22011-03-04 13:41:31 +0100719 rc = abis_rsl_sendmsg(msg);
720
Harald Welte85a163c2009-08-10 11:43:22 +0200721 /* BTS will respond by RF CHAN REL ACK */
Harald Welte6bddd822011-01-14 23:18:59 +0100722#ifdef HSL_SR_1_0
Harald Welte08011e22011-03-04 13:41:31 +0100723 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
724 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
725 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte6bddd822011-01-14 23:18:59 +0100726#endif
Harald Welte08011e22011-03-04 13:41:31 +0100727
728 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800729}
730
Harald Welte9773f6c2011-01-14 14:16:16 +0100731static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
732{
733
734 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
735
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100736 /* Stop all pending timers */
Harald Welte32951ea2011-08-10 23:26:33 +0200737 osmo_timer_del(&lchan->act_timer);
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100738 osmo_timer_del(&lchan->T3111);
Harald Welte32951ea2011-08-10 23:26:33 +0200739
Harald Welte9773f6c2011-01-14 14:16:16 +0100740 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
741 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
742 gsm_lchan_name(lchan),
743 gsm_lchans_name(lchan->state));
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100744 do_lchan_free(lchan);
Harald Welte9773f6c2011-01-14 14:16:16 +0100745
746 return 0;
747}
748
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200749int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
750 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte59b04682009-06-10 05:40:52 +0800751{
752 struct abis_rsl_dchan_hdr *dh;
753 struct msgb *msg = rsl_msgb_alloc();
754
755 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
756 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
757 dh->chan_nr = RSL_CHAN_PCH_AGCH;
758
759 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
760 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
761 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
762
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200763 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800764
765 return abis_rsl_sendmsg(msg);
766}
767
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200768int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte59b04682009-06-10 05:40:52 +0800769{
770 int i, len = strlen(str_in);
771
772 for (i = 0; i < len; i++) {
773 int num = str_in[i] - 0x30;
774 if (num < 0 || num > 9)
775 return -1;
776 if (i % 2 == 0)
777 bcd_out[i/2] = num;
778 else
779 bcd_out[i/2] |= (num << 4);
780 }
781
782 return 0;
783}
784
785/* Chapter 8.5.6 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200786int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte59b04682009-06-10 05:40:52 +0800787{
788 struct msgb *msg = rsl_msgb_alloc();
789 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200790 uint8_t buf[MACBLOCK_SIZE];
Harald Welte59b04682009-06-10 05:40:52 +0800791
792 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
793 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
794 dh->chan_nr = RSL_CHAN_PCH_AGCH;
795
796 switch (bts->type) {
797 case GSM_BTS_TYPE_BS11:
798 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
799 break;
800 default:
801 /* If phase 2, construct a FULL_IMM_ASS_INFO */
802 pad_macblock(buf, val, len);
803 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
804 break;
805 }
806
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200807 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800808
809 return abis_rsl_sendmsg(msg);
810}
811
Harald Welte4684e632009-08-10 09:51:40 +0200812/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte12090752009-08-10 10:07:33 +0200813int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte4684e632009-08-10 09:51:40 +0200814{
815 struct msgb *msg = rsl_msgb_alloc();
816 struct abis_rsl_dchan_hdr *dh;
817
818 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
819 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte874a5b42009-08-10 11:26:14 +0200820 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +0200821 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200822 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte4684e632009-08-10 09:51:40 +0200823
Harald Weltede4477a2009-12-24 12:20:20 +0100824 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200825 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte874a5b42009-08-10 11:26:14 +0200826
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200827 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte874a5b42009-08-10 11:26:14 +0200828
Harald Welte4684e632009-08-10 09:51:40 +0200829 return abis_rsl_sendmsg(msg);
830}
831
832
Harald Welte59b04682009-06-10 05:40:52 +0800833/* Send "DATA REQUEST" message with given L3 Info payload */
834/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200835int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800836{
Harald Welte59b04682009-06-10 05:40:52 +0800837 if (msg->lchan == NULL) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100838 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte59b04682009-06-10 05:40:52 +0800839 return -EINVAL;
840 }
841
Harald Weltee6d51f92011-06-25 10:02:33 +0200842 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100843 link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800844
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200845 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800846
847 return abis_rsl_sendmsg(msg);
848}
849
Harald Welteed9a5ab2009-08-09 13:47:35 +0200850/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
851/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200852int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteed9a5ab2009-08-09 13:47:35 +0200853{
Harald Weltea22d36b2010-03-04 10:33:10 +0100854 struct msgb *msg;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200855
Harald Weltee6d51f92011-06-25 10:02:33 +0200856 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100857 link_id, 0);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200858 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200859
Harald Welte17091bd2012-04-26 19:42:19 +0200860 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
861 gsm_lchan_name(lchan), link_id);
862
Harald Welteed9a5ab2009-08-09 13:47:35 +0200863 return abis_rsl_sendmsg(msg);
864}
865
Harald Welte0f2e3c12009-08-08 13:15:07 +0200866/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
867 This is what higher layers should call. The BTS then responds with
868 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
869 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
870 lchan_free() */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100871int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
872 enum rsl_rel_mode release_mode)
Harald Welte0f2e3c12009-08-08 13:15:07 +0200873{
Harald Welte0f2e3c12009-08-08 13:15:07 +0200874
Harald Weltea22d36b2010-03-04 10:33:10 +0100875 struct msgb *msg;
876
Harald Weltee6d51f92011-06-25 10:02:33 +0200877 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100878 link_id, 0);
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800879 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100880 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welte0f2e3c12009-08-08 13:15:07 +0200881
Harald Weltec88a4432009-12-29 10:44:17 +0100882 /* FIXME: start some timer in case we don't receive a REL ACK ? */
883
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200884 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte0f2e3c12009-08-08 13:15:07 +0200885
Harald Welte17091bd2012-04-26 19:42:19 +0200886 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100887 gsm_lchan_name(lchan), link_id, release_mode);
Harald Welte17091bd2012-04-26 19:42:19 +0200888
Harald Welte0f2e3c12009-08-08 13:15:07 +0200889 return abis_rsl_sendmsg(msg);
890}
891
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200892int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
893{
894 lchan->state = state;
895 return 0;
896}
897
Harald Welte59b04682009-06-10 05:40:52 +0800898/* Chapter 8.4.2: Channel Activate Acknowledge */
899static int rsl_rx_chan_act_ack(struct msgb *msg)
900{
901 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
902
903 /* BTS has confirmed channel activation, we now need
904 * to assign the activated channel to the MS */
905 if (rslh->ie_chan != RSL_IE_CHAN_NR)
906 return -EINVAL;
Harald Welte6720a432009-11-29 22:45:52 +0100907
Harald Welte32951ea2011-08-10 23:26:33 +0200908 osmo_timer_del(&msg->lchan->act_timer);
909
Harald Weltec88a4432009-12-29 10:44:17 +0100910 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welteab2534c2009-12-29 10:52:38 +0100911 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
912 gsm_lchan_name(msg->lchan),
913 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200914 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welte4baa9c52009-12-21 13:27:11 +0100915
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +0800916 if (msg->lchan->rqd_ref) {
917 rsl_send_imm_assignment(msg->lchan);
918 talloc_free(msg->lchan->rqd_ref);
919 msg->lchan->rqd_ref = NULL;
920 msg->lchan->rqd_ta = 0;
921 }
922
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100923 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100924
Harald Welte59b04682009-06-10 05:40:52 +0800925 return 0;
926}
927
928/* Chapter 8.4.3: Channel Activate NACK */
929static int rsl_rx_chan_act_nack(struct msgb *msg)
930{
931 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
932 struct tlv_parsed tp;
933
Harald Welte32951ea2011-08-10 23:26:33 +0200934 osmo_timer_del(&msg->lchan->act_timer);
935
Daniel Willmann9e9d44c2011-08-11 04:54:23 +0200936 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100937 gsm_lchan_name(msg->lchan));
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100938
Harald Welte59b04682009-06-10 05:40:52 +0800939 /* BTS has rejected channel activation ?!? */
940 if (dh->ie_chan != RSL_IE_CHAN_NR)
941 return -EINVAL;
942
943 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100944 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200945 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100946 print_rsl_cause(LOGL_ERROR, cause,
Harald Weltef1a168d2009-07-28 17:58:09 +0200947 TLVP_LEN(&tp, RSL_IE_CAUSE));
Holger Hans Peter Freyther5149c172012-12-06 19:25:06 +0100948 msg->lchan->error_cause = *cause;
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100949 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther5149c172012-12-06 19:25:06 +0100950 rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
Daniel Willmann245ee032011-08-11 04:47:11 +0200951 else
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +0100952 rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
Daniel Willmann245ee032011-08-11 04:47:11 +0200953
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100954 } else
Holger Hans Peter Freyther5149c172012-12-06 19:25:06 +0100955 rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200956
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100957 LOGPC(DRSL, LOGL_ERROR, "\n");
958
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100959 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte59b04682009-06-10 05:40:52 +0800960 return 0;
961}
962
963/* Chapter 8.4.4: Connection Failure Indication */
964static int rsl_rx_conn_fail(struct msgb *msg)
965{
966 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
967 struct tlv_parsed tp;
968
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100969 /* FIXME: print which channel */
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100970 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100971 gsm_lchan_name(msg->lchan));
Harald Welte59b04682009-06-10 05:40:52 +0800972
973 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
974
Harald Weltef1a168d2009-07-28 17:58:09 +0200975 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +0100976 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +0200977 TLVP_LEN(&tp, RSL_IE_CAUSE));
978
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100979 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte59b04682009-06-10 05:40:52 +0800980 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200981 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +0100982 return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
Harald Welte59b04682009-06-10 05:40:52 +0800983}
984
Harald Weltec20bd1d2009-11-29 19:07:28 +0100985static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
986 const char *prefix)
987{
Harald Welte0e4fa782009-12-16 16:52:07 +0100988 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
989 prefix, rxlev2dbm(mru->full.rx_lev),
990 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Weltec20bd1d2009-11-29 19:07:28 +0100991 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
992 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
993}
994
Harald Welte50290cc2012-07-02 17:12:08 +0200995static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Weltec20bd1d2009-11-29 19:07:28 +0100996{
Harald Welte0e4fa782009-12-16 16:52:07 +0100997 int i;
Harald Welte50290cc2012-07-02 17:12:08 +0200998 char *name = "";
Harald Welte0e4fa782009-12-16 16:52:07 +0100999
Harald Welte50290cc2012-07-02 17:12:08 +02001000 if (lchan && lchan->conn && lchan->conn->subscr)
1001 name = subscr_name(lchan->conn->subscr);
1002
1003 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001004
1005 if (mr->flags & MEAS_REP_F_DL_DTX)
1006 DEBUGPC(DMEAS, "DTXd ");
1007
1008 print_meas_rep_uni(&mr->ul, "ul");
1009 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
1010 if (mr->flags & MEAS_REP_F_MS_TO)
1011 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
1012
1013 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte0e4fa782009-12-16 16:52:07 +01001014 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001015 DEBUGPC(DMEAS, "L1_FPC=%u ",
1016 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
1017 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
1018 }
1019
1020 if (mr->flags & MEAS_REP_F_UL_DTX)
1021 DEBUGPC(DMEAS, "DTXu ");
1022 if (mr->flags & MEAS_REP_F_BA1)
1023 DEBUGPC(DMEAS, "BA1 ");
1024 if (!(mr->flags & MEAS_REP_F_DL_VALID))
1025 DEBUGPC(DMEAS, "NOT VALID ");
1026 else
1027 print_meas_rep_uni(&mr->dl, "dl");
1028
1029 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte0b833f82009-12-19 18:33:05 +01001030 if (mr->num_cell == 7)
1031 return;
Harald Welte0e4fa782009-12-16 16:52:07 +01001032 for (i = 0; i < mr->num_cell; i++) {
1033 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte350c2d32009-12-25 23:02:22 +01001034 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1035 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte0e4fa782009-12-16 16:52:07 +01001036 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001037}
1038
Harald Welte59b04682009-06-10 05:40:52 +08001039static int rsl_rx_meas_res(struct msgb *msg)
1040{
1041 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1042 struct tlv_parsed tp;
Harald Weltef9476812009-12-15 21:36:05 +01001043 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001044 uint8_t len;
1045 const uint8_t *val;
Harald Weltec20bd1d2009-11-29 19:07:28 +01001046 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001047
Harald Welte4baa9c52009-12-21 13:27:11 +01001048 /* check if this channel is actually active */
1049 /* FIXME: maybe this check should be way more generic/centralized */
Harald Weltec88a4432009-12-29 10:44:17 +01001050 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freyther67a2e292010-07-29 14:50:57 +08001051 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Weltec88a4432009-12-29 10:44:17 +01001052 gsm_lchan_name(msg->lchan));
Harald Welte4baa9c52009-12-21 13:27:11 +01001053 return 0;
Harald Weltec88a4432009-12-29 10:44:17 +01001054 }
Harald Welte4baa9c52009-12-21 13:27:11 +01001055
Harald Weltef9476812009-12-15 21:36:05 +01001056 memset(mr, 0, sizeof(*mr));
Harald Welteaa0efa12009-12-16 23:29:34 +01001057 mr->lchan = msg->lchan;
Harald Welte4efcc542009-11-30 19:16:47 +01001058
Harald Welte59b04682009-06-10 05:40:52 +08001059 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1060
Harald Weltec20bd1d2009-11-29 19:07:28 +01001061 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1062 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1063 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1064 return -EIO;
1065
1066 /* Mandatory Parts */
Harald Weltef9476812009-12-15 21:36:05 +01001067 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001068
1069 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1070 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1071 if (len >= 3) {
1072 if (val[0] & 0x40)
Harald Weltef9476812009-12-15 21:36:05 +01001073 mr->flags |= MEAS_REP_F_DL_DTX;
1074 mr->ul.full.rx_lev = val[0] & 0x3f;
1075 mr->ul.sub.rx_lev = val[1] & 0x3f;
1076 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1077 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte59b04682009-06-10 05:40:52 +08001078 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001079
Harald Weltef9476812009-12-15 21:36:05 +01001080 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001081
1082 /* Optional Parts */
Harald Welte59b04682009-06-10 05:40:52 +08001083 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Weltef9476812009-12-15 21:36:05 +01001084 mr->ms_timing_offset =
Harald Weltec20bd1d2009-11-29 19:07:28 +01001085 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1086
Harald Weltea1467eb2009-06-20 18:44:35 +02001087 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001088 struct e1inp_sign_link *sign_link = msg->dst;
1089
Harald Weltec20bd1d2009-11-29 19:07:28 +01001090 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001091 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001092 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001093 if (val[0] & 0x04)
Harald Weltef9476812009-12-15 21:36:05 +01001094 mr->flags |= MEAS_REP_F_FPC;
1095 mr->ms_l1.ta = val[1];
Andreas Eversbergfe56cf82011-12-24 11:49:05 +01001096 /* BS11 and Nokia reports TA shifted by 2 bits */
1097 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1098 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001099 mr->ms_l1.ta >>= 2;
Harald Weltea1467eb2009-06-20 18:44:35 +02001100 }
Harald Welte59b04682009-06-10 05:40:52 +08001101 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001102 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001103 rc = gsm48_parse_meas_rep(mr, msg);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001104 if (rc < 0)
1105 return rc;
1106 }
1107
Harald Welte50290cc2012-07-02 17:12:08 +02001108 print_meas_rep(msg->lchan, mr);
Harald Welte59b04682009-06-10 05:40:52 +08001109
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001110 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Welte4efcc542009-11-30 19:16:47 +01001111
Harald Welte59b04682009-06-10 05:40:52 +08001112 return 0;
1113}
1114
Harald Welte6720a432009-11-29 22:45:52 +01001115/* Chapter 8.4.7 */
1116static int rsl_rx_hando_det(struct msgb *msg)
1117{
1118 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1119 struct tlv_parsed tp;
1120
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001121 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welte6720a432009-11-29 22:45:52 +01001122
1123 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1124
1125 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1126 DEBUGPC(DRSL, "access delay = %u\n",
1127 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1128 else
1129 DEBUGPC(DRSL, "\n");
1130
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001131 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +01001132
1133 return 0;
1134}
1135
Harald Welte59b04682009-06-10 05:40:52 +08001136static int abis_rsl_rx_dchan(struct msgb *msg)
1137{
1138 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1139 int rc = 0;
1140 char *ts_name;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001141 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001142
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001143 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001144 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001145
Harald Welte59b04682009-06-10 05:40:52 +08001146 switch (rslh->c.msg_type) {
1147 case RSL_MT_CHAN_ACTIV_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001148 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001149 rc = rsl_rx_chan_act_ack(msg);
1150 break;
1151 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001152 rc = rsl_rx_chan_act_nack(msg);
1153 break;
1154 case RSL_MT_CONN_FAIL:
1155 rc = rsl_rx_conn_fail(msg);
1156 break;
1157 case RSL_MT_MEAS_RES:
1158 rc = rsl_rx_meas_res(msg);
1159 break;
Harald Welte6720a432009-11-29 22:45:52 +01001160 case RSL_MT_HANDO_DET:
1161 rc = rsl_rx_hando_det(msg);
1162 break;
Harald Welte59b04682009-06-10 05:40:52 +08001163 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte9773f6c2011-01-14 14:16:16 +01001164 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001165 break;
1166 case RSL_MT_MODE_MODIFY_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001167 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001168 break;
1169 case RSL_MT_MODE_MODIFY_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001170 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001171 break;
Harald Welteaed946e2009-10-24 10:29:22 +02001172 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001173 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001174 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001175 break;
1176 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001177 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001178 break;
1179 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001180 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001181 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001182 break;
1183 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001184 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001185 break;
Harald Welte59b04682009-06-10 05:40:52 +08001186 case RSL_MT_PHY_CONTEXT_CONF:
1187 case RSL_MT_PREPROC_MEAS_RES:
1188 case RSL_MT_TALKER_DET:
1189 case RSL_MT_LISTENER_DET:
1190 case RSL_MT_REMOTE_CODEC_CONF_REP:
1191 case RSL_MT_MR_CODEC_MOD_ACK:
1192 case RSL_MT_MR_CODEC_MOD_NACK:
1193 case RSL_MT_MR_CODEC_MOD_PER:
Harald Weltede4477a2009-12-24 12:20:20 +01001194 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1195 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001196 break;
1197 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001198 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1199 ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001200 return -EINVAL;
1201 }
1202
1203 return rc;
1204}
1205
1206static int rsl_rx_error_rep(struct msgb *msg)
1207{
1208 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Weltef1a168d2009-07-28 17:58:09 +02001209 struct tlv_parsed tp;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001210 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001211
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001212 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Weltef1a168d2009-07-28 17:58:09 +02001213
1214 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1215
1216 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001217 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001218 TLVP_LEN(&tp, RSL_IE_CAUSE));
1219
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001220 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001221
1222 return 0;
1223}
1224
1225static int abis_rsl_rx_trx(struct msgb *msg)
1226{
1227 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001228 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001229 int rc = 0;
1230
1231 switch (rslh->msg_type) {
1232 case RSL_MT_ERROR_REPORT:
1233 rc = rsl_rx_error_rep(msg);
1234 break;
1235 case RSL_MT_RF_RES_IND:
1236 /* interference on idle channels of TRX */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001237 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001238 break;
1239 case RSL_MT_OVERLOAD:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001240 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001241 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001242 gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001243 break;
Dieter Spaar49c843e2011-07-28 00:01:50 +02001244 case 0x42: /* Nokia specific: SI End ACK */
1245 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1246 break;
1247 case 0x43: /* Nokia specific: SI End NACK */
1248 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1249 break;
Harald Welte59b04682009-06-10 05:40:52 +08001250 default:
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001251 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001252 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001253 return -EINVAL;
1254 }
1255 return rc;
1256}
1257
Harald Welte427dbc42009-08-10 00:26:10 +02001258/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1259static void t3101_expired(void *data)
1260{
1261 struct gsm_lchan *lchan = data;
1262
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +01001263 rsl_rf_chan_release(lchan, 1, SACCH_DEACTIVATE);
Harald Welte427dbc42009-08-10 00:26:10 +02001264}
1265
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001266/* If T3111 expires, we will send the RF Channel Request */
1267static void t3111_expired(void *data)
1268{
1269 struct gsm_lchan *lchan = data;
1270
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +01001271 rsl_rf_chan_release(lchan, 0, SACCH_NONE);
1272}
1273
1274/* If T3109 expires the MS has not send a UA/UM do the error release */
1275static void t3109_expired(void *data)
1276{
1277 struct gsm_lchan *lchan = data;
1278
1279 LOGP(DRSL, LOGL_ERROR,
1280 "%s SACCH deactivation timeout.\n", gsm_lchan_name(lchan));
1281 rsl_rf_chan_release(lchan, 1, SACCH_NONE);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001282}
1283
laforge50312e82010-06-21 12:08:52 +02001284#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1285
Harald Weltea00fdd72010-12-23 14:39:29 +01001286/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1287static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1288 unsigned int num_req_refs,
1289 struct gsm48_req_ref *rqd_refs,
1290 uint8_t wait_ind)
1291{
1292 uint8_t buf[GSM_MACBLOCK_LEN];
1293 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1294
1295 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1296 memset(iar, 0, sizeof(*iar));
1297 iar->proto_discr = GSM48_PDISC_RR;
1298 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1299 iar->page_mode = GSM48_PM_SAME;
1300
1301 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1302 iar->wait_ind1 = wait_ind;
1303
1304 if (num_req_refs >= 2)
1305 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1306 else
1307 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1308 iar->wait_ind2 = wait_ind;
1309
1310 if (num_req_refs >= 3)
1311 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1312 else
1313 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1314 iar->wait_ind3 = wait_ind;
1315
1316 if (num_req_refs >= 4)
1317 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1318 else
1319 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1320 iar->wait_ind4 = wait_ind;
1321
1322 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1323}
1324
Harald Welte59b04682009-06-10 05:40:52 +08001325/* MS has requested a channel on the RACH */
1326static int rsl_rx_chan_rqd(struct msgb *msg)
1327{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001328 struct e1inp_sign_link *sign_link = msg->dst;
1329 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001330 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1331 struct gsm48_req_ref *rqd_ref;
Harald Welte59b04682009-06-10 05:40:52 +08001332 enum gsm_chan_t lctype;
1333 enum gsm_chreq_reason_t chreq_reason;
1334 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001335 uint8_t rqd_ta;
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001336 int is_lu;
Harald Welte59b04682009-06-10 05:40:52 +08001337
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001338 uint16_t arfcn;
Holger Hans Peter Freytherefd75b52012-02-03 20:10:13 +01001339 uint8_t subch;
Harald Welte59b04682009-06-10 05:40:52 +08001340
1341 /* parse request reference to be used in immediate assign */
1342 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1343 return -EINVAL;
1344
1345 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1346
1347 /* parse access delay and use as TA */
1348 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1349 return -EINVAL;
1350 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1351
1352 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1353 * request reference RA */
Holger Hans Peter Freytherf0f37f12010-09-06 09:36:02 +08001354 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1355 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte59b04682009-06-10 05:40:52 +08001356
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001357 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte3edc5a92009-12-22 00:41:05 +01001358
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001359 /*
1360 * We want LOCATION UPDATES to succeed and will assign a TCH
1361 * if we have no SDCCH available.
1362 */
1363 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1364
Harald Welte59b04682009-06-10 05:40:52 +08001365 /* check availability / allocate channel */
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001366 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte59b04682009-06-10 05:40:52 +08001367 if (!lchan) {
Harald Welte (local)e0bb5fa2009-12-27 13:48:09 +01001368 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)02204d02009-12-27 18:05:25 +01001369 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001370 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Weltea00fdd72010-12-23 14:39:29 +01001371 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1372 if (bts->network->T3122)
1373 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte59b04682009-06-10 05:40:52 +08001374 return -ENOMEM;
1375 }
1376
Harald Weltec88a4432009-12-29 10:44:17 +01001377 if (lchan->state != LCHAN_S_NONE)
1378 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welteab2534c2009-12-29 10:52:38 +01001379 "in state %s\n", gsm_lchan_name(lchan),
1380 gsm_lchans_name(lchan->state));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +01001381
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001382 /* save the RACH data as we need it after the CHAN ACT ACK */
1383 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1384 if (!lchan->rqd_ref) {
1385 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1386 lchan_free(lchan);
1387 return -ENOMEM;
1388 }
1389
Holger Hans Peter Freyther161cec12011-12-29 23:33:04 +01001390 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001391 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1392 lchan->rqd_ta = rqd_ta;
1393
Harald Welte59b04682009-06-10 05:40:52 +08001394 arfcn = lchan->ts->trx->arfcn;
1395 subch = lchan->nr;
1396
Harald Welted2dd9de2009-08-30 15:37:11 +09001397 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)cbd46102009-08-13 10:14:26 +02001398 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte9a229e12009-08-10 00:45:40 +02001399 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte39274f42009-07-29 15:41:29 +02001400 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte77234e12009-08-28 23:28:28 +09001401 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001402
Harald Welte32951ea2011-08-10 23:26:33 +02001403 /* Start another timer or assume the BTS sends a ACK/NACK? */
1404 lchan->act_timer.cb = lchan_act_tmr_cb;
1405 lchan->act_timer.data = lchan;
1406 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1407
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001408 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1409 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1410 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1411 rqd_ref->ra, rqd_ta);
1412
1413 /* BS11 requires TA shifted by 2 bits */
1414 if (bts->type == GSM_BTS_TYPE_BS11)
1415 rqd_ta <<= 2;
Harald Welteb90d7bd2009-12-17 00:31:10 +01001416 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001417
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001418 return 0;
1419}
1420
1421static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1422{
1423 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001424 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001425 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1426
Harald Welte59b04682009-06-10 05:40:52 +08001427 /* create IMMEDIATE ASSIGN 04.08 messge */
laforgee06d5982010-06-20 15:18:46 +02001428 memset(ia, 0, sizeof(*ia));
laforge50312e82010-06-21 12:08:52 +02001429 /* we set ia->l2_plen once we know the length of the MA below */
laforgee06d5982010-06-20 15:18:46 +02001430 ia->proto_discr = GSM48_PDISC_RR;
1431 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1432 ia->page_mode = GSM48_PM_SAME;
1433 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea42a93f2010-06-14 22:26:10 +02001434
Harald Welte59b04682009-06-10 05:40:52 +08001435 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001436 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1437 ia->timing_advance = lchan->rqd_ta;
Harald Weltea42a93f2010-06-14 22:26:10 +02001438 if (!lchan->ts->hopping.enabled) {
laforgee06d5982010-06-20 15:18:46 +02001439 ia->mob_alloc_len = 0;
Harald Weltea42a93f2010-06-14 22:26:10 +02001440 } else {
laforgee06d5982010-06-20 15:18:46 +02001441 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1442 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea42a93f2010-06-14 22:26:10 +02001443 }
Harald Welte07f32182010-06-28 18:41:27 +02001444 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1445 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte59b04682009-06-10 05:40:52 +08001446
Harald Welte427dbc42009-08-10 00:26:10 +02001447 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1448 lchan->T3101.cb = t3101_expired;
1449 lchan->T3101.data = lchan;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001450 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001451
1452 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001453 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte59b04682009-06-10 05:40:52 +08001454}
1455
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001456/* current load on the CCCH */
Harald Welte59b04682009-06-10 05:40:52 +08001457static int rsl_rx_ccch_load(struct msgb *msg)
1458{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001459 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001460 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001461 struct ccch_signal_data sd;
1462
1463 sd.bts = sign_link->trx->bts;
1464 sd.rach_slot_count = -1;
1465 sd.rach_busy_count = -1;
1466 sd.rach_access_count = -1;
Harald Welte59b04682009-06-10 05:40:52 +08001467
1468 switch (rslh->data[0]) {
1469 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001470 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1471 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte008a4922010-04-19 10:24:07 +02001472 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001473 sd.pg_buf_space = 50;
Harald Welte008a4922010-04-19 10:24:07 +02001474 }
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001475 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1476 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001477 break;
1478 case RSL_IE_RACH_LOAD:
1479 if (msg->data_len >= 7) {
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001480 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1481 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1482 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1483 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001484 }
1485 break;
1486 default:
1487 break;
1488 }
1489
1490 return 0;
1491}
1492
1493static int abis_rsl_rx_cchan(struct msgb *msg)
1494{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001495 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001496 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1497 int rc = 0;
1498
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001499 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +08001500
1501 switch (rslh->c.msg_type) {
1502 case RSL_MT_CHAN_RQD:
1503 /* MS has requested a channel on the RACH */
1504 rc = rsl_rx_chan_rqd(msg);
1505 break;
1506 case RSL_MT_CCCH_LOAD_IND:
1507 /* current load on the CCCH */
1508 rc = rsl_rx_ccch_load(msg);
1509 break;
1510 case RSL_MT_DELETE_IND:
1511 /* CCCH overloaded, IMM_ASSIGN was dropped */
1512 case RSL_MT_CBCH_LOAD_IND:
1513 /* current load on the CBCH */
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001514 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1515 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001516 break;
1517 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001518 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1519 "0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001520 return -EINVAL;
1521 }
1522
1523 return rc;
1524}
1525
1526static int rsl_rx_rll_err_ind(struct msgb *msg)
1527{
1528 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001529 uint8_t *rlm_cause = rllh->data;
Harald Welte59b04682009-06-10 05:40:52 +08001530
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001531 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001532 gsm_lchan_name(msg->lchan),
Harald Welteb30935e2010-03-25 12:13:02 +08001533 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteed9a5ab2009-08-09 13:47:35 +02001534
1535 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001536
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001537 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001538 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +01001539 return rsl_rf_chan_release(msg->lchan, 1, SACCH_DEACTIVATE);
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001540 }
Harald Welte692f5852009-07-04 09:40:05 +02001541
Harald Welte59b04682009-06-10 05:40:52 +08001542 return 0;
1543}
1544
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001545static void rsl_handle_release(struct gsm_lchan *lchan)
1546{
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001547 int sapi;
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001548 struct gsm_bts *bts;
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001549
Holger Hans Peter Freyther701a6472011-12-28 12:11:40 +01001550 /*
1551 * Maybe only one link/SAPI was releasd or the error handling
1552 * was activated. Just return now and let the other code handle
1553 * it.
1554 */
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001555 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001556 return;
1557
1558 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1559 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1560 continue;
Harald Welte497aa982010-12-24 12:51:07 +01001561 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001562 gsm_lchan_name(lchan), sapi);
1563 return;
1564 }
1565
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001566
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +01001567 /* Stop T3109 and wait for T3111 before re-using the channel */
1568 osmo_timer_del(&lchan->T3109);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001569 lchan->T3111.cb = t3111_expired;
1570 lchan->T3111.data = lchan;
1571 bts = lchan->ts->trx->bts;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001572 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001573}
1574
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001575/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte59b04682009-06-10 05:40:52 +08001576 0x02, 0x06,
1577 0x01, 0x20,
1578 0x02, 0x00,
1579 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1580
1581static int abis_rsl_rx_rll(struct msgb *msg)
1582{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001583 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001584 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1585 int rc = 0;
1586 char *ts_name;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001587 uint8_t sapi = rllh->link_id & 7;
Harald Welte59b04682009-06-10 05:40:52 +08001588
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001589 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001590 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltede4477a2009-12-24 12:20:20 +01001591 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte59b04682009-06-10 05:40:52 +08001592
1593 switch (rllh->c.msg_type) {
1594 case RSL_MT_DATA_IND:
1595 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001596 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001597 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1598 rllh->data[0] == RSL_IE_L3_INFO) {
1599 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001600 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001601 }
1602 break;
1603 case RSL_MT_EST_IND:
1604 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte427dbc42009-08-10 00:26:10 +02001605 /* lchan is established, stop T3101 */
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001606 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001607 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001608 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001609 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1610 rllh->data[0] == RSL_IE_L3_INFO) {
1611 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001612 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001613 }
1614 break;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001615 case RSL_MT_EST_CONF:
Harald Welte61402172009-08-09 14:13:58 +02001616 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001617 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001618 rll_indication(msg->lchan, rllh->link_id,
1619 BSC_RLLR_IND_EST_CONF);
1620 break;
Harald Welte59b04682009-06-10 05:40:52 +08001621 case RSL_MT_REL_IND:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001622 /* BTS informs us of having received DISC from MS */
Harald Welteb6601442009-08-04 02:50:21 +02001623 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001624 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001625 rll_indication(msg->lchan, rllh->link_id,
1626 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001627 rsl_handle_release(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001628 break;
1629 case RSL_MT_REL_CONF:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001630 /* BTS informs us of having received UA from MS,
1631 * in response to DISC that we've sent earlier */
Harald Welteb6601442009-08-04 02:50:21 +02001632 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001633 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001634 rsl_handle_release(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001635 break;
1636 case RSL_MT_ERROR_IND:
Harald Welte59b04682009-06-10 05:40:52 +08001637 rc = rsl_rx_rll_err_ind(msg);
1638 break;
1639 case RSL_MT_UNIT_DATA_IND:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001640 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1641 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001642 break;
1643 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001644 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1645 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001646 }
Harald Welte59b04682009-06-10 05:40:52 +08001647 return rc;
1648}
1649
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001650static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Welte98d79f92009-07-28 18:11:56 +02001651{
Harald Welteb284b472009-12-02 01:58:23 +05301652 switch (lchan->tch_mode) {
Harald Welte98d79f92009-07-28 18:11:56 +02001653 case GSM48_CMODE_SPEECH_V1:
Harald Welteb284b472009-12-02 01:58:23 +05301654 switch (lchan->type) {
1655 case GSM_LCHAN_TCH_F:
1656 return 0x00;
1657 case GSM_LCHAN_TCH_H:
1658 return 0x03;
1659 default:
1660 break;
1661 }
Harald Welte98d79f92009-07-28 18:11:56 +02001662 case GSM48_CMODE_SPEECH_EFR:
Harald Welteb284b472009-12-02 01:58:23 +05301663 switch (lchan->type) {
1664 case GSM_LCHAN_TCH_F:
1665 return 0x01;
1666 /* there's no half-rate EFR */
1667 default:
1668 break;
1669 }
Harald Welte98d79f92009-07-28 18:11:56 +02001670 case GSM48_CMODE_SPEECH_AMR:
Harald Welteb284b472009-12-02 01:58:23 +05301671 switch (lchan->type) {
1672 case GSM_LCHAN_TCH_F:
1673 return 0x02;
1674 case GSM_LCHAN_TCH_H:
1675 return 0x05;
1676 default:
1677 break;
1678 }
1679 default:
1680 break;
Harald Welte98d79f92009-07-28 18:11:56 +02001681 }
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001682 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welteb284b472009-12-02 01:58:23 +05301683 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001684 return 0;
Harald Welte98d79f92009-07-28 18:11:56 +02001685}
1686
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001687static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munaut1338a552009-12-20 22:06:40 +01001688{
1689 switch (lchan->tch_mode) {
1690 case GSM48_CMODE_SPEECH_V1:
1691 switch (lchan->type) {
1692 case GSM_LCHAN_TCH_F:
1693 return RTP_PT_GSM_FULL;
1694 case GSM_LCHAN_TCH_H:
1695 return RTP_PT_GSM_HALF;
1696 default:
1697 break;
1698 }
1699 case GSM48_CMODE_SPEECH_EFR:
1700 switch (lchan->type) {
1701 case GSM_LCHAN_TCH_F:
1702 return RTP_PT_GSM_EFR;
1703 /* there's no half-rate EFR */
1704 default:
1705 break;
1706 }
1707 case GSM48_CMODE_SPEECH_AMR:
1708 switch (lchan->type) {
1709 case GSM_LCHAN_TCH_F:
Sylvain Munaut1338a552009-12-20 22:06:40 +01001710 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freytherd78bee82011-07-21 10:24:46 +02001711 return RTP_PT_AMR;
Sylvain Munaut1338a552009-12-20 22:06:40 +01001712 default:
1713 break;
1714 }
1715 default:
1716 break;
1717 }
1718 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1719 "tch_mode == 0x%02x\n & lchan_type == %d",
1720 lchan->tch_mode, lchan->type);
1721 return 0;
1722}
1723
Harald Welte59b04682009-06-10 05:40:52 +08001724/* ip.access specific RSL extensions */
Harald Weltebffa4992009-12-19 16:42:06 +01001725static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1726{
1727 struct in_addr ip;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001728 uint16_t port, conn_id;
Harald Weltebffa4992009-12-19 16:42:06 +01001729
1730 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001731 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001732 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1733 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1734 }
1735
1736 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001737 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001738 port = ntohs(port);
1739 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1740 lchan->abis_ip.bound_port = port;
1741 }
1742
1743 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001744 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Weltebffa4992009-12-19 16:42:06 +01001745 conn_id = ntohs(conn_id);
1746 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1747 lchan->abis_ip.conn_id = conn_id;
1748 }
1749
1750 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1751 lchan->abis_ip.rtp_payload2 =
1752 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1753 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1754 lchan->abis_ip.rtp_payload2);
1755 }
1756
1757 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1758 lchan->abis_ip.speech_mode =
1759 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1760 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1761 lchan->abis_ip.speech_mode);
1762 }
1763
1764 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001765 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001766 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1767 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1768 }
1769
1770 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001771 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001772 port = ntohs(port);
1773 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1774 lchan->abis_ip.connect_port = port;
1775 }
1776}
1777
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001778int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte59b04682009-06-10 05:40:52 +08001779{
1780 struct msgb *msg = rsl_msgb_alloc();
1781 struct abis_rsl_dchan_hdr *dh;
1782
1783 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001784 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte59b04682009-06-10 05:40:52 +08001785 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001786 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001787
Harald Welte98d79f92009-07-28 18:11:56 +02001788 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001789 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001790 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001791 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001792 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001793
Sylvain Munaut1338a552009-12-20 22:06:40 +01001794 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1795 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1796 lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001797
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001798 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001799
1800 return abis_rsl_sendmsg(msg);
1801}
1802
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001803int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1804 uint8_t rtp_payload2)
Harald Welte59b04682009-06-10 05:40:52 +08001805{
1806 struct msgb *msg = rsl_msgb_alloc();
1807 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001808 uint32_t *att_ip;
Harald Welte98d79f92009-07-28 18:11:56 +02001809 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +08001810
1811 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001812 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte59b04682009-06-10 05:40:52 +08001813 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001814 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001815
Harald Weltebffa4992009-12-19 16:42:06 +01001816 /* we need to store these now as MDCX_ACK does not return them :( */
1817 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1818 lchan->abis_ip.connect_port = port;
1819 lchan->abis_ip.connect_ip = ip;
1820
Harald Weltefb4a9e92009-07-29 12:12:18 +02001821 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001822 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001823 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltefb4a9e92009-07-29 12:12:18 +02001824
Harald Welte98d79f92009-07-28 18:11:56 +02001825 ia.s_addr = htonl(ip);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001826 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1827 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1828 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1829 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001830
Harald Weltebffa4992009-12-19 16:42:06 +01001831 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1832 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001833 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Weltebffa4992009-12-19 16:42:06 +01001834 *att_ip = ia.s_addr;
1835 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1836 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001837 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001838 if (rtp_payload2)
1839 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001840
1841 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001842
1843 return abis_rsl_sendmsg(msg);
1844}
1845
Harald Welte9947d9f2009-12-20 16:51:09 +01001846/* tell BTS to connect RTP stream to our local RTP socket */
1847int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1848{
1849 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1850 int rc;
1851
1852 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1853 ntohs(rs->rtp.sin_local.sin_port),
1854 /* FIXME: use RTP payload of bound socket, not BTS*/
1855 lchan->abis_ip.rtp_payload2);
1856
1857 return rc;
1858}
1859
Harald Welte6f40df02010-12-23 12:59:52 +01001860int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welteaed946e2009-10-24 10:29:22 +02001861{
1862 struct msgb *msg = rsl_msgb_alloc();
1863 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001864 uint8_t msg_type;
Harald Welte2b361522010-03-28 14:42:09 +08001865
1866 if (act)
1867 msg_type = RSL_MT_IPAC_PDCH_ACT;
1868 else
1869 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welteaed946e2009-10-24 10:29:22 +02001870
1871 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte2b361522010-03-28 14:42:09 +08001872 init_dchan_hdr(dh, msg_type);
Harald Welteaed946e2009-10-24 10:29:22 +02001873 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +02001874 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welteaed946e2009-10-24 10:29:22 +02001875
Harald Welte6f40df02010-12-23 12:59:52 +01001876 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte2b361522010-03-28 14:42:09 +08001877 act ? "" : "DE");
Harald Welteaed946e2009-10-24 10:29:22 +02001878
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001879 msg->dst = ts->trx->rsl_link;
Harald Welteaed946e2009-10-24 10:29:22 +02001880
1881 return abis_rsl_sendmsg(msg);
1882}
1883
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001884static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001885{
1886 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1887 struct tlv_parsed tv;
Harald Welte87504212009-12-02 01:56:49 +05301888 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001889
1890 /* the BTS has acknowledged a local bind, it now tells us the IP
1891 * address and port number to which it has bound the given logical
1892 * channel */
1893
1894 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1895 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1896 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welteb9498952009-07-12 09:45:05 +02001897 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001898 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte59b04682009-06-10 05:40:52 +08001899 return -EINVAL;
1900 }
Harald Welte50517742009-12-20 15:42:44 +01001901
Harald Weltebffa4992009-12-19 16:42:06 +01001902 ipac_parse_rtp(lchan, &tv);
Harald Welte50517742009-12-20 15:42:44 +01001903
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001904 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001905
1906 return 0;
1907}
1908
Harald Weltebffa4992009-12-19 16:42:06 +01001909static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1910{
1911 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1912 struct tlv_parsed tv;
1913 struct gsm_lchan *lchan = msg->lchan;
1914
1915 /* the BTS has acknowledged a remote connect request and
1916 * it now tells us the IP address and port number to which it has
1917 * connected the given logical channel */
1918
1919 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1920 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001921 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001922
1923 return 0;
1924}
1925
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001926static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001927{
1928 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1929 struct tlv_parsed tv;
1930
1931 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte59b04682009-06-10 05:40:52 +08001932
Harald Weltef1a168d2009-07-28 17:58:09 +02001933 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001934 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001935 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte59b04682009-06-10 05:40:52 +08001936
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001937 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welteba4e58d2009-07-28 18:02:05 +02001938
Harald Welte59b04682009-06-10 05:40:52 +08001939 return 0;
1940}
1941
1942static int abis_rsl_rx_ipacc(struct msgb *msg)
1943{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001944 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001945 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltede4477a2009-12-24 12:20:20 +01001946 char *ts_name;
Harald Welte59b04682009-06-10 05:40:52 +08001947 int rc = 0;
1948
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001949 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001950 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001951
1952 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001953 case RSL_MT_IPAC_CRCX_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001954 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001955 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001956 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001957 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001958 /* somehow the BTS was unable to bind the lchan to its local
1959 * port?!? */
Harald Weltede4477a2009-12-24 12:20:20 +01001960 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001961 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001962 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte59b04682009-06-10 05:40:52 +08001963 /* the BTS tells us that a connect operation was successful */
Harald Weltede4477a2009-12-24 12:20:20 +01001964 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Weltebffa4992009-12-19 16:42:06 +01001965 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001966 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001967 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001968 /* somehow the BTS was unable to connect the lchan to a remote
1969 * port */
Harald Weltede4477a2009-12-24 12:20:20 +01001970 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001971 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001972 case RSL_MT_IPAC_DLCX_IND:
Harald Weltede4477a2009-12-24 12:20:20 +01001973 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001974 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001975 break;
1976 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001977 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001978 rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001979 break;
1980 }
1981 DEBUGPC(DRSL, "\n");
1982
1983 return rc;
1984}
1985
1986
1987/* Entry-point where L2 RSL from BTS enters */
1988int abis_rsl_rcvmsg(struct msgb *msg)
1989{
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001990 struct abis_rsl_common_hdr *rslh;
Harald Welte59b04682009-06-10 05:40:52 +08001991 int rc = 0;
1992
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001993 if (!msg) {
1994 DEBUGP(DRSL, "Empty RSL msg?..\n");
1995 return -1;
1996 }
1997
1998 if (msgb_l2len(msg) < sizeof(*rslh)) {
1999 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltece807262012-05-31 20:22:34 +02002000 msgb_free(msg);
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01002001 return -1;
2002 }
2003
2004 rslh = msgb_l2(msg);
2005
Harald Welte59b04682009-06-10 05:40:52 +08002006 switch (rslh->msg_discr & 0xfe) {
2007 case ABIS_RSL_MDISC_RLL:
2008 rc = abis_rsl_rx_rll(msg);
2009 break;
2010 case ABIS_RSL_MDISC_DED_CHAN:
2011 rc = abis_rsl_rx_dchan(msg);
2012 break;
2013 case ABIS_RSL_MDISC_COM_CHAN:
2014 rc = abis_rsl_rx_cchan(msg);
2015 break;
2016 case ABIS_RSL_MDISC_TRX:
2017 rc = abis_rsl_rx_trx(msg);
2018 break;
2019 case ABIS_RSL_MDISC_LOC:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01002020 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte59b04682009-06-10 05:40:52 +08002021 rslh->msg_discr);
2022 break;
2023 case ABIS_RSL_MDISC_IPACCESS:
2024 rc = abis_rsl_rx_ipacc(msg);
2025 break;
2026 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01002027 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
2028 "0x%02x\n", rslh->msg_discr);
Harald Weltece807262012-05-31 20:22:34 +02002029 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002030 }
2031 msgb_free(msg);
2032 return rc;
2033}
2034
Holger Hans Peter Freytherb67f4082010-07-21 15:54:32 +08002035int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
2036 uint8_t cb_command, const uint8_t *data, int len)
2037{
2038 struct abis_rsl_dchan_hdr *dh;
2039 struct msgb *cb_cmd;
2040
2041 cb_cmd = rsl_msgb_alloc();
2042 if (!cb_cmd)
2043 return -1;
2044
2045 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2046 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2047 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2048
2049 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2050 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2051
2052 cb_cmd->trx = bts->c0;
2053
2054 return abis_rsl_sendmsg(cb_cmd);
2055}
Dieter Spaar49c843e2011-07-28 00:01:50 +02002056
2057int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2058{
2059 struct abis_rsl_common_hdr *ch;
2060 struct msgb *msg = rsl_msgb_alloc();
2061
2062 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2063 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2064 ch->msg_type = 0x40; /* Nokia SI Begin */
2065
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002066 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002067
2068 return abis_rsl_sendmsg(msg);
2069}
2070
2071int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2072{
2073 struct abis_rsl_common_hdr *ch;
2074 struct msgb *msg = rsl_msgb_alloc();
2075
2076 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2077 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2078 ch->msg_type = 0x41; /* Nokia SI End */
2079
2080 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2081
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002082 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002083
2084 return abis_rsl_sendmsg(msg);
2085}
2086
2087int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2088{
2089 struct abis_rsl_common_hdr *ch;
2090 struct msgb *msg = rsl_msgb_alloc();
2091
2092 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2093 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2094 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2095
2096 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2097 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2098
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002099 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002100
2101 return abis_rsl_sendmsg(msg);
2102}
Holger Hans Peter Freythere38af682011-12-27 22:24:17 +01002103
2104/**
2105 * Release all allocated SAPIs starting from @param start and
2106 * release them with the given release mode. Once the release
2107 * confirmation arrives it will be attempted to release the
2108 * the RF channel.
2109 */
2110int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
2111 enum rsl_rel_mode release_mode)
2112{
2113 int no_sapi = 1;
2114 int sapi;
2115
2116 for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
2117 uint8_t link_id;
2118 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
2119 continue;
2120
2121 link_id = sapi;
2122 if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
2123 link_id |= 0x40;
2124 rsl_release_request(lchan, link_id, release_mode);
2125 no_sapi = 0;
2126 }
2127
2128 return no_sapi;
2129}
Holger Hans Peter Freyther969a4052011-12-28 16:21:05 +01002130
2131int rsl_start_t3109(struct gsm_lchan *lchan)
2132{
2133 struct gsm_bts *bts = lchan->ts->trx->bts;
2134
2135 /* Disabled, mostly legacy code */
2136 if (bts->network->T3109 == 0)
2137 return -1;
2138
2139 lchan->T3109.cb = t3109_expired;
2140 lchan->T3109.data = lchan;
2141 osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0);
2142 return 0;
2143}
Holger Hans Peter Freytherc63cb862012-12-25 23:45:14 +01002144
2145/**
2146 * \brief directly RF Channel Release the lchan
2147 *
2148 * When no SAPI was allocated, directly release the logical channel. This
2149 * should only be called from chan_alloc.c on channel release handling. In
2150 * case no SAPI was established the RF Channel can be directly released,
2151 */
2152int rsl_direct_rf_release(struct gsm_lchan *lchan)
2153{
2154 int i;
2155 for (i = 0; i < ARRAY_SIZE(lchan->sapis); ++i) {
2156 if (lchan->sapis[i] != LCHAN_SAPI_UNUSED) {
2157 LOGP(DRSL, LOGL_ERROR, "%s SAPI(%d) still allocated.\n",
2158 gsm_lchan_name(lchan), i);
2159 return -1;
2160 }
2161 }
2162
2163 /* Now release it */
2164 return rsl_rf_chan_release(lchan, 0, SACCH_NONE);
2165}