blob: 04d5c61b3dd0a47dd89715f36bf7944d1b9e6ee4 [file] [log] [blame]
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001/* GSM Radio Signalling Link messages on the A-bis interface
Harald Welte59b04682009-06-10 05:40:52 +08002 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Weltea22d36b2010-03-04 10:33:10 +01004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freythere38af682011-12-27 22:24:17 +01005 * (C) 2012 by Holger Hans Peter Freyther
Harald Welte59b04682009-06-10 05:40:52 +08006 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Welte59b04682009-06-10 05:40:52 +080012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte0e3e88e2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Welte59b04682009-06-10 05:40:52 +080018 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte59b04682009-06-10 05:40:52 +080021 *
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <errno.h>
Harald Welte59b04682009-06-10 05:40:52 +080027#include <netinet/in.h>
28#include <arpa/inet.h>
29
30#include <openbsc/gsm_data.h>
31#include <openbsc/gsm_04_08.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010032#include <osmocom/gsm/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080033#include <openbsc/abis_rsl.h>
34#include <openbsc/chan_alloc.h>
Harald Welteed9a5ab2009-08-09 13:47:35 +020035#include <openbsc/bsc_rll.h>
Harald Welte59b04682009-06-10 05:40:52 +080036#include <openbsc/debug.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010037#include <osmocom/gsm/tlv.h>
Harald Welte59b04682009-06-10 05:40:52 +080038#include <openbsc/paging.h>
39#include <openbsc/signal.h>
Harald Weltec20bd1d2009-11-29 19:07:28 +010040#include <openbsc/meas_rep.h>
Harald Welte50517742009-12-20 15:42:44 +010041#include <openbsc/rtp_proxy.h>
Pablo Neira Ayuso42e41df2011-08-17 22:44:07 +020042#include <osmocom/abis/e1_input.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010043#include <osmocom/gsm/rsl.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010044#include <osmocom/core/talloc.h>
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080045
Harald Welte59b04682009-06-10 05:40:52 +080046#define RSL_ALLOC_SIZE 1024
47#define RSL_ALLOC_HEADROOM 128
48
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080049static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
50
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010051static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
52 struct gsm_meas_rep *resp)
53{
54 struct lchan_signal_data sig;
55 sig.lchan = lchan;
56 sig.mr = resp;
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +020057 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010058}
59
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +010060static void do_lchan_free(struct gsm_lchan *lchan)
61{
62 /* we have an error timer pending to release that */
63 if (lchan->state != LCHAN_S_REL_ERR)
64 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
65 lchan_free(lchan);
66}
67
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020068static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080069{
70 /* mask off the transparent bit ? */
71 msg_type &= 0xfe;
72
73 if ((msg_type & 0xf0) == 0x00)
74 return ABIS_RSL_MDISC_RLL;
75 if ((msg_type & 0xf0) == 0x10) {
76 if (msg_type >= 0x19 && msg_type <= 0x22)
77 return ABIS_RSL_MDISC_TRX;
78 else
79 return ABIS_RSL_MDISC_COM_CHAN;
80 }
81 if ((msg_type & 0xe0) == 0x20)
82 return ABIS_RSL_MDISC_DED_CHAN;
83
84 return ABIS_RSL_MDISC_LOC;
85}
86
87static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020088 uint8_t msg_type)
Harald Welte59b04682009-06-10 05:40:52 +080089{
90 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
91 dh->c.msg_type = msg_type;
92 dh->ie_chan = RSL_IE_CHAN_NR;
93}
94
Harald Welte59b04682009-06-10 05:40:52 +080095/* determine logical channel based on TRX and channel number IE */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020096struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte59b04682009-06-10 05:40:52 +080097{
98 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020099 uint8_t ts_nr = chan_nr & 0x07;
100 uint8_t cbits = chan_nr >> 3;
101 uint8_t lch_idx;
Harald Welte59b04682009-06-10 05:40:52 +0800102 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
103
104 if (cbits == 0x01) {
105 lch_idx = 0; /* TCH/F */
Harald Welte37884ed2009-10-24 10:25:50 +0200106 if (ts->pchan != GSM_PCHAN_TCH_F &&
107 ts->pchan != GSM_PCHAN_PDCH &&
108 ts->pchan != GSM_PCHAN_TCH_F_PDCH)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100109 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800110 chan_nr, ts->pchan);
111 } else if ((cbits & 0x1e) == 0x02) {
112 lch_idx = cbits & 0x1; /* TCH/H */
113 if (ts->pchan != GSM_PCHAN_TCH_H)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100114 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800115 chan_nr, ts->pchan);
116 } else if ((cbits & 0x1c) == 0x04) {
117 lch_idx = cbits & 0x3; /* SDCCH/4 */
118 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100119 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800120 chan_nr, ts->pchan);
121 } else if ((cbits & 0x18) == 0x08) {
122 lch_idx = cbits & 0x7; /* SDCCH/8 */
123 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100124 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800125 chan_nr, ts->pchan);
126 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
127 lch_idx = 0;
128 if (ts->pchan != GSM_PCHAN_CCCH &&
129 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100130 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800131 chan_nr, ts->pchan);
132 /* FIXME: we should not return first sdcch4 !!! */
133 } else {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100134 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +0800135 return NULL;
136 }
137
138 lchan = &ts->lchan[lch_idx];
Harald Welte51d2a592010-03-26 21:28:59 +0800139 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther1a95fa82010-06-28 15:47:12 +0800140 if (lchan->conn)
141 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800142
143 return lchan;
144}
145
Harald Welte59b04682009-06-10 05:40:52 +0800146/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200147uint64_t str_to_imsi(const char *imsi_str)
Harald Welte59b04682009-06-10 05:40:52 +0800148{
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200149 uint64_t ret;
Harald Welte59b04682009-06-10 05:40:52 +0800150
151 ret = strtoull(imsi_str, NULL, 10);
152
153 return ret;
154}
155
Harald Welte59b04682009-06-10 05:40:52 +0800156static struct msgb *rsl_msgb_alloc(void)
157{
Harald Welte9cfc9352009-06-26 19:39:35 +0200158 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
159 "RSL");
Harald Welte59b04682009-06-10 05:40:52 +0800160}
161
162#define MACBLOCK_SIZE 23
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200163static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800164{
165 memcpy(out, in, len);
166
167 if (len < MACBLOCK_SIZE)
168 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
169}
170
Harald Welted2dd9de2009-08-30 15:37:11 +0900171/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200172static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welted2dd9de2009-08-30 15:37:11 +0900173{
174 *out++ = lchan->encr.alg_id & 0xff;
175 if (lchan->encr.key_len)
176 memcpy(out, lchan->encr.key, lchan->encr.key_len);
177 return lchan->encr.key_len + 1;
178}
179
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200180static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Weltef1a168d2009-07-28 17:58:09 +0200181{
Harald Welte59b04682009-06-10 05:40:52 +0800182 int i;
183
Harald Weltede4477a2009-12-24 12:20:20 +0100184 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Weltef1a168d2009-07-28 17:58:09 +0200185 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200186 for (i = 1; i < cause_len-1; i++)
Harald Weltede4477a2009-12-24 12:20:20 +0100187 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte59b04682009-06-10 05:40:52 +0800188}
189
Harald Welte32951ea2011-08-10 23:26:33 +0200190static void lchan_act_tmr_cb(void *data)
191{
192 struct gsm_lchan *lchan = data;
193
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100194 LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200195 gsm_lchan_name(lchan));
196
Daniel Willmann2731e732011-08-11 04:44:12 +0200197 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
198 lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200199}
200
201static void lchan_deact_tmr_cb(void *data)
202{
203 struct gsm_lchan *lchan = data;
204
Holger Hans Peter Freytherb050e3e2012-12-06 19:00:35 +0100205 LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
Harald Welte32951ea2011-08-10 23:26:33 +0200206 gsm_lchan_name(lchan));
207
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100208 do_lchan_free(lchan);
Harald Welte32951ea2011-08-10 23:26:33 +0200209}
210
211
Harald Welte59b04682009-06-10 05:40:52 +0800212/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200213int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
214 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800215{
216 struct abis_rsl_dchan_hdr *dh;
217 struct msgb *msg = rsl_msgb_alloc();
218
219 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
220 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
221 dh->chan_nr = RSL_CHAN_BCCH;
222
223 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
224 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
225
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200226 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800227
228 return abis_rsl_sendmsg(msg);
229}
230
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200231int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
232 const uint8_t *data, int len)
Harald Welte59b04682009-06-10 05:40:52 +0800233{
234 struct abis_rsl_common_hdr *ch;
235 struct msgb *msg = rsl_msgb_alloc();
236
237 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
238 ch->msg_discr = ABIS_RSL_MDISC_TRX;
239 ch->msg_type = RSL_MT_SACCH_FILL;
240
241 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
242 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
243
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200244 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800245
246 return abis_rsl_sendmsg(msg);
247}
248
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200249int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
250 const uint8_t *data, int len)
Harald Welte10b7d8f2011-01-13 23:16:03 +0100251{
252 struct abis_rsl_dchan_hdr *dh;
253 struct msgb *msg = rsl_msgb_alloc();
Harald Weltee6d51f92011-06-25 10:02:33 +0200254 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte10b7d8f2011-01-13 23:16:03 +0100255
256 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
257 init_dchan_hdr(dh, RSL_MT_SACCH_INFO_MODIFY);
258 dh->chan_nr = chan_nr;
259
260 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
261 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
262
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200263 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte10b7d8f2011-01-13 23:16:03 +0100264
265 return abis_rsl_sendmsg(msg);
266}
267
Harald Welte91afe4c2009-06-20 18:15:19 +0200268int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
269{
270 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200271 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200272 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200273
274 db = abs(db);
275 if (db > 30)
276 return -EINVAL;
277
Harald Welteed831842009-06-27 03:09:08 +0200278 msg = rsl_msgb_alloc();
279
Harald Welte91afe4c2009-06-20 18:15:19 +0200280 lchan->bs_power = db/2;
281 if (fpc)
282 lchan->bs_power |= 0x10;
283
284 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
285 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
286 dh->chan_nr = chan_nr;
287
288 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
289
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200290 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200291
292 return abis_rsl_sendmsg(msg);
293}
294
Harald Welte91afe4c2009-06-20 18:15:19 +0200295int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
296{
297 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200298 struct msgb *msg;
Harald Weltee6d51f92011-06-25 10:02:33 +0200299 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte91afe4c2009-06-20 18:15:19 +0200300 int ctl_lvl;
301
Harald Weltec4dcda02009-08-09 14:45:18 +0200302 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Welte91afe4c2009-06-20 18:15:19 +0200303 if (ctl_lvl < 0)
304 return ctl_lvl;
305
Harald Welteed831842009-06-27 03:09:08 +0200306 msg = rsl_msgb_alloc();
307
Harald Welte91afe4c2009-06-20 18:15:19 +0200308 lchan->ms_power = ctl_lvl;
309
310 if (fpc)
311 lchan->ms_power |= 0x20;
312
313 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
314 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
315 dh->chan_nr = chan_nr;
316
317 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
318
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200319 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte91afe4c2009-06-20 18:15:19 +0200320
321 return abis_rsl_sendmsg(msg);
322}
323
Harald Welte39274f42009-07-29 15:41:29 +0200324static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
325 struct gsm_lchan *lchan)
326{
327 memset(cm, 0, sizeof(cm));
328
329 /* FIXME: what to do with data calls ? */
Holger Hans Peter Freyther21d63ff2010-09-06 09:25:48 +0800330 if (lchan->ts->trx->bts->network->dtx_enabled)
331 cm->dtx_dtu = 0x03;
332 else
333 cm->dtx_dtu = 0x00;
Harald Welte39274f42009-07-29 15:41:29 +0200334
335 /* set TCH Speech/Data */
336 cm->spd_ind = lchan->rsl_cmode;
337
Harald Welte951e3512009-11-27 08:55:16 +0100338 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
339 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100340 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte951e3512009-11-27 08:55:16 +0100341 "but tch_mode != signalling\n");
342
Harald Welte39274f42009-07-29 15:41:29 +0200343 switch (lchan->type) {
344 case GSM_LCHAN_SDCCH:
345 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
346 break;
347 case GSM_LCHAN_TCH_F:
348 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
349 break;
350 case GSM_LCHAN_TCH_H:
351 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
352 break;
353 case GSM_LCHAN_NONE:
354 case GSM_LCHAN_UNKNOWN:
355 default:
356 return -EINVAL;
357 }
358
359 switch (lchan->tch_mode) {
360 case GSM48_CMODE_SIGN:
361 cm->chan_rate = 0;
362 break;
363 case GSM48_CMODE_SPEECH_V1:
364 cm->chan_rate = RSL_CMOD_SP_GSM1;
365 break;
366 case GSM48_CMODE_SPEECH_EFR:
367 cm->chan_rate = RSL_CMOD_SP_GSM2;
368 break;
369 case GSM48_CMODE_SPEECH_AMR:
370 cm->chan_rate = RSL_CMOD_SP_GSM3;
371 break;
372 case GSM48_CMODE_DATA_14k5:
Harald Welte39274f42009-07-29 15:41:29 +0200373 case GSM48_CMODE_DATA_12k0:
Harald Welte39274f42009-07-29 15:41:29 +0200374 case GSM48_CMODE_DATA_6k0:
Harald Weltee75a47d2012-08-24 15:33:56 +0200375 switch (lchan->csd_mode) {
376 case LCHAN_CSD_M_NT:
377 /* non-transparent CSD with RLP */
378 switch (lchan->tch_mode) {
379 case GSM48_CMODE_DATA_14k5:
380 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
381 break;
382 case GSM48_CMODE_DATA_12k0:
383 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
384 break;
385 case GSM48_CMODE_DATA_6k0:
386 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
387 break;
388 default:
389 return -EINVAL;
390 }
391 break;
392 /* transparent data services below */
393 case LCHAN_CSD_M_T_1200_75:
394 cm->chan_rate = RSL_CMOD_CSD_T_1200_75;
395 break;
396 case LCHAN_CSD_M_T_600:
397 cm->chan_rate = RSL_CMOD_CSD_T_600;
398 break;
399 case LCHAN_CSD_M_T_1200:
400 cm->chan_rate = RSL_CMOD_CSD_T_1200;
401 break;
402 case LCHAN_CSD_M_T_2400:
403 cm->chan_rate = RSL_CMOD_CSD_T_2400;
404 break;
405 case LCHAN_CSD_M_T_9600:
406 cm->chan_rate = RSL_CMOD_CSD_T_9600;
407 break;
408 case LCHAN_CSD_M_T_14400:
409 cm->chan_rate = RSL_CMOD_CSD_T_14400;
410 break;
411 case LCHAN_CSD_M_T_29000:
412 cm->chan_rate = RSL_CMOD_CSD_T_29000;
413 break;
414 case LCHAN_CSD_M_T_32000:
415 cm->chan_rate = RSL_CMOD_CSD_T_32000;
416 break;
417 default:
418 return -EINVAL;
419 }
Harald Welte39274f42009-07-29 15:41:29 +0200420 default:
421 return -EINVAL;
422 }
423
424 return 0;
425}
426
Harald Welte59b04682009-06-10 05:40:52 +0800427/* Chapter 8.4.1 */
428#if 0
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200429int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
430 uint8_t act_type,
Harald Welte59b04682009-06-10 05:40:52 +0800431 struct rsl_ie_chan_mode *chan_mode,
432 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200433 uint8_t bs_power, uint8_t ms_power,
434 uint8_t ta)
Harald Welte59b04682009-06-10 05:40:52 +0800435{
436 struct abis_rsl_dchan_hdr *dh;
437 struct msgb *msg = rsl_msgb_alloc();
438
439 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
440 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
441 dh->chan_nr = chan_nr;
442
443 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
444 /* For compatibility with Phase 1 */
445 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200446 (uint8_t *) chan_mode);
Harald Welte59b04682009-06-10 05:40:52 +0800447 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200448 (uint8_t *) chan_ident);
Harald Welte59b04682009-06-10 05:40:52 +0800449#if 0
450 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200451 (uint8_t *) &encr_info);
Harald Welte59b04682009-06-10 05:40:52 +0800452#endif
453 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
454 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
455 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
456
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200457 msg->dst = trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800458
459 return abis_rsl_sendmsg(msg);
460}
461#endif
462
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200463int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
464 uint8_t ta, uint8_t ho_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800465{
466 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200467 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200468 int rc;
Harald Weltedea24e92010-06-29 17:53:45 +0200469 uint8_t *len;
Harald Welte59b04682009-06-10 05:40:52 +0800470
Harald Weltee6d51f92011-06-25 10:02:33 +0200471 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800472 struct rsl_ie_chan_mode cm;
laforgef723cf02010-06-20 21:38:19 +0200473 struct gsm48_chan_desc cd;
Harald Welte59b04682009-06-10 05:40:52 +0800474
Harald Welte39274f42009-07-29 15:41:29 +0200475 rc = channel_mode_from_lchan(&cm, lchan);
476 if (rc < 0)
477 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800478
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800479 memset(&cd, 0, sizeof(cd));
laforgef723cf02010-06-20 21:38:19 +0200480 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800481
Harald Welteed831842009-06-27 03:09:08 +0200482 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800483 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
484 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
485 dh->chan_nr = chan_nr;
486
487 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte59b04682009-06-10 05:40:52 +0800488 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200489 (uint8_t *) &cm);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800490
491 /*
492 * The Channel Identification is needed for Phase1 phones
493 * and it contains the GSM48 Channel Description and the
494 * Mobile Allocation. The GSM 08.58 asks for the Mobile
495 * Allocation to have a length of zero. We are using the
496 * msgb_l3len to calculate the length of both messages.
497 */
laforgef723cf02010-06-20 21:38:19 +0200498 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Weltedea24e92010-06-29 17:53:45 +0200499 len = msgb_put(msg, 1);
Dieter Spaar18a55f62011-07-27 23:40:33 +0200500 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther4cab4422010-06-30 12:06:20 +0800501
502 if (lchan->ts->hopping.enabled)
503 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
504 lchan->ts->hopping.ma_data);
505 else
506 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800507
508 /* update the calculated size */
509 msg->l3h = len + 1;
510 *len = msgb_l3len(msg);
511
Harald Welted2dd9de2009-08-30 15:37:11 +0900512 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200513 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900514 rc = build_encr_info(encr_info, lchan);
515 if (rc > 0)
516 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
517 }
518
Harald Welteb90d7bd2009-12-17 00:31:10 +0100519 switch (act_type) {
520 case RSL_ACT_INTER_ASYNC:
521 case RSL_ACT_INTER_SYNC:
522 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
523 break;
524 default:
525 break;
526 }
527
Harald Welte59b04682009-06-10 05:40:52 +0800528 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
529 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
530 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
531
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100532 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
533 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200534 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100535
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200536 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800537
538 return abis_rsl_sendmsg(msg);
539}
540
Harald Welte8e770492009-07-29 11:38:15 +0200541/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welte59b04682009-06-10 05:40:52 +0800542int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
543{
544 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200545 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200546 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800547
Harald Weltee6d51f92011-06-25 10:02:33 +0200548 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800549 struct rsl_ie_chan_mode cm;
550
Harald Welte39274f42009-07-29 15:41:29 +0200551 rc = channel_mode_from_lchan(&cm, lchan);
552 if (rc < 0)
553 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800554
Harald Welteed831842009-06-27 03:09:08 +0200555 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800556 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
557 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
558 dh->chan_nr = chan_nr;
559
560 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200561 (uint8_t *) &cm);
Harald Welted2dd9de2009-08-30 15:37:11 +0900562
563 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200564 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welted2dd9de2009-08-30 15:37:11 +0900565 rc = build_encr_info(encr_info, lchan);
566 if (rc > 0)
567 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
568 }
569
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100570 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
571 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200572 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100573 }
574
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200575 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dd9de2009-08-30 15:37:11 +0900576
577 return abis_rsl_sendmsg(msg);
578}
579
580/* Chapter 8.4.6: Send the encryption command with given L3 info */
581int rsl_encryption_cmd(struct msgb *msg)
582{
583 struct abis_rsl_dchan_hdr *dh;
584 struct gsm_lchan *lchan = msg->lchan;
Harald Weltee6d51f92011-06-25 10:02:33 +0200585 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200586 uint8_t encr_info[MAX_A5_KEY_LEN+2];
587 uint8_t l3_len = msg->len;
Harald Welted2dd9de2009-08-30 15:37:11 +0900588 int rc;
589
590 /* First push the L3 IE tag and length */
591 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
592
593 /* then the link identifier (SAPI0, main sign link) */
594 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
595
596 /* then encryption information */
597 rc = build_encr_info(encr_info, lchan);
598 if (rc <= 0)
599 return rc;
600 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
601
602 /* and finally the DCHAN header */
603 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
604 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
605 dh->chan_nr = chan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800606
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200607 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800608
609 return abis_rsl_sendmsg(msg);
610}
611
Harald Welte85a163c2009-08-10 11:43:22 +0200612/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteafe3c232009-07-19 18:36:49 +0200613int rsl_deact_sacch(struct gsm_lchan *lchan)
614{
615 struct abis_rsl_dchan_hdr *dh;
616 struct msgb *msg = rsl_msgb_alloc();
617
618 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
619 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
Harald Weltee6d51f92011-06-25 10:02:33 +0200620 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteafe3c232009-07-19 18:36:49 +0200621
622 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200623 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteafe3c232009-07-19 18:36:49 +0200624
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100625 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteafe3c232009-07-19 18:36:49 +0200626
627 return abis_rsl_sendmsg(msg);
628}
629
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800630static void error_timeout_cb(void *data)
631{
632 struct gsm_lchan *lchan = data;
633 if (lchan->state != LCHAN_S_REL_ERR) {
634 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
635 gsm_lchan_name(lchan), lchan->state);
636 return;
637 }
638
639 /* go back to the none state */
640 LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800641 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800642}
643
Harald Welte08011e22011-03-04 13:41:31 +0100644static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
645
Harald Welte85a163c2009-08-10 11:43:22 +0200646/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800647static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte59b04682009-06-10 05:40:52 +0800648{
649 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800650 struct msgb *msg;
Harald Welte08011e22011-03-04 13:41:31 +0100651 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800652
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800653 if (lchan->state == LCHAN_S_REL_ERR) {
654 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
655 gsm_lchan_name(lchan));
656 return -1;
657 }
658
659 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800660 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
661 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltee6d51f92011-06-25 10:02:33 +0200662 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800663
664 msg->lchan = lchan;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200665 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800666
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800667 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
668
669 if (error) {
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200670 struct e1inp_sign_link *sign_link = msg->dst;
671
Holger Hans Peter Freyther701a6472011-12-28 12:11:40 +0100672 /*
673 * FIXME: GSM 04.08 gives us two options for the abnormal
674 * chanel release. This can be either like in the non-existent
675 * sub-lcuase 3.5.1 or for the main signalling link deactivate
676 * the SACCH, start timer T3109 and consider the channel as
677 * released.
678 *
679 * This code is doing the later for all raido links and not
680 * only the main link. Right now all SAPIs are released on the
681 * local end, the SACCH will be de-activated and right now the
682 * T3111 will be started. First T3109 should be started and then
683 * the T3111.
684 *
685 * TODO: Move this out of the function.
686 */
687
688 /*
689 * sacch de-activate and "local end release"
690 */
691 rsl_deact_sacch(lchan);
692 rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END);
693
694 /*
695 * TODO: start T3109 now.
696 */
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800697 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800698 lchan->error_timer.data = lchan;
699 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200700 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200701 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800702 }
Harald Welte59b04682009-06-10 05:40:52 +0800703
Harald Welte32951ea2011-08-10 23:26:33 +0200704 /* Start another timer or assume the BTS sends a ACK/NACK? */
705 lchan->act_timer.cb = lchan_deact_tmr_cb;
706 lchan->act_timer.data = lchan;
707 osmo_timer_schedule(&lchan->act_timer, 4, 0);
708
Harald Welte08011e22011-03-04 13:41:31 +0100709 rc = abis_rsl_sendmsg(msg);
710
Harald Welte85a163c2009-08-10 11:43:22 +0200711 /* BTS will respond by RF CHAN REL ACK */
Harald Welte6bddd822011-01-14 23:18:59 +0100712#ifdef HSL_SR_1_0
Harald Welte08011e22011-03-04 13:41:31 +0100713 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
714 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
715 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte6bddd822011-01-14 23:18:59 +0100716#endif
Harald Welte08011e22011-03-04 13:41:31 +0100717
718 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800719}
720
Harald Welte9773f6c2011-01-14 14:16:16 +0100721static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
722{
723
724 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
725
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100726 /* Stop all pending timers */
Harald Welte32951ea2011-08-10 23:26:33 +0200727 osmo_timer_del(&lchan->act_timer);
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100728 osmo_timer_del(&lchan->T3111);
Harald Welte32951ea2011-08-10 23:26:33 +0200729
Harald Welte9773f6c2011-01-14 14:16:16 +0100730 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
731 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
732 gsm_lchan_name(lchan),
733 gsm_lchans_name(lchan->state));
Holger Hans Peter Freytherc22f2992012-12-06 19:09:58 +0100734 do_lchan_free(lchan);
Harald Welte9773f6c2011-01-14 14:16:16 +0100735
736 return 0;
737}
738
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200739int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
740 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte59b04682009-06-10 05:40:52 +0800741{
742 struct abis_rsl_dchan_hdr *dh;
743 struct msgb *msg = rsl_msgb_alloc();
744
745 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
746 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
747 dh->chan_nr = RSL_CHAN_PCH_AGCH;
748
749 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
750 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
751 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
752
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200753 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800754
755 return abis_rsl_sendmsg(msg);
756}
757
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200758int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte59b04682009-06-10 05:40:52 +0800759{
760 int i, len = strlen(str_in);
761
762 for (i = 0; i < len; i++) {
763 int num = str_in[i] - 0x30;
764 if (num < 0 || num > 9)
765 return -1;
766 if (i % 2 == 0)
767 bcd_out[i/2] = num;
768 else
769 bcd_out[i/2] |= (num << 4);
770 }
771
772 return 0;
773}
774
775/* Chapter 8.5.6 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200776int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte59b04682009-06-10 05:40:52 +0800777{
778 struct msgb *msg = rsl_msgb_alloc();
779 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200780 uint8_t buf[MACBLOCK_SIZE];
Harald Welte59b04682009-06-10 05:40:52 +0800781
782 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
783 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
784 dh->chan_nr = RSL_CHAN_PCH_AGCH;
785
786 switch (bts->type) {
787 case GSM_BTS_TYPE_BS11:
788 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
789 break;
790 default:
791 /* If phase 2, construct a FULL_IMM_ASS_INFO */
792 pad_macblock(buf, val, len);
793 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
794 break;
795 }
796
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200797 msg->dst = bts->c0->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800798
799 return abis_rsl_sendmsg(msg);
800}
801
Harald Welte4684e632009-08-10 09:51:40 +0200802/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte12090752009-08-10 10:07:33 +0200803int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte4684e632009-08-10 09:51:40 +0200804{
805 struct msgb *msg = rsl_msgb_alloc();
806 struct abis_rsl_dchan_hdr *dh;
807
808 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
809 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte874a5b42009-08-10 11:26:14 +0200810 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +0200811 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200812 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte4684e632009-08-10 09:51:40 +0200813
Harald Weltede4477a2009-12-24 12:20:20 +0100814 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200815 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte874a5b42009-08-10 11:26:14 +0200816
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200817 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte874a5b42009-08-10 11:26:14 +0200818
Harald Welte4684e632009-08-10 09:51:40 +0200819 return abis_rsl_sendmsg(msg);
820}
821
822
Harald Welte59b04682009-06-10 05:40:52 +0800823/* Send "DATA REQUEST" message with given L3 Info payload */
824/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200825int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800826{
Harald Welte59b04682009-06-10 05:40:52 +0800827 if (msg->lchan == NULL) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100828 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte59b04682009-06-10 05:40:52 +0800829 return -EINVAL;
830 }
831
Harald Weltee6d51f92011-06-25 10:02:33 +0200832 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100833 link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800834
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200835 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +0800836
837 return abis_rsl_sendmsg(msg);
838}
839
Harald Welteed9a5ab2009-08-09 13:47:35 +0200840/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
841/* Chapter 8.3.1 */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200842int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteed9a5ab2009-08-09 13:47:35 +0200843{
Harald Weltea22d36b2010-03-04 10:33:10 +0100844 struct msgb *msg;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200845
Harald Weltee6d51f92011-06-25 10:02:33 +0200846 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100847 link_id, 0);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200848 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200849
Harald Welte17091bd2012-04-26 19:42:19 +0200850 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
851 gsm_lchan_name(lchan), link_id);
852
Harald Welteed9a5ab2009-08-09 13:47:35 +0200853 return abis_rsl_sendmsg(msg);
854}
855
Harald Welte0f2e3c12009-08-08 13:15:07 +0200856/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
857 This is what higher layers should call. The BTS then responds with
858 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
859 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
860 lchan_free() */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100861int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
862 enum rsl_rel_mode release_mode)
Harald Welte0f2e3c12009-08-08 13:15:07 +0200863{
Harald Welte0f2e3c12009-08-08 13:15:07 +0200864
Harald Weltea22d36b2010-03-04 10:33:10 +0100865 struct msgb *msg;
866
Harald Weltee6d51f92011-06-25 10:02:33 +0200867 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Weltea22d36b2010-03-04 10:33:10 +0100868 link_id, 0);
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800869 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100870 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welte0f2e3c12009-08-08 13:15:07 +0200871
Harald Weltec88a4432009-12-29 10:44:17 +0100872 /* FIXME: start some timer in case we don't receive a REL ACK ? */
873
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +0200874 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte0f2e3c12009-08-08 13:15:07 +0200875
Harald Welte17091bd2012-04-26 19:42:19 +0200876 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther2806c792012-12-06 12:01:38 +0100877 gsm_lchan_name(lchan), link_id, release_mode);
Harald Welte17091bd2012-04-26 19:42:19 +0200878
Harald Welte0f2e3c12009-08-08 13:15:07 +0200879 return abis_rsl_sendmsg(msg);
880}
881
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200882int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
883{
884 lchan->state = state;
885 return 0;
886}
887
Harald Welte59b04682009-06-10 05:40:52 +0800888/* Chapter 8.4.2: Channel Activate Acknowledge */
889static int rsl_rx_chan_act_ack(struct msgb *msg)
890{
891 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
892
893 /* BTS has confirmed channel activation, we now need
894 * to assign the activated channel to the MS */
895 if (rslh->ie_chan != RSL_IE_CHAN_NR)
896 return -EINVAL;
Harald Welte6720a432009-11-29 22:45:52 +0100897
Harald Welte32951ea2011-08-10 23:26:33 +0200898 osmo_timer_del(&msg->lchan->act_timer);
899
Harald Weltec88a4432009-12-29 10:44:17 +0100900 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welteab2534c2009-12-29 10:52:38 +0100901 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
902 gsm_lchan_name(msg->lchan),
903 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200904 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welte4baa9c52009-12-21 13:27:11 +0100905
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +0800906 if (msg->lchan->rqd_ref) {
907 rsl_send_imm_assignment(msg->lchan);
908 talloc_free(msg->lchan->rqd_ref);
909 msg->lchan->rqd_ref = NULL;
910 msg->lchan->rqd_ta = 0;
911 }
912
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100913 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100914
Harald Welte59b04682009-06-10 05:40:52 +0800915 return 0;
916}
917
918/* Chapter 8.4.3: Channel Activate NACK */
919static int rsl_rx_chan_act_nack(struct msgb *msg)
920{
921 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
922 struct tlv_parsed tp;
923
Harald Welte32951ea2011-08-10 23:26:33 +0200924 osmo_timer_del(&msg->lchan->act_timer);
925
Daniel Willmann9e9d44c2011-08-11 04:54:23 +0200926 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100927 gsm_lchan_name(msg->lchan));
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100928
Harald Welte59b04682009-06-10 05:40:52 +0800929 /* BTS has rejected channel activation ?!? */
930 if (dh->ie_chan != RSL_IE_CHAN_NR)
931 return -EINVAL;
932
933 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100934 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200935 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100936 print_rsl_cause(LOGL_ERROR, cause,
Harald Weltef1a168d2009-07-28 17:58:09 +0200937 TLVP_LEN(&tp, RSL_IE_CAUSE));
Holger Hans Peter Freyther5149c172012-12-06 19:25:06 +0100938 msg->lchan->error_cause = *cause;
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100939 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther5149c172012-12-06 19:25:06 +0100940 rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
Daniel Willmann245ee032011-08-11 04:47:11 +0200941 else
942 rsl_rf_chan_release(msg->lchan, 1);
943
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100944 } else
Holger Hans Peter Freyther5149c172012-12-06 19:25:06 +0100945 rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200946
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100947 LOGPC(DRSL, LOGL_ERROR, "\n");
948
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100949 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte59b04682009-06-10 05:40:52 +0800950 return 0;
951}
952
953/* Chapter 8.4.4: Connection Failure Indication */
954static int rsl_rx_conn_fail(struct msgb *msg)
955{
956 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
957 struct tlv_parsed tp;
958
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100959 /* FIXME: print which channel */
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100960 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100961 gsm_lchan_name(msg->lchan));
Harald Welte59b04682009-06-10 05:40:52 +0800962
963 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
964
Harald Weltef1a168d2009-07-28 17:58:09 +0200965 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +0100966 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +0200967 TLVP_LEN(&tp, RSL_IE_CAUSE));
968
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100969 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte59b04682009-06-10 05:40:52 +0800970 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200971 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800972 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800973}
974
Harald Weltec20bd1d2009-11-29 19:07:28 +0100975static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
976 const char *prefix)
977{
Harald Welte0e4fa782009-12-16 16:52:07 +0100978 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
979 prefix, rxlev2dbm(mru->full.rx_lev),
980 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Weltec20bd1d2009-11-29 19:07:28 +0100981 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
982 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
983}
984
Harald Welte50290cc2012-07-02 17:12:08 +0200985static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Weltec20bd1d2009-11-29 19:07:28 +0100986{
Harald Welte0e4fa782009-12-16 16:52:07 +0100987 int i;
Harald Welte50290cc2012-07-02 17:12:08 +0200988 char *name = "";
Harald Welte0e4fa782009-12-16 16:52:07 +0100989
Harald Welte50290cc2012-07-02 17:12:08 +0200990 if (lchan && lchan->conn && lchan->conn->subscr)
991 name = subscr_name(lchan->conn->subscr);
992
993 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100994
995 if (mr->flags & MEAS_REP_F_DL_DTX)
996 DEBUGPC(DMEAS, "DTXd ");
997
998 print_meas_rep_uni(&mr->ul, "ul");
999 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
1000 if (mr->flags & MEAS_REP_F_MS_TO)
1001 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
1002
1003 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte0e4fa782009-12-16 16:52:07 +01001004 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001005 DEBUGPC(DMEAS, "L1_FPC=%u ",
1006 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
1007 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
1008 }
1009
1010 if (mr->flags & MEAS_REP_F_UL_DTX)
1011 DEBUGPC(DMEAS, "DTXu ");
1012 if (mr->flags & MEAS_REP_F_BA1)
1013 DEBUGPC(DMEAS, "BA1 ");
1014 if (!(mr->flags & MEAS_REP_F_DL_VALID))
1015 DEBUGPC(DMEAS, "NOT VALID ");
1016 else
1017 print_meas_rep_uni(&mr->dl, "dl");
1018
1019 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte0b833f82009-12-19 18:33:05 +01001020 if (mr->num_cell == 7)
1021 return;
Harald Welte0e4fa782009-12-16 16:52:07 +01001022 for (i = 0; i < mr->num_cell; i++) {
1023 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte350c2d32009-12-25 23:02:22 +01001024 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1025 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte0e4fa782009-12-16 16:52:07 +01001026 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001027}
1028
Harald Welte59b04682009-06-10 05:40:52 +08001029static int rsl_rx_meas_res(struct msgb *msg)
1030{
1031 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1032 struct tlv_parsed tp;
Harald Weltef9476812009-12-15 21:36:05 +01001033 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001034 uint8_t len;
1035 const uint8_t *val;
Harald Weltec20bd1d2009-11-29 19:07:28 +01001036 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001037
Harald Welte4baa9c52009-12-21 13:27:11 +01001038 /* check if this channel is actually active */
1039 /* FIXME: maybe this check should be way more generic/centralized */
Harald Weltec88a4432009-12-29 10:44:17 +01001040 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freyther67a2e292010-07-29 14:50:57 +08001041 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Weltec88a4432009-12-29 10:44:17 +01001042 gsm_lchan_name(msg->lchan));
Harald Welte4baa9c52009-12-21 13:27:11 +01001043 return 0;
Harald Weltec88a4432009-12-29 10:44:17 +01001044 }
Harald Welte4baa9c52009-12-21 13:27:11 +01001045
Harald Weltef9476812009-12-15 21:36:05 +01001046 memset(mr, 0, sizeof(*mr));
Harald Welteaa0efa12009-12-16 23:29:34 +01001047 mr->lchan = msg->lchan;
Harald Welte4efcc542009-11-30 19:16:47 +01001048
Harald Welte59b04682009-06-10 05:40:52 +08001049 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1050
Harald Weltec20bd1d2009-11-29 19:07:28 +01001051 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1052 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1053 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1054 return -EIO;
1055
1056 /* Mandatory Parts */
Harald Weltef9476812009-12-15 21:36:05 +01001057 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001058
1059 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1060 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1061 if (len >= 3) {
1062 if (val[0] & 0x40)
Harald Weltef9476812009-12-15 21:36:05 +01001063 mr->flags |= MEAS_REP_F_DL_DTX;
1064 mr->ul.full.rx_lev = val[0] & 0x3f;
1065 mr->ul.sub.rx_lev = val[1] & 0x3f;
1066 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1067 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte59b04682009-06-10 05:40:52 +08001068 }
Harald Weltec20bd1d2009-11-29 19:07:28 +01001069
Harald Weltef9476812009-12-15 21:36:05 +01001070 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001071
1072 /* Optional Parts */
Harald Welte59b04682009-06-10 05:40:52 +08001073 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Weltef9476812009-12-15 21:36:05 +01001074 mr->ms_timing_offset =
Harald Weltec20bd1d2009-11-29 19:07:28 +01001075 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1076
Harald Weltea1467eb2009-06-20 18:44:35 +02001077 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001078 struct e1inp_sign_link *sign_link = msg->dst;
1079
Harald Weltec20bd1d2009-11-29 19:07:28 +01001080 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001081 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001082 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001083 if (val[0] & 0x04)
Harald Weltef9476812009-12-15 21:36:05 +01001084 mr->flags |= MEAS_REP_F_FPC;
1085 mr->ms_l1.ta = val[1];
Andreas Eversbergfe56cf82011-12-24 11:49:05 +01001086 /* BS11 and Nokia reports TA shifted by 2 bits */
1087 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1088 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001089 mr->ms_l1.ta >>= 2;
Harald Weltea1467eb2009-06-20 18:44:35 +02001090 }
Harald Welte59b04682009-06-10 05:40:52 +08001091 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001092 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Weltef9476812009-12-15 21:36:05 +01001093 rc = gsm48_parse_meas_rep(mr, msg);
Harald Weltec20bd1d2009-11-29 19:07:28 +01001094 if (rc < 0)
1095 return rc;
1096 }
1097
Harald Welte50290cc2012-07-02 17:12:08 +02001098 print_meas_rep(msg->lchan, mr);
Harald Welte59b04682009-06-10 05:40:52 +08001099
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001100 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Welte4efcc542009-11-30 19:16:47 +01001101
Harald Welte59b04682009-06-10 05:40:52 +08001102 return 0;
1103}
1104
Harald Welte6720a432009-11-29 22:45:52 +01001105/* Chapter 8.4.7 */
1106static int rsl_rx_hando_det(struct msgb *msg)
1107{
1108 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1109 struct tlv_parsed tp;
1110
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001111 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welte6720a432009-11-29 22:45:52 +01001112
1113 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1114
1115 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1116 DEBUGPC(DRSL, "access delay = %u\n",
1117 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1118 else
1119 DEBUGPC(DRSL, "\n");
1120
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001121 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +01001122
1123 return 0;
1124}
1125
Harald Welte59b04682009-06-10 05:40:52 +08001126static int abis_rsl_rx_dchan(struct msgb *msg)
1127{
1128 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1129 int rc = 0;
1130 char *ts_name;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001131 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001132
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001133 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001134 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001135
Harald Welte59b04682009-06-10 05:40:52 +08001136 switch (rslh->c.msg_type) {
1137 case RSL_MT_CHAN_ACTIV_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001138 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001139 rc = rsl_rx_chan_act_ack(msg);
1140 break;
1141 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001142 rc = rsl_rx_chan_act_nack(msg);
1143 break;
1144 case RSL_MT_CONN_FAIL:
1145 rc = rsl_rx_conn_fail(msg);
1146 break;
1147 case RSL_MT_MEAS_RES:
1148 rc = rsl_rx_meas_res(msg);
1149 break;
Harald Welte6720a432009-11-29 22:45:52 +01001150 case RSL_MT_HANDO_DET:
1151 rc = rsl_rx_hando_det(msg);
1152 break;
Harald Welte59b04682009-06-10 05:40:52 +08001153 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte9773f6c2011-01-14 14:16:16 +01001154 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001155 break;
1156 case RSL_MT_MODE_MODIFY_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001157 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001158 break;
1159 case RSL_MT_MODE_MODIFY_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001160 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001161 break;
Harald Welteaed946e2009-10-24 10:29:22 +02001162 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001163 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001164 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001165 break;
1166 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001167 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001168 break;
1169 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001170 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001171 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001172 break;
1173 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001174 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001175 break;
Harald Welte59b04682009-06-10 05:40:52 +08001176 case RSL_MT_PHY_CONTEXT_CONF:
1177 case RSL_MT_PREPROC_MEAS_RES:
1178 case RSL_MT_TALKER_DET:
1179 case RSL_MT_LISTENER_DET:
1180 case RSL_MT_REMOTE_CODEC_CONF_REP:
1181 case RSL_MT_MR_CODEC_MOD_ACK:
1182 case RSL_MT_MR_CODEC_MOD_NACK:
1183 case RSL_MT_MR_CODEC_MOD_PER:
Harald Weltede4477a2009-12-24 12:20:20 +01001184 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1185 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001186 break;
1187 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001188 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1189 ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001190 return -EINVAL;
1191 }
1192
1193 return rc;
1194}
1195
1196static int rsl_rx_error_rep(struct msgb *msg)
1197{
1198 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Weltef1a168d2009-07-28 17:58:09 +02001199 struct tlv_parsed tp;
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001200 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001201
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001202 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Weltef1a168d2009-07-28 17:58:09 +02001203
1204 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1205
1206 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001207 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001208 TLVP_LEN(&tp, RSL_IE_CAUSE));
1209
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001210 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001211
1212 return 0;
1213}
1214
1215static int abis_rsl_rx_trx(struct msgb *msg)
1216{
1217 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001218 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001219 int rc = 0;
1220
1221 switch (rslh->msg_type) {
1222 case RSL_MT_ERROR_REPORT:
1223 rc = rsl_rx_error_rep(msg);
1224 break;
1225 case RSL_MT_RF_RES_IND:
1226 /* interference on idle channels of TRX */
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001227 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001228 break;
1229 case RSL_MT_OVERLOAD:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001230 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001231 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001232 gsm_trx_name(sign_link->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001233 break;
Dieter Spaar49c843e2011-07-28 00:01:50 +02001234 case 0x42: /* Nokia specific: SI End ACK */
1235 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1236 break;
1237 case 0x43: /* Nokia specific: SI End NACK */
1238 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1239 break;
Harald Welte59b04682009-06-10 05:40:52 +08001240 default:
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001241 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001242 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001243 return -EINVAL;
1244 }
1245 return rc;
1246}
1247
Harald Welte427dbc42009-08-10 00:26:10 +02001248/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1249static void t3101_expired(void *data)
1250{
1251 struct gsm_lchan *lchan = data;
1252
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001253 rsl_rf_chan_release(lchan, 1);
Harald Welte427dbc42009-08-10 00:26:10 +02001254}
1255
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001256/* If T3111 expires, we will send the RF Channel Request */
1257static void t3111_expired(void *data)
1258{
1259 struct gsm_lchan *lchan = data;
1260
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001261 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001262}
1263
laforge50312e82010-06-21 12:08:52 +02001264#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1265
Harald Weltea00fdd72010-12-23 14:39:29 +01001266/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1267static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1268 unsigned int num_req_refs,
1269 struct gsm48_req_ref *rqd_refs,
1270 uint8_t wait_ind)
1271{
1272 uint8_t buf[GSM_MACBLOCK_LEN];
1273 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1274
1275 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1276 memset(iar, 0, sizeof(*iar));
1277 iar->proto_discr = GSM48_PDISC_RR;
1278 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1279 iar->page_mode = GSM48_PM_SAME;
1280
1281 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1282 iar->wait_ind1 = wait_ind;
1283
1284 if (num_req_refs >= 2)
1285 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1286 else
1287 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1288 iar->wait_ind2 = wait_ind;
1289
1290 if (num_req_refs >= 3)
1291 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1292 else
1293 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1294 iar->wait_ind3 = wait_ind;
1295
1296 if (num_req_refs >= 4)
1297 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1298 else
1299 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1300 iar->wait_ind4 = wait_ind;
1301
1302 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1303}
1304
Harald Welte59b04682009-06-10 05:40:52 +08001305/* MS has requested a channel on the RACH */
1306static int rsl_rx_chan_rqd(struct msgb *msg)
1307{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001308 struct e1inp_sign_link *sign_link = msg->dst;
1309 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +08001310 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1311 struct gsm48_req_ref *rqd_ref;
Harald Welte59b04682009-06-10 05:40:52 +08001312 enum gsm_chan_t lctype;
1313 enum gsm_chreq_reason_t chreq_reason;
1314 struct gsm_lchan *lchan;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001315 uint8_t rqd_ta;
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001316 int is_lu;
Harald Welte59b04682009-06-10 05:40:52 +08001317
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001318 uint16_t arfcn;
Holger Hans Peter Freytherefd75b52012-02-03 20:10:13 +01001319 uint8_t subch;
Harald Welte59b04682009-06-10 05:40:52 +08001320
1321 /* parse request reference to be used in immediate assign */
1322 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1323 return -EINVAL;
1324
1325 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1326
1327 /* parse access delay and use as TA */
1328 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1329 return -EINVAL;
1330 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1331
1332 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1333 * request reference RA */
Holger Hans Peter Freytherf0f37f12010-09-06 09:36:02 +08001334 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1335 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte59b04682009-06-10 05:40:52 +08001336
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001337 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte3edc5a92009-12-22 00:41:05 +01001338
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001339 /*
1340 * We want LOCATION UPDATES to succeed and will assign a TCH
1341 * if we have no SDCCH available.
1342 */
1343 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1344
Harald Welte59b04682009-06-10 05:40:52 +08001345 /* check availability / allocate channel */
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001346 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte59b04682009-06-10 05:40:52 +08001347 if (!lchan) {
Harald Welte (local)e0bb5fa2009-12-27 13:48:09 +01001348 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)02204d02009-12-27 18:05:25 +01001349 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001350 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Weltea00fdd72010-12-23 14:39:29 +01001351 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1352 if (bts->network->T3122)
1353 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte59b04682009-06-10 05:40:52 +08001354 return -ENOMEM;
1355 }
1356
Harald Weltec88a4432009-12-29 10:44:17 +01001357 if (lchan->state != LCHAN_S_NONE)
1358 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welteab2534c2009-12-29 10:52:38 +01001359 "in state %s\n", gsm_lchan_name(lchan),
1360 gsm_lchans_name(lchan->state));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +01001361
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001362 /* save the RACH data as we need it after the CHAN ACT ACK */
1363 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1364 if (!lchan->rqd_ref) {
1365 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1366 lchan_free(lchan);
1367 return -ENOMEM;
1368 }
1369
Holger Hans Peter Freyther161cec12011-12-29 23:33:04 +01001370 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001371 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1372 lchan->rqd_ta = rqd_ta;
1373
Harald Welte59b04682009-06-10 05:40:52 +08001374 arfcn = lchan->ts->trx->arfcn;
1375 subch = lchan->nr;
1376
Harald Welted2dd9de2009-08-30 15:37:11 +09001377 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)cbd46102009-08-13 10:14:26 +02001378 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte9a229e12009-08-10 00:45:40 +02001379 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte39274f42009-07-29 15:41:29 +02001380 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte77234e12009-08-28 23:28:28 +09001381 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001382
Harald Welte32951ea2011-08-10 23:26:33 +02001383 /* Start another timer or assume the BTS sends a ACK/NACK? */
1384 lchan->act_timer.cb = lchan_act_tmr_cb;
1385 lchan->act_timer.data = lchan;
1386 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1387
Andreas Eversberg0f18e5e2011-12-16 17:45:37 +01001388 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1389 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1390 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1391 rqd_ref->ra, rqd_ta);
1392
1393 /* BS11 requires TA shifted by 2 bits */
1394 if (bts->type == GSM_BTS_TYPE_BS11)
1395 rqd_ta <<= 2;
Harald Welteb90d7bd2009-12-17 00:31:10 +01001396 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001397
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001398 return 0;
1399}
1400
1401static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1402{
1403 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001404 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001405 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1406
Harald Welte59b04682009-06-10 05:40:52 +08001407 /* create IMMEDIATE ASSIGN 04.08 messge */
laforgee06d5982010-06-20 15:18:46 +02001408 memset(ia, 0, sizeof(*ia));
laforge50312e82010-06-21 12:08:52 +02001409 /* we set ia->l2_plen once we know the length of the MA below */
laforgee06d5982010-06-20 15:18:46 +02001410 ia->proto_discr = GSM48_PDISC_RR;
1411 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1412 ia->page_mode = GSM48_PM_SAME;
1413 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea42a93f2010-06-14 22:26:10 +02001414
Harald Welte59b04682009-06-10 05:40:52 +08001415 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001416 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1417 ia->timing_advance = lchan->rqd_ta;
Harald Weltea42a93f2010-06-14 22:26:10 +02001418 if (!lchan->ts->hopping.enabled) {
laforgee06d5982010-06-20 15:18:46 +02001419 ia->mob_alloc_len = 0;
Harald Weltea42a93f2010-06-14 22:26:10 +02001420 } else {
laforgee06d5982010-06-20 15:18:46 +02001421 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1422 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea42a93f2010-06-14 22:26:10 +02001423 }
Harald Welte07f32182010-06-28 18:41:27 +02001424 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1425 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte59b04682009-06-10 05:40:52 +08001426
Harald Welte427dbc42009-08-10 00:26:10 +02001427 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1428 lchan->T3101.cb = t3101_expired;
1429 lchan->T3101.data = lchan;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001430 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001431
1432 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001433 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte59b04682009-06-10 05:40:52 +08001434}
1435
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001436/* current load on the CCCH */
Harald Welte59b04682009-06-10 05:40:52 +08001437static int rsl_rx_ccch_load(struct msgb *msg)
1438{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001439 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001440 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001441 struct ccch_signal_data sd;
1442
1443 sd.bts = sign_link->trx->bts;
1444 sd.rach_slot_count = -1;
1445 sd.rach_busy_count = -1;
1446 sd.rach_access_count = -1;
Harald Welte59b04682009-06-10 05:40:52 +08001447
1448 switch (rslh->data[0]) {
1449 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001450 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1451 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte008a4922010-04-19 10:24:07 +02001452 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001453 sd.pg_buf_space = 50;
Harald Welte008a4922010-04-19 10:24:07 +02001454 }
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001455 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1456 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001457 break;
1458 case RSL_IE_RACH_LOAD:
1459 if (msg->data_len >= 7) {
Holger Hans Peter Freyther285af692012-02-03 20:26:25 +01001460 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1461 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1462 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1463 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Harald Welte59b04682009-06-10 05:40:52 +08001464 }
1465 break;
1466 default:
1467 break;
1468 }
1469
1470 return 0;
1471}
1472
1473static int abis_rsl_rx_cchan(struct msgb *msg)
1474{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001475 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001476 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1477 int rc = 0;
1478
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001479 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +08001480
1481 switch (rslh->c.msg_type) {
1482 case RSL_MT_CHAN_RQD:
1483 /* MS has requested a channel on the RACH */
1484 rc = rsl_rx_chan_rqd(msg);
1485 break;
1486 case RSL_MT_CCCH_LOAD_IND:
1487 /* current load on the CCCH */
1488 rc = rsl_rx_ccch_load(msg);
1489 break;
1490 case RSL_MT_DELETE_IND:
1491 /* CCCH overloaded, IMM_ASSIGN was dropped */
1492 case RSL_MT_CBCH_LOAD_IND:
1493 /* current load on the CBCH */
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001494 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1495 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001496 break;
1497 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001498 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1499 "0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001500 return -EINVAL;
1501 }
1502
1503 return rc;
1504}
1505
1506static int rsl_rx_rll_err_ind(struct msgb *msg)
1507{
1508 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001509 uint8_t *rlm_cause = rllh->data;
Harald Welte59b04682009-06-10 05:40:52 +08001510
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001511 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001512 gsm_lchan_name(msg->lchan),
Harald Welteb30935e2010-03-25 12:13:02 +08001513 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteed9a5ab2009-08-09 13:47:35 +02001514
1515 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001516
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001517 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +02001518 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001519 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001520 }
Harald Welte692f5852009-07-04 09:40:05 +02001521
Harald Welte59b04682009-06-10 05:40:52 +08001522 return 0;
1523}
1524
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001525static void rsl_handle_release(struct gsm_lchan *lchan)
1526{
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001527 int sapi;
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001528 struct gsm_bts *bts;
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001529
Holger Hans Peter Freyther701a6472011-12-28 12:11:40 +01001530 /*
1531 * Maybe only one link/SAPI was releasd or the error handling
1532 * was activated. Just return now and let the other code handle
1533 * it.
1534 */
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001535 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001536 return;
1537
1538 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1539 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1540 continue;
Harald Welte497aa982010-12-24 12:51:07 +01001541 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001542 gsm_lchan_name(lchan), sapi);
1543 return;
1544 }
1545
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001546
1547
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001548 /* wait a bit to send the RF Channel Release */
1549 lchan->T3111.cb = t3111_expired;
1550 lchan->T3111.data = lchan;
1551 bts = lchan->ts->trx->bts;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001552 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001553}
1554
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001555/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte59b04682009-06-10 05:40:52 +08001556 0x02, 0x06,
1557 0x01, 0x20,
1558 0x02, 0x00,
1559 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1560
1561static int abis_rsl_rx_rll(struct msgb *msg)
1562{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001563 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001564 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1565 int rc = 0;
1566 char *ts_name;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001567 uint8_t sapi = rllh->link_id & 7;
Harald Welte59b04682009-06-10 05:40:52 +08001568
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001569 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001570 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltede4477a2009-12-24 12:20:20 +01001571 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte59b04682009-06-10 05:40:52 +08001572
1573 switch (rllh->c.msg_type) {
1574 case RSL_MT_DATA_IND:
1575 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001576 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001577 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1578 rllh->data[0] == RSL_IE_L3_INFO) {
1579 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001580 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001581 }
1582 break;
1583 case RSL_MT_EST_IND:
1584 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte427dbc42009-08-10 00:26:10 +02001585 /* lchan is established, stop T3101 */
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001586 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001587 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001588 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001589 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1590 rllh->data[0] == RSL_IE_L3_INFO) {
1591 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001592 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001593 }
1594 break;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001595 case RSL_MT_EST_CONF:
Harald Welte61402172009-08-09 14:13:58 +02001596 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001597 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001598 rll_indication(msg->lchan, rllh->link_id,
1599 BSC_RLLR_IND_EST_CONF);
1600 break;
Harald Welte59b04682009-06-10 05:40:52 +08001601 case RSL_MT_REL_IND:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001602 /* BTS informs us of having received DISC from MS */
Harald Welteb6601442009-08-04 02:50:21 +02001603 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001604 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001605 rll_indication(msg->lchan, rllh->link_id,
1606 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001607 rsl_handle_release(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001608 break;
1609 case RSL_MT_REL_CONF:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001610 /* BTS informs us of having received UA from MS,
1611 * in response to DISC that we've sent earlier */
Harald Welteb6601442009-08-04 02:50:21 +02001612 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001613 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001614 rsl_handle_release(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001615 break;
1616 case RSL_MT_ERROR_IND:
Harald Welte59b04682009-06-10 05:40:52 +08001617 rc = rsl_rx_rll_err_ind(msg);
1618 break;
1619 case RSL_MT_UNIT_DATA_IND:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001620 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1621 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001622 break;
1623 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001624 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1625 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001626 }
Harald Welte59b04682009-06-10 05:40:52 +08001627 return rc;
1628}
1629
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001630static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Welte98d79f92009-07-28 18:11:56 +02001631{
Harald Welteb284b472009-12-02 01:58:23 +05301632 switch (lchan->tch_mode) {
Harald Welte98d79f92009-07-28 18:11:56 +02001633 case GSM48_CMODE_SPEECH_V1:
Harald Welteb284b472009-12-02 01:58:23 +05301634 switch (lchan->type) {
1635 case GSM_LCHAN_TCH_F:
1636 return 0x00;
1637 case GSM_LCHAN_TCH_H:
1638 return 0x03;
1639 default:
1640 break;
1641 }
Harald Welte98d79f92009-07-28 18:11:56 +02001642 case GSM48_CMODE_SPEECH_EFR:
Harald Welteb284b472009-12-02 01:58:23 +05301643 switch (lchan->type) {
1644 case GSM_LCHAN_TCH_F:
1645 return 0x01;
1646 /* there's no half-rate EFR */
1647 default:
1648 break;
1649 }
Harald Welte98d79f92009-07-28 18:11:56 +02001650 case GSM48_CMODE_SPEECH_AMR:
Harald Welteb284b472009-12-02 01:58:23 +05301651 switch (lchan->type) {
1652 case GSM_LCHAN_TCH_F:
1653 return 0x02;
1654 case GSM_LCHAN_TCH_H:
1655 return 0x05;
1656 default:
1657 break;
1658 }
1659 default:
1660 break;
Harald Welte98d79f92009-07-28 18:11:56 +02001661 }
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001662 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welteb284b472009-12-02 01:58:23 +05301663 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001664 return 0;
Harald Welte98d79f92009-07-28 18:11:56 +02001665}
1666
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001667static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munaut1338a552009-12-20 22:06:40 +01001668{
1669 switch (lchan->tch_mode) {
1670 case GSM48_CMODE_SPEECH_V1:
1671 switch (lchan->type) {
1672 case GSM_LCHAN_TCH_F:
1673 return RTP_PT_GSM_FULL;
1674 case GSM_LCHAN_TCH_H:
1675 return RTP_PT_GSM_HALF;
1676 default:
1677 break;
1678 }
1679 case GSM48_CMODE_SPEECH_EFR:
1680 switch (lchan->type) {
1681 case GSM_LCHAN_TCH_F:
1682 return RTP_PT_GSM_EFR;
1683 /* there's no half-rate EFR */
1684 default:
1685 break;
1686 }
1687 case GSM48_CMODE_SPEECH_AMR:
1688 switch (lchan->type) {
1689 case GSM_LCHAN_TCH_F:
Sylvain Munaut1338a552009-12-20 22:06:40 +01001690 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freytherd78bee82011-07-21 10:24:46 +02001691 return RTP_PT_AMR;
Sylvain Munaut1338a552009-12-20 22:06:40 +01001692 default:
1693 break;
1694 }
1695 default:
1696 break;
1697 }
1698 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1699 "tch_mode == 0x%02x\n & lchan_type == %d",
1700 lchan->tch_mode, lchan->type);
1701 return 0;
1702}
1703
Harald Welte59b04682009-06-10 05:40:52 +08001704/* ip.access specific RSL extensions */
Harald Weltebffa4992009-12-19 16:42:06 +01001705static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1706{
1707 struct in_addr ip;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001708 uint16_t port, conn_id;
Harald Weltebffa4992009-12-19 16:42:06 +01001709
1710 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001711 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001712 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1713 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1714 }
1715
1716 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001717 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001718 port = ntohs(port);
1719 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1720 lchan->abis_ip.bound_port = port;
1721 }
1722
1723 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001724 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Weltebffa4992009-12-19 16:42:06 +01001725 conn_id = ntohs(conn_id);
1726 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1727 lchan->abis_ip.conn_id = conn_id;
1728 }
1729
1730 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1731 lchan->abis_ip.rtp_payload2 =
1732 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1733 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1734 lchan->abis_ip.rtp_payload2);
1735 }
1736
1737 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1738 lchan->abis_ip.speech_mode =
1739 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1740 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1741 lchan->abis_ip.speech_mode);
1742 }
1743
1744 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001745 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Weltebffa4992009-12-19 16:42:06 +01001746 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1747 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1748 }
1749
1750 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001751 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Weltebffa4992009-12-19 16:42:06 +01001752 port = ntohs(port);
1753 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1754 lchan->abis_ip.connect_port = port;
1755 }
1756}
1757
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001758int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte59b04682009-06-10 05:40:52 +08001759{
1760 struct msgb *msg = rsl_msgb_alloc();
1761 struct abis_rsl_dchan_hdr *dh;
1762
1763 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001764 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte59b04682009-06-10 05:40:52 +08001765 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001766 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001767
Harald Welte98d79f92009-07-28 18:11:56 +02001768 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001769 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001770 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001771 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001772 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001773
Sylvain Munaut1338a552009-12-20 22:06:40 +01001774 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1775 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1776 lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001777
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001778 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001779
1780 return abis_rsl_sendmsg(msg);
1781}
1782
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001783int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1784 uint8_t rtp_payload2)
Harald Welte59b04682009-06-10 05:40:52 +08001785{
1786 struct msgb *msg = rsl_msgb_alloc();
1787 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001788 uint32_t *att_ip;
Harald Welte98d79f92009-07-28 18:11:56 +02001789 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +08001790
1791 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001792 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte59b04682009-06-10 05:40:52 +08001793 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltee6d51f92011-06-25 10:02:33 +02001794 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001795
Harald Weltebffa4992009-12-19 16:42:06 +01001796 /* we need to store these now as MDCX_ACK does not return them :( */
1797 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1798 lchan->abis_ip.connect_port = port;
1799 lchan->abis_ip.connect_ip = ip;
1800
Harald Weltefb4a9e92009-07-29 12:12:18 +02001801 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001802 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001803 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltefb4a9e92009-07-29 12:12:18 +02001804
Harald Welte98d79f92009-07-28 18:11:56 +02001805 ia.s_addr = htonl(ip);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001806 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1807 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1808 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1809 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001810
Harald Weltebffa4992009-12-19 16:42:06 +01001811 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1812 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001813 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Weltebffa4992009-12-19 16:42:06 +01001814 *att_ip = ia.s_addr;
1815 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1816 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001817 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001818 if (rtp_payload2)
1819 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001820
1821 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte59b04682009-06-10 05:40:52 +08001822
1823 return abis_rsl_sendmsg(msg);
1824}
1825
Harald Welte9947d9f2009-12-20 16:51:09 +01001826/* tell BTS to connect RTP stream to our local RTP socket */
1827int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1828{
1829 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1830 int rc;
1831
1832 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1833 ntohs(rs->rtp.sin_local.sin_port),
1834 /* FIXME: use RTP payload of bound socket, not BTS*/
1835 lchan->abis_ip.rtp_payload2);
1836
1837 return rc;
1838}
1839
Harald Welte6f40df02010-12-23 12:59:52 +01001840int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welteaed946e2009-10-24 10:29:22 +02001841{
1842 struct msgb *msg = rsl_msgb_alloc();
1843 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +02001844 uint8_t msg_type;
Harald Welte2b361522010-03-28 14:42:09 +08001845
1846 if (act)
1847 msg_type = RSL_MT_IPAC_PDCH_ACT;
1848 else
1849 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welteaed946e2009-10-24 10:29:22 +02001850
1851 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte2b361522010-03-28 14:42:09 +08001852 init_dchan_hdr(dh, msg_type);
Harald Welteaed946e2009-10-24 10:29:22 +02001853 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltee6d51f92011-06-25 10:02:33 +02001854 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welteaed946e2009-10-24 10:29:22 +02001855
Harald Welte6f40df02010-12-23 12:59:52 +01001856 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte2b361522010-03-28 14:42:09 +08001857 act ? "" : "DE");
Harald Welteaed946e2009-10-24 10:29:22 +02001858
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001859 msg->dst = ts->trx->rsl_link;
Harald Welteaed946e2009-10-24 10:29:22 +02001860
1861 return abis_rsl_sendmsg(msg);
1862}
1863
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001864static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001865{
1866 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1867 struct tlv_parsed tv;
Harald Welte87504212009-12-02 01:56:49 +05301868 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001869
1870 /* the BTS has acknowledged a local bind, it now tells us the IP
1871 * address and port number to which it has bound the given logical
1872 * channel */
1873
1874 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1875 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1876 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welteb9498952009-07-12 09:45:05 +02001877 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001878 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte59b04682009-06-10 05:40:52 +08001879 return -EINVAL;
1880 }
Harald Welte50517742009-12-20 15:42:44 +01001881
Harald Weltebffa4992009-12-19 16:42:06 +01001882 ipac_parse_rtp(lchan, &tv);
Harald Welte50517742009-12-20 15:42:44 +01001883
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001884 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001885
1886 return 0;
1887}
1888
Harald Weltebffa4992009-12-19 16:42:06 +01001889static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1890{
1891 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1892 struct tlv_parsed tv;
1893 struct gsm_lchan *lchan = msg->lchan;
1894
1895 /* the BTS has acknowledged a remote connect request and
1896 * it now tells us the IP address and port number to which it has
1897 * connected the given logical channel */
1898
1899 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1900 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001901 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001902
1903 return 0;
1904}
1905
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001906static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001907{
1908 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1909 struct tlv_parsed tv;
1910
1911 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte59b04682009-06-10 05:40:52 +08001912
Harald Weltef1a168d2009-07-28 17:58:09 +02001913 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001914 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001915 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte59b04682009-06-10 05:40:52 +08001916
Pablo Neira Ayusoef717c62011-05-06 12:12:31 +02001917 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welteba4e58d2009-07-28 18:02:05 +02001918
Harald Welte59b04682009-06-10 05:40:52 +08001919 return 0;
1920}
1921
1922static int abis_rsl_rx_ipacc(struct msgb *msg)
1923{
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001924 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte59b04682009-06-10 05:40:52 +08001925 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltede4477a2009-12-24 12:20:20 +01001926 char *ts_name;
Harald Welte59b04682009-06-10 05:40:52 +08001927 int rc = 0;
1928
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02001929 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001930 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001931
1932 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001933 case RSL_MT_IPAC_CRCX_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001934 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001935 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001936 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001937 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001938 /* somehow the BTS was unable to bind the lchan to its local
1939 * port?!? */
Harald Weltede4477a2009-12-24 12:20:20 +01001940 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001941 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001942 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte59b04682009-06-10 05:40:52 +08001943 /* the BTS tells us that a connect operation was successful */
Harald Weltede4477a2009-12-24 12:20:20 +01001944 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Weltebffa4992009-12-19 16:42:06 +01001945 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001946 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001947 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001948 /* somehow the BTS was unable to connect the lchan to a remote
1949 * port */
Harald Weltede4477a2009-12-24 12:20:20 +01001950 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001951 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001952 case RSL_MT_IPAC_DLCX_IND:
Harald Weltede4477a2009-12-24 12:20:20 +01001953 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001954 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001955 break;
1956 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001957 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001958 rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001959 break;
1960 }
1961 DEBUGPC(DRSL, "\n");
1962
1963 return rc;
1964}
1965
1966
1967/* Entry-point where L2 RSL from BTS enters */
1968int abis_rsl_rcvmsg(struct msgb *msg)
1969{
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001970 struct abis_rsl_common_hdr *rslh;
Harald Welte59b04682009-06-10 05:40:52 +08001971 int rc = 0;
1972
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001973 if (!msg) {
1974 DEBUGP(DRSL, "Empty RSL msg?..\n");
1975 return -1;
1976 }
1977
1978 if (msgb_l2len(msg) < sizeof(*rslh)) {
1979 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltece807262012-05-31 20:22:34 +02001980 msgb_free(msg);
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001981 return -1;
1982 }
1983
1984 rslh = msgb_l2(msg);
1985
Harald Welte59b04682009-06-10 05:40:52 +08001986 switch (rslh->msg_discr & 0xfe) {
1987 case ABIS_RSL_MDISC_RLL:
1988 rc = abis_rsl_rx_rll(msg);
1989 break;
1990 case ABIS_RSL_MDISC_DED_CHAN:
1991 rc = abis_rsl_rx_dchan(msg);
1992 break;
1993 case ABIS_RSL_MDISC_COM_CHAN:
1994 rc = abis_rsl_rx_cchan(msg);
1995 break;
1996 case ABIS_RSL_MDISC_TRX:
1997 rc = abis_rsl_rx_trx(msg);
1998 break;
1999 case ABIS_RSL_MDISC_LOC:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01002000 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte59b04682009-06-10 05:40:52 +08002001 rslh->msg_discr);
2002 break;
2003 case ABIS_RSL_MDISC_IPACCESS:
2004 rc = abis_rsl_rx_ipacc(msg);
2005 break;
2006 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01002007 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
2008 "0x%02x\n", rslh->msg_discr);
Harald Weltece807262012-05-31 20:22:34 +02002009 rc = -EINVAL;
Harald Welte59b04682009-06-10 05:40:52 +08002010 }
2011 msgb_free(msg);
2012 return rc;
2013}
2014
Holger Hans Peter Freytherb67f4082010-07-21 15:54:32 +08002015int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
2016 uint8_t cb_command, const uint8_t *data, int len)
2017{
2018 struct abis_rsl_dchan_hdr *dh;
2019 struct msgb *cb_cmd;
2020
2021 cb_cmd = rsl_msgb_alloc();
2022 if (!cb_cmd)
2023 return -1;
2024
2025 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2026 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2027 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2028
2029 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2030 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2031
2032 cb_cmd->trx = bts->c0;
2033
2034 return abis_rsl_sendmsg(cb_cmd);
2035}
Dieter Spaar49c843e2011-07-28 00:01:50 +02002036
2037int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2038{
2039 struct abis_rsl_common_hdr *ch;
2040 struct msgb *msg = rsl_msgb_alloc();
2041
2042 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2043 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2044 ch->msg_type = 0x40; /* Nokia SI Begin */
2045
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002046 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002047
2048 return abis_rsl_sendmsg(msg);
2049}
2050
2051int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2052{
2053 struct abis_rsl_common_hdr *ch;
2054 struct msgb *msg = rsl_msgb_alloc();
2055
2056 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2057 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2058 ch->msg_type = 0x41; /* Nokia SI End */
2059
2060 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2061
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002062 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002063
2064 return abis_rsl_sendmsg(msg);
2065}
2066
2067int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2068{
2069 struct abis_rsl_common_hdr *ch;
2070 struct msgb *msg = rsl_msgb_alloc();
2071
2072 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2073 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2074 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2075
2076 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2077 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2078
Pablo Neira Ayuso88c9bba2011-08-17 22:43:54 +02002079 msg->dst = trx->rsl_link;
Dieter Spaar49c843e2011-07-28 00:01:50 +02002080
2081 return abis_rsl_sendmsg(msg);
2082}
Holger Hans Peter Freythere38af682011-12-27 22:24:17 +01002083
2084/**
2085 * Release all allocated SAPIs starting from @param start and
2086 * release them with the given release mode. Once the release
2087 * confirmation arrives it will be attempted to release the
2088 * the RF channel.
2089 */
2090int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
2091 enum rsl_rel_mode release_mode)
2092{
2093 int no_sapi = 1;
2094 int sapi;
2095
2096 for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
2097 uint8_t link_id;
2098 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
2099 continue;
2100
2101 link_id = sapi;
2102 if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
2103 link_id |= 0x40;
2104 rsl_release_request(lchan, link_id, release_mode);
2105 no_sapi = 0;
2106 }
2107
2108 return no_sapi;
2109}