blob: ad11c73623134504de71d49deaa80a6214d76368 [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>
Harald Welte59b04682009-06-10 05:40:52 +08005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <sys/types.h>
28#include <netinet/in.h>
29#include <arpa/inet.h>
30
31#include <openbsc/gsm_data.h>
32#include <openbsc/gsm_04_08.h>
Harald Weltef4625b12010-02-20 16:24:02 +010033#include <osmocore/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080034#include <openbsc/abis_rsl.h>
35#include <openbsc/chan_alloc.h>
Harald Welteed9a5ab2009-08-09 13:47:35 +020036#include <openbsc/bsc_rll.h>
Harald Welte59b04682009-06-10 05:40:52 +080037#include <openbsc/debug.h>
Harald Weltef4625b12010-02-20 16:24:02 +010038#include <osmocore/tlv.h>
Harald Welte59b04682009-06-10 05:40:52 +080039#include <openbsc/paging.h>
40#include <openbsc/signal.h>
Harald Weltec20bd1d2009-11-29 19:07:28 +010041#include <openbsc/meas_rep.h>
Harald Welte50517742009-12-20 15:42:44 +010042#include <openbsc/rtp_proxy.h>
Harald Welte1fa8bac2010-03-01 21:59:06 +010043#include <osmocore/rsl.h>
Harald Welte59b04682009-06-10 05:40:52 +080044
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080045#include <osmocore/talloc.h>
46
Harald Welte59b04682009-06-10 05:40:52 +080047#define RSL_ALLOC_SIZE 1024
48#define RSL_ALLOC_HEADROOM 128
49
50#define MAX(a, b) (a) >= (b) ? (a) : (b)
51
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +080052static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
53
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +010054static void send_lchan_signal(int sig_no, struct gsm_lchan *lchan,
55 struct gsm_meas_rep *resp)
56{
57 struct lchan_signal_data sig;
58 sig.lchan = lchan;
59 sig.mr = resp;
60 dispatch_signal(SS_LCHAN, sig_no, &sig);
61}
62
Harald Welte59b04682009-06-10 05:40:52 +080063static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
64{
65 /* mask off the transparent bit ? */
66 msg_type &= 0xfe;
67
68 if ((msg_type & 0xf0) == 0x00)
69 return ABIS_RSL_MDISC_RLL;
70 if ((msg_type & 0xf0) == 0x10) {
71 if (msg_type >= 0x19 && msg_type <= 0x22)
72 return ABIS_RSL_MDISC_TRX;
73 else
74 return ABIS_RSL_MDISC_COM_CHAN;
75 }
76 if ((msg_type & 0xe0) == 0x20)
77 return ABIS_RSL_MDISC_DED_CHAN;
78
79 return ABIS_RSL_MDISC_LOC;
80}
81
82static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
83 u_int8_t msg_type)
84{
85 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
86 dh->c.msg_type = msg_type;
87 dh->ie_chan = RSL_IE_CHAN_NR;
88}
89
Harald Welte59b04682009-06-10 05:40:52 +080090/* determine logical channel based on TRX and channel number IE */
91struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
92{
93 struct gsm_lchan *lchan;
94 u_int8_t ts_nr = chan_nr & 0x07;
95 u_int8_t cbits = chan_nr >> 3;
96 u_int8_t lch_idx;
97 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
98
99 if (cbits == 0x01) {
100 lch_idx = 0; /* TCH/F */
Harald Welte37884ed2009-10-24 10:25:50 +0200101 if (ts->pchan != GSM_PCHAN_TCH_F &&
102 ts->pchan != GSM_PCHAN_PDCH &&
103 ts->pchan != GSM_PCHAN_TCH_F_PDCH)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100104 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800105 chan_nr, ts->pchan);
106 } else if ((cbits & 0x1e) == 0x02) {
107 lch_idx = cbits & 0x1; /* TCH/H */
108 if (ts->pchan != GSM_PCHAN_TCH_H)
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 & 0x1c) == 0x04) {
112 lch_idx = cbits & 0x3; /* SDCCH/4 */
113 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
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 & 0x18) == 0x08) {
117 lch_idx = cbits & 0x7; /* SDCCH/8 */
118 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
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 == 0x10 || cbits == 0x11 || cbits == 0x12) {
122 lch_idx = 0;
123 if (ts->pchan != GSM_PCHAN_CCCH &&
124 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100125 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte59b04682009-06-10 05:40:52 +0800126 chan_nr, ts->pchan);
127 /* FIXME: we should not return first sdcch4 !!! */
128 } else {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100129 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte59b04682009-06-10 05:40:52 +0800130 return NULL;
131 }
132
133 lchan = &ts->lchan[lch_idx];
Harald Welte51d2a592010-03-26 21:28:59 +0800134 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther1a95fa82010-06-28 15:47:12 +0800135 if (lchan->conn)
136 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800137
138 return lchan;
139}
140
Holger Hans Peter Freyther942ff172009-10-22 11:47:45 +0200141/* See Table 10.5.25 of GSM04.08 */
Harald Welte6f40df02010-12-23 12:59:52 +0100142static u_int8_t ts2chan_nr(const struct gsm_bts_trx_ts *ts, uint8_t lchan_nr)
Harald Welte59b04682009-06-10 05:40:52 +0800143{
Harald Welte59b04682009-06-10 05:40:52 +0800144 u_int8_t cbits, chan_nr;
145
146 switch (ts->pchan) {
147 case GSM_PCHAN_TCH_F:
Harald Welte37884ed2009-10-24 10:25:50 +0200148 case GSM_PCHAN_PDCH:
149 case GSM_PCHAN_TCH_F_PDCH:
Harald Welte59b04682009-06-10 05:40:52 +0800150 cbits = 0x01;
151 break;
152 case GSM_PCHAN_TCH_H:
153 cbits = 0x02;
Harald Welte6f40df02010-12-23 12:59:52 +0100154 cbits += lchan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800155 break;
156 case GSM_PCHAN_CCCH_SDCCH4:
157 cbits = 0x04;
Harald Welte6f40df02010-12-23 12:59:52 +0100158 cbits += lchan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800159 break;
160 case GSM_PCHAN_SDCCH8_SACCH8C:
161 cbits = 0x08;
Harald Welte6f40df02010-12-23 12:59:52 +0100162 cbits += lchan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800163 break;
164 default:
165 case GSM_PCHAN_CCCH:
166 cbits = 0x10;
167 break;
168 }
169
170 chan_nr = (cbits << 3) | (ts->nr & 0x7);
171
172 return chan_nr;
173}
174
Harald Welte6f40df02010-12-23 12:59:52 +0100175u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan)
176{
177 return ts2chan_nr(lchan->ts, lchan->nr);
178}
179
Harald Welte59b04682009-06-10 05:40:52 +0800180/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
181u_int64_t str_to_imsi(const char *imsi_str)
182{
183 u_int64_t ret;
184
185 ret = strtoull(imsi_str, NULL, 10);
186
187 return ret;
188}
189
190/* Table 5 Clause 7 TS 05.02 */
191unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res)
192{
193 if (!bs_ccch_sdcch_comb)
194 return 9 - bs_ag_blks_res;
195 else
196 return 3 - bs_ag_blks_res;
197}
198
199/* Chapter 6.5.2 of TS 05.02 */
200unsigned int get_ccch_group(u_int64_t imsi, unsigned int bs_cc_chans,
201 unsigned int n_pag_blocks)
202{
203 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) / n_pag_blocks;
204}
205
206/* Chapter 6.5.2 of TS 05.02 */
207unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
208 int n_pag_blocks)
209{
210 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) % n_pag_blocks;
211}
212
213static struct msgb *rsl_msgb_alloc(void)
214{
Harald Welte9cfc9352009-06-26 19:39:35 +0200215 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
216 "RSL");
Harald Welte59b04682009-06-10 05:40:52 +0800217}
218
219#define MACBLOCK_SIZE 23
220static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
221{
222 memcpy(out, in, len);
223
224 if (len < MACBLOCK_SIZE)
225 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
226}
227
Harald Welted2dd9de2009-08-30 15:37:11 +0900228/* Chapter 9.3.7: Encryption Information */
229static int build_encr_info(u_int8_t *out, struct gsm_lchan *lchan)
230{
231 *out++ = lchan->encr.alg_id & 0xff;
232 if (lchan->encr.key_len)
233 memcpy(out, lchan->encr.key, lchan->encr.key_len);
234 return lchan->encr.key_len + 1;
235}
236
Harald Weltede4477a2009-12-24 12:20:20 +0100237static void print_rsl_cause(int lvl, const u_int8_t *cause_v, u_int8_t cause_len)
Harald Weltef1a168d2009-07-28 17:58:09 +0200238{
Harald Welte59b04682009-06-10 05:40:52 +0800239 int i;
240
Harald Weltede4477a2009-12-24 12:20:20 +0100241 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Weltef1a168d2009-07-28 17:58:09 +0200242 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200243 for (i = 1; i < cause_len-1; i++)
Harald Weltede4477a2009-12-24 12:20:20 +0100244 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte59b04682009-06-10 05:40:52 +0800245}
246
247/* Send a BCCH_INFO message as per Chapter 8.5.1 */
248int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
249 const u_int8_t *data, int len)
250{
251 struct abis_rsl_dchan_hdr *dh;
252 struct msgb *msg = rsl_msgb_alloc();
253
254 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
255 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
256 dh->chan_nr = RSL_CHAN_BCCH;
257
258 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
259 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
260
261 msg->trx = trx;
262
263 return abis_rsl_sendmsg(msg);
264}
265
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200266int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte59b04682009-06-10 05:40:52 +0800267 const u_int8_t *data, int len)
268{
269 struct abis_rsl_common_hdr *ch;
270 struct msgb *msg = rsl_msgb_alloc();
271
272 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
273 ch->msg_discr = ABIS_RSL_MDISC_TRX;
274 ch->msg_type = RSL_MT_SACCH_FILL;
275
276 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
277 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
278
279 msg->trx = trx;
280
281 return abis_rsl_sendmsg(msg);
282}
283
Harald Welte91afe4c2009-06-20 18:15:19 +0200284int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
285{
286 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200287 struct msgb *msg;
Harald Welte91afe4c2009-06-20 18:15:19 +0200288 u_int8_t chan_nr = lchan2chan_nr(lchan);
289
290 db = abs(db);
291 if (db > 30)
292 return -EINVAL;
293
Harald Welteed831842009-06-27 03:09:08 +0200294 msg = rsl_msgb_alloc();
295
Harald Welte91afe4c2009-06-20 18:15:19 +0200296 lchan->bs_power = db/2;
297 if (fpc)
298 lchan->bs_power |= 0x10;
299
300 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
301 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
302 dh->chan_nr = chan_nr;
303
304 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
305
306 msg->trx = lchan->ts->trx;
307
308 return abis_rsl_sendmsg(msg);
309}
310
Harald Welte91afe4c2009-06-20 18:15:19 +0200311int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
312{
313 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200314 struct msgb *msg;
Harald Welte91afe4c2009-06-20 18:15:19 +0200315 u_int8_t chan_nr = lchan2chan_nr(lchan);
316 int ctl_lvl;
317
Harald Weltec4dcda02009-08-09 14:45:18 +0200318 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Welte91afe4c2009-06-20 18:15:19 +0200319 if (ctl_lvl < 0)
320 return ctl_lvl;
321
Harald Welteed831842009-06-27 03:09:08 +0200322 msg = rsl_msgb_alloc();
323
Harald Welte91afe4c2009-06-20 18:15:19 +0200324 lchan->ms_power = ctl_lvl;
325
326 if (fpc)
327 lchan->ms_power |= 0x20;
328
329 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
330 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
331 dh->chan_nr = chan_nr;
332
333 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
334
335 msg->trx = lchan->ts->trx;
336
337 return abis_rsl_sendmsg(msg);
338}
339
Harald Welte39274f42009-07-29 15:41:29 +0200340static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
341 struct gsm_lchan *lchan)
342{
343 memset(cm, 0, sizeof(cm));
344
345 /* FIXME: what to do with data calls ? */
Holger Hans Peter Freyther21d63ff2010-09-06 09:25:48 +0800346 if (lchan->ts->trx->bts->network->dtx_enabled)
347 cm->dtx_dtu = 0x03;
348 else
349 cm->dtx_dtu = 0x00;
Harald Welte39274f42009-07-29 15:41:29 +0200350
351 /* set TCH Speech/Data */
352 cm->spd_ind = lchan->rsl_cmode;
353
Harald Welte951e3512009-11-27 08:55:16 +0100354 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
355 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100356 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte951e3512009-11-27 08:55:16 +0100357 "but tch_mode != signalling\n");
358
Harald Welte39274f42009-07-29 15:41:29 +0200359 switch (lchan->type) {
360 case GSM_LCHAN_SDCCH:
361 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
362 break;
363 case GSM_LCHAN_TCH_F:
364 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
365 break;
366 case GSM_LCHAN_TCH_H:
367 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
368 break;
369 case GSM_LCHAN_NONE:
370 case GSM_LCHAN_UNKNOWN:
371 default:
372 return -EINVAL;
373 }
374
375 switch (lchan->tch_mode) {
376 case GSM48_CMODE_SIGN:
377 cm->chan_rate = 0;
378 break;
379 case GSM48_CMODE_SPEECH_V1:
380 cm->chan_rate = RSL_CMOD_SP_GSM1;
381 break;
382 case GSM48_CMODE_SPEECH_EFR:
383 cm->chan_rate = RSL_CMOD_SP_GSM2;
384 break;
385 case GSM48_CMODE_SPEECH_AMR:
386 cm->chan_rate = RSL_CMOD_SP_GSM3;
387 break;
388 case GSM48_CMODE_DATA_14k5:
389 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
390 break;
391 case GSM48_CMODE_DATA_12k0:
392 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
393 break;
394 case GSM48_CMODE_DATA_6k0:
395 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
396 break;
397 default:
398 return -EINVAL;
399 }
400
401 return 0;
402}
403
Harald Welte59b04682009-06-10 05:40:52 +0800404/* Chapter 8.4.1 */
405#if 0
406int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
407 u_int8_t act_type,
408 struct rsl_ie_chan_mode *chan_mode,
409 struct rsl_ie_chan_ident *chan_ident,
410 u_int8_t bs_power, u_int8_t ms_power,
411 u_int8_t ta)
412{
413 struct abis_rsl_dchan_hdr *dh;
414 struct msgb *msg = rsl_msgb_alloc();
415
416 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
417 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
418 dh->chan_nr = chan_nr;
419
420 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
421 /* For compatibility with Phase 1 */
422 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
423 (u_int8_t *) chan_mode);
424 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
425 (u_int8_t *) chan_ident);
426#if 0
427 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
428 (u_int8_t *) &encr_info);
429#endif
430 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
431 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
432 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
433
434 msg->trx = trx;
435
436 return abis_rsl_sendmsg(msg);
437}
438#endif
439
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200440int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
Harald Welteb90d7bd2009-12-17 00:31:10 +0100441 u_int8_t ta, u_int8_t ho_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800442{
443 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200444 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200445 int rc;
Harald Weltedea24e92010-06-29 17:53:45 +0200446 uint8_t *len;
Harald Welte59b04682009-06-10 05:40:52 +0800447
448 u_int8_t chan_nr = lchan2chan_nr(lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800449 struct rsl_ie_chan_mode cm;
laforgef723cf02010-06-20 21:38:19 +0200450 struct gsm48_chan_desc cd;
Harald Welte59b04682009-06-10 05:40:52 +0800451
Harald Welte39274f42009-07-29 15:41:29 +0200452 rc = channel_mode_from_lchan(&cm, lchan);
453 if (rc < 0)
454 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800455
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800456 memset(&cd, 0, sizeof(cd));
laforgef723cf02010-06-20 21:38:19 +0200457 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800458
Harald Welteed831842009-06-27 03:09:08 +0200459 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800460 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
461 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
462 dh->chan_nr = chan_nr;
463
464 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
Harald Welte59b04682009-06-10 05:40:52 +0800465 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
466 (u_int8_t *) &cm);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800467
468 /*
469 * The Channel Identification is needed for Phase1 phones
470 * and it contains the GSM48 Channel Description and the
471 * Mobile Allocation. The GSM 08.58 asks for the Mobile
472 * Allocation to have a length of zero. We are using the
473 * msgb_l3len to calculate the length of both messages.
474 */
laforgef723cf02010-06-20 21:38:19 +0200475 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Weltedea24e92010-06-29 17:53:45 +0200476 len = msgb_put(msg, 1);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800477 msgb_tlv_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther4cab4422010-06-30 12:06:20 +0800478
479 if (lchan->ts->hopping.enabled)
480 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
481 lchan->ts->hopping.ma_data);
482 else
483 msgb_tlv_put(msg, GSM48_IE_MA_AFTER, 0, NULL);
Holger Hans Peter Freyther11b01402010-06-30 11:56:43 +0800484
485 /* update the calculated size */
486 msg->l3h = len + 1;
487 *len = msgb_l3len(msg);
488
Harald Welted2dd9de2009-08-30 15:37:11 +0900489 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
490 u_int8_t encr_info[MAX_A5_KEY_LEN+2];
491 rc = build_encr_info(encr_info, lchan);
492 if (rc > 0)
493 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
494 }
495
Harald Welteb90d7bd2009-12-17 00:31:10 +0100496 switch (act_type) {
497 case RSL_ACT_INTER_ASYNC:
498 case RSL_ACT_INTER_SYNC:
499 msgb_tv_put(msg, RSL_IE_HANDO_REF, ho_ref);
500 break;
501 default:
502 break;
503 }
504
Harald Welte59b04682009-06-10 05:40:52 +0800505 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
506 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
507 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
508
Holger Hans Peter Freyther6fe8ab92010-01-28 04:45:05 +0100509 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)
510 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
511 (u_int8_t *) &lchan->mr_conf);
512
Harald Welte59b04682009-06-10 05:40:52 +0800513 msg->trx = lchan->ts->trx;
514
515 return abis_rsl_sendmsg(msg);
516}
517
Harald Welte8e770492009-07-29 11:38:15 +0200518/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welte59b04682009-06-10 05:40:52 +0800519int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
520{
521 struct abis_rsl_dchan_hdr *dh;
Harald Welteed831842009-06-27 03:09:08 +0200522 struct msgb *msg;
Harald Welte39274f42009-07-29 15:41:29 +0200523 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800524
525 u_int8_t chan_nr = lchan2chan_nr(lchan);
526 struct rsl_ie_chan_mode cm;
527
Harald Welte39274f42009-07-29 15:41:29 +0200528 rc = channel_mode_from_lchan(&cm, lchan);
529 if (rc < 0)
530 return rc;
Harald Welte59b04682009-06-10 05:40:52 +0800531
Harald Welteed831842009-06-27 03:09:08 +0200532 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800533 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
534 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
535 dh->chan_nr = chan_nr;
536
537 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
538 (u_int8_t *) &cm);
Harald Welted2dd9de2009-08-30 15:37:11 +0900539
540 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
541 u_int8_t encr_info[MAX_A5_KEY_LEN+2];
542 rc = build_encr_info(encr_info, lchan);
543 if (rc > 0)
544 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
545 }
546
Holger Hans Peter Freyther3cce58f2009-11-18 22:57:02 +0100547 if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
548 msgb_tlv_put(msg, RSL_IE_MR_CONFIG, sizeof(lchan->mr_conf),
549 (u_int8_t *) &lchan->mr_conf);
550 }
551
Harald Welted2dd9de2009-08-30 15:37:11 +0900552 msg->trx = lchan->ts->trx;
553
554 return abis_rsl_sendmsg(msg);
555}
556
557/* Chapter 8.4.6: Send the encryption command with given L3 info */
558int rsl_encryption_cmd(struct msgb *msg)
559{
560 struct abis_rsl_dchan_hdr *dh;
561 struct gsm_lchan *lchan = msg->lchan;
562 u_int8_t chan_nr = lchan2chan_nr(lchan);
563 u_int8_t encr_info[MAX_A5_KEY_LEN+2];
Sylvain Munaut01f1caf2009-09-27 11:13:18 +0200564 u_int8_t l3_len = msg->len;
Harald Welted2dd9de2009-08-30 15:37:11 +0900565 int rc;
566
567 /* First push the L3 IE tag and length */
568 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
569
570 /* then the link identifier (SAPI0, main sign link) */
571 msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
572
573 /* then encryption information */
574 rc = build_encr_info(encr_info, lchan);
575 if (rc <= 0)
576 return rc;
577 msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
578
579 /* and finally the DCHAN header */
580 dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
581 init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
582 dh->chan_nr = chan_nr;
Harald Welte59b04682009-06-10 05:40:52 +0800583
584 msg->trx = lchan->ts->trx;
585
586 return abis_rsl_sendmsg(msg);
587}
588
Harald Welte85a163c2009-08-10 11:43:22 +0200589/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteafe3c232009-07-19 18:36:49 +0200590int rsl_deact_sacch(struct gsm_lchan *lchan)
591{
592 struct abis_rsl_dchan_hdr *dh;
593 struct msgb *msg = rsl_msgb_alloc();
594
595 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
596 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
597 dh->chan_nr = lchan2chan_nr(lchan);
598
599 msg->lchan = lchan;
600 msg->trx = lchan->ts->trx;
601
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100602 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteafe3c232009-07-19 18:36:49 +0200603
604 return abis_rsl_sendmsg(msg);
605}
606
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800607static void error_timeout_cb(void *data)
608{
609 struct gsm_lchan *lchan = data;
610 if (lchan->state != LCHAN_S_REL_ERR) {
611 LOGP(DRSL, LOGL_ERROR, "%s error timeout but not in error state: %d\n",
612 gsm_lchan_name(lchan), lchan->state);
613 return;
614 }
615
616 /* go back to the none state */
617 LOGP(DRSL, LOGL_NOTICE, "%s is back in operation.\n", gsm_lchan_name(lchan));
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800618 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800619}
620
Harald Welte85a163c2009-08-10 11:43:22 +0200621/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800622static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte59b04682009-06-10 05:40:52 +0800623{
624 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800625 struct msgb *msg;
Harald Welte59b04682009-06-10 05:40:52 +0800626
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800627 if (lchan->state == LCHAN_S_REL_ERR) {
628 LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n",
629 gsm_lchan_name(lchan));
630 return -1;
631 }
632
633 msg = rsl_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800634 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
635 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
636 dh->chan_nr = lchan2chan_nr(lchan);
637
638 msg->lchan = lchan;
639 msg->trx = lchan->ts->trx;
640
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800641 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
642
643 if (error) {
644 /*
645 * the nanoBTS sends RLL release indications after the channel release. This can
646 * be a problem when we have reassigned the channel to someone else and then can
647 * not figure out who used this channel.
648 */
Holger Hans Peter Freyther456fb9d2010-06-08 11:53:33 +0800649 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800650 lchan->error_timer.data = lchan;
651 lchan->error_timer.cb = error_timeout_cb;
652 bsc_schedule_timer(&lchan->error_timer,
653 msg->trx->bts->network->T3111 + 2, 0);
654 }
Harald Welte59b04682009-06-10 05:40:52 +0800655
Harald Welte85a163c2009-08-10 11:43:22 +0200656 /* BTS will respond by RF CHAN REL ACK */
Harald Welte59b04682009-06-10 05:40:52 +0800657 return abis_rsl_sendmsg(msg);
658}
659
660int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
661 u_int8_t *ms_ident, u_int8_t chan_needed)
662{
663 struct abis_rsl_dchan_hdr *dh;
664 struct msgb *msg = rsl_msgb_alloc();
665
666 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
667 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
668 dh->chan_nr = RSL_CHAN_PCH_AGCH;
669
670 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
671 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
672 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
673
674 msg->trx = bts->c0;
675
676 return abis_rsl_sendmsg(msg);
677}
678
Harald Welte59b04682009-06-10 05:40:52 +0800679int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
680{
681 int i, len = strlen(str_in);
682
683 for (i = 0; i < len; i++) {
684 int num = str_in[i] - 0x30;
685 if (num < 0 || num > 9)
686 return -1;
687 if (i % 2 == 0)
688 bcd_out[i/2] = num;
689 else
690 bcd_out[i/2] |= (num << 4);
691 }
692
693 return 0;
694}
695
696/* Chapter 8.5.6 */
697int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val)
698{
699 struct msgb *msg = rsl_msgb_alloc();
700 struct abis_rsl_dchan_hdr *dh;
701 u_int8_t buf[MACBLOCK_SIZE];
702
703 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
704 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
705 dh->chan_nr = RSL_CHAN_PCH_AGCH;
706
707 switch (bts->type) {
708 case GSM_BTS_TYPE_BS11:
709 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
710 break;
711 default:
712 /* If phase 2, construct a FULL_IMM_ASS_INFO */
713 pad_macblock(buf, val, len);
714 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
715 break;
716 }
717
718 msg->trx = bts->c0;
719
720 return abis_rsl_sendmsg(msg);
721}
722
Harald Welte4684e632009-08-10 09:51:40 +0200723/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte12090752009-08-10 10:07:33 +0200724int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte4684e632009-08-10 09:51:40 +0200725{
726 struct msgb *msg = rsl_msgb_alloc();
727 struct abis_rsl_dchan_hdr *dh;
728
729 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
730 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte874a5b42009-08-10 11:26:14 +0200731 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Welte4684e632009-08-10 09:51:40 +0200732 dh->chan_nr = lchan2chan_nr(lchan);
Harald Welte12090752009-08-10 10:07:33 +0200733 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(u_int8_t *)mrpci);
Harald Welte4684e632009-08-10 09:51:40 +0200734
Harald Weltede4477a2009-12-24 12:20:20 +0100735 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100736 gsm_lchan_name(lchan), *(u_int8_t *)mrpci);
Harald Welte874a5b42009-08-10 11:26:14 +0200737
738 msg->trx = lchan->ts->trx;
739
Harald Welte4684e632009-08-10 09:51:40 +0200740 return abis_rsl_sendmsg(msg);
741}
742
743
Harald Welte59b04682009-06-10 05:40:52 +0800744/* Send "DATA REQUEST" message with given L3 Info payload */
745/* Chapter 8.3.1 */
746int rsl_data_request(struct msgb *msg, u_int8_t link_id)
747{
Harald Welte59b04682009-06-10 05:40:52 +0800748 if (msg->lchan == NULL) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100749 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte59b04682009-06-10 05:40:52 +0800750 return -EINVAL;
751 }
752
Harald Weltea22d36b2010-03-04 10:33:10 +0100753 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, lchan2chan_nr(msg->lchan),
754 link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800755
756 msg->trx = msg->lchan->ts->trx;
757
758 return abis_rsl_sendmsg(msg);
759}
760
Harald Welteed9a5ab2009-08-09 13:47:35 +0200761/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
762/* Chapter 8.3.1 */
763int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id)
764{
Harald Weltea22d36b2010-03-04 10:33:10 +0100765 struct msgb *msg;
Harald Welteed9a5ab2009-08-09 13:47:35 +0200766
Harald Weltea22d36b2010-03-04 10:33:10 +0100767 msg = rsl_rll_simple(RSL_MT_EST_REQ, lchan2chan_nr(lchan),
768 link_id, 0);
Harald Welteed9a5ab2009-08-09 13:47:35 +0200769 msg->trx = lchan->ts->trx;
770
771 return abis_rsl_sendmsg(msg);
772}
773
Harald Welte0f2e3c12009-08-08 13:15:07 +0200774/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
775 This is what higher layers should call. The BTS then responds with
776 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
777 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
778 lchan_free() */
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800779int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t reason)
Harald Welte0f2e3c12009-08-08 13:15:07 +0200780{
Harald Welte0f2e3c12009-08-08 13:15:07 +0200781
Harald Weltea22d36b2010-03-04 10:33:10 +0100782 struct msgb *msg;
783
784 msg = rsl_rll_simple(RSL_MT_REL_REQ, lchan2chan_nr(lchan),
785 link_id, 0);
Holger Hans Peter Freytherbcea9a72010-06-08 11:57:45 +0800786 /* 0 is normal release, 1 is local end */
787 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, reason);
Harald Welte0f2e3c12009-08-08 13:15:07 +0200788
Harald Weltec88a4432009-12-29 10:44:17 +0100789 /* FIXME: start some timer in case we don't receive a REL ACK ? */
790
Harald Welte0f2e3c12009-08-08 13:15:07 +0200791 msg->trx = lchan->ts->trx;
792
793 return abis_rsl_sendmsg(msg);
794}
795
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200796int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
797{
798 lchan->state = state;
799 return 0;
800}
801
Harald Welte59b04682009-06-10 05:40:52 +0800802/* Chapter 8.4.2: Channel Activate Acknowledge */
803static int rsl_rx_chan_act_ack(struct msgb *msg)
804{
805 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
806
807 /* BTS has confirmed channel activation, we now need
808 * to assign the activated channel to the MS */
809 if (rslh->ie_chan != RSL_IE_CHAN_NR)
810 return -EINVAL;
Harald Welte6720a432009-11-29 22:45:52 +0100811
Harald Weltec88a4432009-12-29 10:44:17 +0100812 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welteab2534c2009-12-29 10:52:38 +0100813 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
814 gsm_lchan_name(msg->lchan),
815 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200816 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welte4baa9c52009-12-21 13:27:11 +0100817
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +0800818 if (msg->lchan->rqd_ref) {
819 rsl_send_imm_assignment(msg->lchan);
820 talloc_free(msg->lchan->rqd_ref);
821 msg->lchan->rqd_ref = NULL;
822 msg->lchan->rqd_ta = 0;
823 }
824
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100825 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100826
Harald Welte59b04682009-06-10 05:40:52 +0800827 return 0;
828}
829
830/* Chapter 8.4.3: Channel Activate NACK */
831static int rsl_rx_chan_act_nack(struct msgb *msg)
832{
833 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
834 struct tlv_parsed tp;
835
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100836 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100837 gsm_lchan_name(msg->lchan));
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100838
Harald Welte59b04682009-06-10 05:40:52 +0800839 /* BTS has rejected channel activation ?!? */
840 if (dh->ie_chan != RSL_IE_CHAN_NR)
841 return -EINVAL;
842
843 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100844 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
845 const u_int8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
846 print_rsl_cause(LOGL_ERROR, cause,
Harald Weltef1a168d2009-07-28 17:58:09 +0200847 TLVP_LEN(&tp, RSL_IE_CAUSE));
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100848 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200849 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +0100850 } else
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +0200851 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200852
Harald Welte (local)ed6d7622009-12-27 11:48:11 +0100853 LOGPC(DRSL, LOGL_ERROR, "\n");
854
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100855 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +0100856
Harald Weltecddb9802009-08-09 19:50:08 +0200857 lchan_free(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +0800858 return 0;
859}
860
861/* Chapter 8.4.4: Connection Failure Indication */
862static int rsl_rx_conn_fail(struct msgb *msg)
863{
864 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
865 struct tlv_parsed tp;
866
Harald Weltecf2ec4a2009-12-17 23:10:46 +0100867 /* FIXME: print which channel */
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100868 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +0100869 gsm_lchan_name(msg->lchan));
Harald Welte59b04682009-06-10 05:40:52 +0800870
871 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
872
Harald Weltef1a168d2009-07-28 17:58:09 +0200873 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +0100874 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +0200875 TLVP_LEN(&tp, RSL_IE_CAUSE));
876
Harald Welte (local)4bd76642009-12-26 22:33:09 +0100877 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte59b04682009-06-10 05:40:52 +0800878 /* FIXME: only free it after channel release ACK */
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +0200879 counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +0800880 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800881}
882
Harald Weltec20bd1d2009-11-29 19:07:28 +0100883static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
884 const char *prefix)
885{
Harald Welte0e4fa782009-12-16 16:52:07 +0100886 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
887 prefix, rxlev2dbm(mru->full.rx_lev),
888 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Weltec20bd1d2009-11-29 19:07:28 +0100889 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
890 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
891}
892
893static void print_meas_rep(struct gsm_meas_rep *mr)
894{
Harald Welte0e4fa782009-12-16 16:52:07 +0100895 int i;
896
Harald Weltec20bd1d2009-11-29 19:07:28 +0100897 DEBUGP(DMEAS, "MEASUREMENT RESULT NR=%d ", mr->nr);
898
899 if (mr->flags & MEAS_REP_F_DL_DTX)
900 DEBUGPC(DMEAS, "DTXd ");
901
902 print_meas_rep_uni(&mr->ul, "ul");
903 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
904 if (mr->flags & MEAS_REP_F_MS_TO)
905 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
906
907 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte0e4fa782009-12-16 16:52:07 +0100908 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100909 DEBUGPC(DMEAS, "L1_FPC=%u ",
910 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
911 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
912 }
913
914 if (mr->flags & MEAS_REP_F_UL_DTX)
915 DEBUGPC(DMEAS, "DTXu ");
916 if (mr->flags & MEAS_REP_F_BA1)
917 DEBUGPC(DMEAS, "BA1 ");
918 if (!(mr->flags & MEAS_REP_F_DL_VALID))
919 DEBUGPC(DMEAS, "NOT VALID ");
920 else
921 print_meas_rep_uni(&mr->dl, "dl");
922
923 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte0b833f82009-12-19 18:33:05 +0100924 if (mr->num_cell == 7)
925 return;
Harald Welte0e4fa782009-12-16 16:52:07 +0100926 for (i = 0; i < mr->num_cell; i++) {
927 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte350c2d32009-12-25 23:02:22 +0100928 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
929 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte0e4fa782009-12-16 16:52:07 +0100930 }
Harald Weltec20bd1d2009-11-29 19:07:28 +0100931}
932
Harald Welte59b04682009-06-10 05:40:52 +0800933static int rsl_rx_meas_res(struct msgb *msg)
934{
935 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
936 struct tlv_parsed tp;
Harald Weltef9476812009-12-15 21:36:05 +0100937 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100938 u_int8_t len;
939 const u_int8_t *val;
940 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800941
Harald Welte4baa9c52009-12-21 13:27:11 +0100942 /* check if this channel is actually active */
943 /* FIXME: maybe this check should be way more generic/centralized */
Harald Weltec88a4432009-12-29 10:44:17 +0100944 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freyther67a2e292010-07-29 14:50:57 +0800945 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Weltec88a4432009-12-29 10:44:17 +0100946 gsm_lchan_name(msg->lchan));
Harald Welte4baa9c52009-12-21 13:27:11 +0100947 return 0;
Harald Weltec88a4432009-12-29 10:44:17 +0100948 }
Harald Welte4baa9c52009-12-21 13:27:11 +0100949
Harald Weltef9476812009-12-15 21:36:05 +0100950 memset(mr, 0, sizeof(*mr));
Harald Welteaa0efa12009-12-16 23:29:34 +0100951 mr->lchan = msg->lchan;
Harald Welte4efcc542009-11-30 19:16:47 +0100952
Harald Welte59b04682009-06-10 05:40:52 +0800953 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
954
Harald Weltec20bd1d2009-11-29 19:07:28 +0100955 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
956 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
957 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
958 return -EIO;
959
960 /* Mandatory Parts */
Harald Weltef9476812009-12-15 21:36:05 +0100961 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100962
963 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
964 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
965 if (len >= 3) {
966 if (val[0] & 0x40)
Harald Weltef9476812009-12-15 21:36:05 +0100967 mr->flags |= MEAS_REP_F_DL_DTX;
968 mr->ul.full.rx_lev = val[0] & 0x3f;
969 mr->ul.sub.rx_lev = val[1] & 0x3f;
970 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
971 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte59b04682009-06-10 05:40:52 +0800972 }
Harald Weltec20bd1d2009-11-29 19:07:28 +0100973
Harald Weltef9476812009-12-15 21:36:05 +0100974 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100975
976 /* Optional Parts */
Harald Welte59b04682009-06-10 05:40:52 +0800977 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Weltef9476812009-12-15 21:36:05 +0100978 mr->ms_timing_offset =
Harald Weltec20bd1d2009-11-29 19:07:28 +0100979 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
980
Harald Weltea1467eb2009-06-20 18:44:35 +0200981 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Harald Weltec20bd1d2009-11-29 19:07:28 +0100982 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltef9476812009-12-15 21:36:05 +0100983 mr->flags |= MEAS_REP_F_MS_L1;
984 mr->ms_l1.pwr = ms_pwr_dbm(msg->trx->bts->band, val[0] >> 3);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100985 if (val[0] & 0x04)
Harald Weltef9476812009-12-15 21:36:05 +0100986 mr->flags |= MEAS_REP_F_FPC;
987 mr->ms_l1.ta = val[1];
Harald Weltea1467eb2009-06-20 18:44:35 +0200988 }
Harald Welte59b04682009-06-10 05:40:52 +0800989 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freyther6d0c8b42009-10-22 15:43:55 +0200990 msg->l3h = (u_int8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Weltef9476812009-12-15 21:36:05 +0100991 rc = gsm48_parse_meas_rep(mr, msg);
Harald Weltec20bd1d2009-11-29 19:07:28 +0100992 if (rc < 0)
993 return rc;
994 }
995
Harald Weltef9476812009-12-15 21:36:05 +0100996 print_meas_rep(mr);
Harald Welte59b04682009-06-10 05:40:52 +0800997
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +0100998 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Welte4efcc542009-11-30 19:16:47 +0100999
Harald Welte59b04682009-06-10 05:40:52 +08001000 return 0;
1001}
1002
Harald Welte6720a432009-11-29 22:45:52 +01001003/* Chapter 8.4.7 */
1004static int rsl_rx_hando_det(struct msgb *msg)
1005{
1006 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1007 struct tlv_parsed tp;
1008
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001009 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welte6720a432009-11-29 22:45:52 +01001010
1011 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1012
1013 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1014 DEBUGPC(DRSL, "access delay = %u\n",
1015 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1016 else
1017 DEBUGPC(DRSL, "\n");
1018
Holger Hans Peter Freyther645b3832010-12-27 13:28:20 +01001019 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welte6720a432009-11-29 22:45:52 +01001020
1021 return 0;
1022}
1023
Harald Welte59b04682009-06-10 05:40:52 +08001024static int abis_rsl_rx_dchan(struct msgb *msg)
1025{
1026 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1027 int rc = 0;
1028 char *ts_name;
1029
1030 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001031 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001032
Harald Welte59b04682009-06-10 05:40:52 +08001033 switch (rslh->c.msg_type) {
1034 case RSL_MT_CHAN_ACTIV_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001035 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001036 rc = rsl_rx_chan_act_ack(msg);
1037 break;
1038 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001039 rc = rsl_rx_chan_act_nack(msg);
1040 break;
1041 case RSL_MT_CONN_FAIL:
1042 rc = rsl_rx_conn_fail(msg);
1043 break;
1044 case RSL_MT_MEAS_RES:
1045 rc = rsl_rx_meas_res(msg);
1046 break;
Harald Welte6720a432009-11-29 22:45:52 +01001047 case RSL_MT_HANDO_DET:
1048 rc = rsl_rx_hando_det(msg);
1049 break;
Harald Welte59b04682009-06-10 05:40:52 +08001050 case RSL_MT_RF_CHAN_REL_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001051 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", ts_name);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001052 if (msg->lchan->state != LCHAN_S_REL_REQ && msg->lchan->state != LCHAN_S_REL_ERR)
Harald Welteab2534c2009-12-29 10:52:38 +01001053 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
1054 gsm_lchan_name(msg->lchan),
1055 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001056 bsc_del_timer(&msg->lchan->T3111);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001057 /* we have an error timer pending to release that */
1058 if (msg->lchan->state != LCHAN_S_REL_ERR)
1059 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Harald Welte59b04682009-06-10 05:40:52 +08001060 lchan_free(msg->lchan);
1061 break;
1062 case RSL_MT_MODE_MODIFY_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001063 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001064 break;
1065 case RSL_MT_MODE_MODIFY_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001066 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001067 break;
Harald Welteaed946e2009-10-24 10:29:22 +02001068 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001069 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001070 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001071 break;
1072 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001073 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001074 break;
1075 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001076 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte2b361522010-03-28 14:42:09 +08001077 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welteaed946e2009-10-24 10:29:22 +02001078 break;
1079 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001080 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welteaed946e2009-10-24 10:29:22 +02001081 break;
Harald Welte59b04682009-06-10 05:40:52 +08001082 case RSL_MT_PHY_CONTEXT_CONF:
1083 case RSL_MT_PREPROC_MEAS_RES:
1084 case RSL_MT_TALKER_DET:
1085 case RSL_MT_LISTENER_DET:
1086 case RSL_MT_REMOTE_CODEC_CONF_REP:
1087 case RSL_MT_MR_CODEC_MOD_ACK:
1088 case RSL_MT_MR_CODEC_MOD_NACK:
1089 case RSL_MT_MR_CODEC_MOD_PER:
Harald Weltede4477a2009-12-24 12:20:20 +01001090 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1091 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001092 break;
1093 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001094 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1095 ts_name, rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001096 return -EINVAL;
1097 }
1098
1099 return rc;
1100}
1101
1102static int rsl_rx_error_rep(struct msgb *msg)
1103{
1104 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Weltef1a168d2009-07-28 17:58:09 +02001105 struct tlv_parsed tp;
Harald Welte59b04682009-06-10 05:40:52 +08001106
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001107 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(msg->trx));
Harald Weltef1a168d2009-07-28 17:58:09 +02001108
1109 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1110
1111 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001112 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001113 TLVP_LEN(&tp, RSL_IE_CAUSE));
1114
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001115 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte59b04682009-06-10 05:40:52 +08001116
1117 return 0;
1118}
1119
1120static int abis_rsl_rx_trx(struct msgb *msg)
1121{
1122 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
1123 int rc = 0;
1124
1125 switch (rslh->msg_type) {
1126 case RSL_MT_ERROR_REPORT:
1127 rc = rsl_rx_error_rep(msg);
1128 break;
1129 case RSL_MT_RF_RES_IND:
1130 /* interference on idle channels of TRX */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001131 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(msg->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001132 break;
1133 case RSL_MT_OVERLOAD:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001134 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001135 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
1136 gsm_trx_name(msg->trx));
Harald Welte59b04682009-06-10 05:40:52 +08001137 break;
1138 default:
Harald Welte (local)ab788cf2009-12-28 23:14:22 +01001139 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
1140 "type 0x%02x\n", gsm_trx_name(msg->trx), rslh->msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001141 return -EINVAL;
1142 }
1143 return rc;
1144}
1145
Harald Welte427dbc42009-08-10 00:26:10 +02001146/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1147static void t3101_expired(void *data)
1148{
1149 struct gsm_lchan *lchan = data;
1150
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001151 rsl_rf_chan_release(lchan, 1);
Harald Welte427dbc42009-08-10 00:26:10 +02001152}
1153
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001154/* If T3111 expires, we will send the RF Channel Request */
1155static void t3111_expired(void *data)
1156{
1157 struct gsm_lchan *lchan = data;
1158
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001159 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001160}
1161
laforge50312e82010-06-21 12:08:52 +02001162#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1163
Harald Weltea00fdd72010-12-23 14:39:29 +01001164/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1165static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1166 unsigned int num_req_refs,
1167 struct gsm48_req_ref *rqd_refs,
1168 uint8_t wait_ind)
1169{
1170 uint8_t buf[GSM_MACBLOCK_LEN];
1171 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1172
1173 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1174 memset(iar, 0, sizeof(*iar));
1175 iar->proto_discr = GSM48_PDISC_RR;
1176 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1177 iar->page_mode = GSM48_PM_SAME;
1178
1179 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1180 iar->wait_ind1 = wait_ind;
1181
1182 if (num_req_refs >= 2)
1183 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1184 else
1185 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1186 iar->wait_ind2 = wait_ind;
1187
1188 if (num_req_refs >= 3)
1189 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1190 else
1191 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1192 iar->wait_ind3 = wait_ind;
1193
1194 if (num_req_refs >= 4)
1195 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1196 else
1197 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1198 iar->wait_ind4 = wait_ind;
1199
1200 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1201}
1202
Harald Welte59b04682009-06-10 05:40:52 +08001203/* MS has requested a channel on the RACH */
1204static int rsl_rx_chan_rqd(struct msgb *msg)
1205{
1206 struct gsm_bts *bts = msg->trx->bts;
1207 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1208 struct gsm48_req_ref *rqd_ref;
Harald Welte59b04682009-06-10 05:40:52 +08001209 enum gsm_chan_t lctype;
1210 enum gsm_chreq_reason_t chreq_reason;
1211 struct gsm_lchan *lchan;
1212 u_int8_t rqd_ta;
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001213 int is_lu;
Harald Welte59b04682009-06-10 05:40:52 +08001214
1215 u_int16_t arfcn;
1216 u_int8_t ts_number, subch;
1217
1218 /* parse request reference to be used in immediate assign */
1219 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1220 return -EINVAL;
1221
1222 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1223
1224 /* parse access delay and use as TA */
1225 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1226 return -EINVAL;
1227 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1228
1229 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1230 * request reference RA */
Holger Hans Peter Freytherf0f37f12010-09-06 09:36:02 +08001231 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1232 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte59b04682009-06-10 05:40:52 +08001233
Harald Weltebdbb7442009-12-22 19:07:32 +01001234 counter_inc(bts->network->stats.chreq.total);
Harald Welte3edc5a92009-12-22 00:41:05 +01001235
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001236 /*
1237 * We want LOCATION UPDATES to succeed and will assign a TCH
1238 * if we have no SDCCH available.
1239 */
1240 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1241
Harald Welte59b04682009-06-10 05:40:52 +08001242 /* check availability / allocate channel */
Holger Hans Peter Freytherdb392032010-09-06 08:58:42 +08001243 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte59b04682009-06-10 05:40:52 +08001244 if (!lchan) {
Harald Welte (local)e0bb5fa2009-12-27 13:48:09 +01001245 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)02204d02009-12-27 18:05:25 +01001246 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Harald Weltebdbb7442009-12-22 19:07:32 +01001247 counter_inc(bts->network->stats.chreq.no_channel);
Harald Weltea00fdd72010-12-23 14:39:29 +01001248 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1249 if (bts->network->T3122)
1250 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte59b04682009-06-10 05:40:52 +08001251 return -ENOMEM;
1252 }
1253
Harald Weltec88a4432009-12-29 10:44:17 +01001254 if (lchan->state != LCHAN_S_NONE)
1255 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welteab2534c2009-12-29 10:52:38 +01001256 "in state %s\n", gsm_lchan_name(lchan),
1257 gsm_lchans_name(lchan->state));
Holger Hans Peter Freyther68914a02010-04-10 00:12:31 +02001258 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Harald Welte (local)c3be50c2009-12-27 18:12:29 +01001259
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001260 /* save the RACH data as we need it after the CHAN ACT ACK */
1261 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1262 if (!lchan->rqd_ref) {
1263 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1264 lchan_free(lchan);
1265 return -ENOMEM;
1266 }
1267
1268 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1269 lchan->rqd_ta = rqd_ta;
1270
Harald Welte59b04682009-06-10 05:40:52 +08001271 ts_number = lchan->ts->nr;
1272 arfcn = lchan->ts->trx->arfcn;
1273 subch = lchan->nr;
1274
Harald Welted2dd9de2009-08-30 15:37:11 +09001275 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)cbd46102009-08-13 10:14:26 +02001276 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte9a229e12009-08-10 00:45:40 +02001277 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte39274f42009-07-29 15:41:29 +02001278 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte77234e12009-08-28 23:28:28 +09001279 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001280
1281 /* FIXME: Start another timer or assume the BTS sends a ACK/NACK? */
Harald Welteb90d7bd2009-12-17 00:31:10 +01001282 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001283
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001284 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1285 "r=%s ra=0x%02x\n", gsm_lchan_name(lchan), arfcn, subch,
1286 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1287 rqd_ref->ra);
1288 return 0;
1289}
1290
1291static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1292{
1293 struct gsm_bts *bts = lchan->ts->trx->bts;
1294 u_int8_t buf[GSM_MACBLOCK_LEN];
1295 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1296
Harald Welte59b04682009-06-10 05:40:52 +08001297 /* create IMMEDIATE ASSIGN 04.08 messge */
laforgee06d5982010-06-20 15:18:46 +02001298 memset(ia, 0, sizeof(*ia));
laforge50312e82010-06-21 12:08:52 +02001299 /* we set ia->l2_plen once we know the length of the MA below */
laforgee06d5982010-06-20 15:18:46 +02001300 ia->proto_discr = GSM48_PDISC_RR;
1301 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1302 ia->page_mode = GSM48_PM_SAME;
1303 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea42a93f2010-06-14 22:26:10 +02001304
Harald Welte59b04682009-06-10 05:40:52 +08001305 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001306 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1307 ia->timing_advance = lchan->rqd_ta;
Harald Weltea42a93f2010-06-14 22:26:10 +02001308 if (!lchan->ts->hopping.enabled) {
laforgee06d5982010-06-20 15:18:46 +02001309 ia->mob_alloc_len = 0;
Harald Weltea42a93f2010-06-14 22:26:10 +02001310 } else {
laforgee06d5982010-06-20 15:18:46 +02001311 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1312 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea42a93f2010-06-14 22:26:10 +02001313 }
Harald Welte07f32182010-06-28 18:41:27 +02001314 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1315 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte59b04682009-06-10 05:40:52 +08001316
Harald Welte427dbc42009-08-10 00:26:10 +02001317 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1318 lchan->T3101.cb = t3101_expired;
1319 lchan->T3101.data = lchan;
Holger Hans Peter Freyther26ba2e72009-11-21 21:18:38 +01001320 bsc_schedule_timer(&lchan->T3101, bts->network->T3101, 0);
Harald Welte59b04682009-06-10 05:40:52 +08001321
1322 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freytherc08f6f02010-06-22 12:11:59 +08001323 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (u_int8_t *) ia);
Harald Welte59b04682009-06-10 05:40:52 +08001324}
1325
1326/* MS has requested a channel on the RACH */
1327static int rsl_rx_ccch_load(struct msgb *msg)
1328{
1329 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1330 u_int16_t pg_buf_space;
1331 u_int16_t rach_slot_count = -1;
1332 u_int16_t rach_busy_count = -1;
1333 u_int16_t rach_access_count = -1;
1334
1335 switch (rslh->data[0]) {
1336 case RSL_IE_PAGING_LOAD:
1337 pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
Harald Welte008a4922010-04-19 10:24:07 +02001338 if (is_ipaccess_bts(msg->trx->bts) && pg_buf_space == 0xffff) {
1339 /* paging load below configured threshold, use 50 as default */
1340 pg_buf_space = 50;
1341 }
Harald Welte59b04682009-06-10 05:40:52 +08001342 paging_update_buffer_space(msg->trx->bts, pg_buf_space);
1343 break;
1344 case RSL_IE_RACH_LOAD:
1345 if (msg->data_len >= 7) {
1346 rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1347 rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1348 rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1349 }
1350 break;
1351 default:
1352 break;
1353 }
1354
1355 return 0;
1356}
1357
1358static int abis_rsl_rx_cchan(struct msgb *msg)
1359{
1360 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1361 int rc = 0;
1362
1363 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
1364
1365 switch (rslh->c.msg_type) {
1366 case RSL_MT_CHAN_RQD:
1367 /* MS has requested a channel on the RACH */
1368 rc = rsl_rx_chan_rqd(msg);
1369 break;
1370 case RSL_MT_CCCH_LOAD_IND:
1371 /* current load on the CCCH */
1372 rc = rsl_rx_ccch_load(msg);
1373 break;
1374 case RSL_MT_DELETE_IND:
1375 /* CCCH overloaded, IMM_ASSIGN was dropped */
1376 case RSL_MT_CBCH_LOAD_IND:
1377 /* current load on the CBCH */
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001378 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1379 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001380 break;
1381 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001382 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1383 "0x%02x\n", rslh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001384 return -EINVAL;
1385 }
1386
1387 return rc;
1388}
1389
1390static int rsl_rx_rll_err_ind(struct msgb *msg)
1391{
1392 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1393 u_int8_t *rlm_cause = rllh->data;
1394
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001395 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001396 gsm_lchan_name(msg->lchan),
Harald Welteb30935e2010-03-25 12:13:02 +08001397 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteed9a5ab2009-08-09 13:47:35 +02001398
1399 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)bd76cce2009-12-26 23:55:00 +01001400
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001401 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
1402 counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther10ea12f2010-05-31 21:38:24 +08001403 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther27942e92010-04-17 06:48:29 +02001404 }
Harald Welte692f5852009-07-04 09:40:05 +02001405
Harald Welte59b04682009-06-10 05:40:52 +08001406 return 0;
1407}
1408
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001409static void rsl_handle_release(struct gsm_lchan *lchan)
1410{
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001411 int sapi;
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001412 struct gsm_bts *bts;
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001413
1414 /* maybe we have only brought down one RLL */
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001415 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001416 return;
1417
1418 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1419 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1420 continue;
Harald Welte497aa982010-12-24 12:51:07 +01001421 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001422 gsm_lchan_name(lchan), sapi);
1423 return;
1424 }
1425
Holger Hans Peter Freytherd26cbc82010-04-08 22:47:44 +02001426
1427
Holger Hans Peter Freyther4a00c062010-05-31 21:33:15 +08001428 /* wait a bit to send the RF Channel Release */
1429 lchan->T3111.cb = t3111_expired;
1430 lchan->T3111.data = lchan;
1431 bts = lchan->ts->trx->bts;
1432 bsc_schedule_timer(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001433}
1434
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001435/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte59b04682009-06-10 05:40:52 +08001436 0x02, 0x06,
1437 0x01, 0x20,
1438 0x02, 0x00,
1439 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1440
1441static int abis_rsl_rx_rll(struct msgb *msg)
1442{
1443 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1444 int rc = 0;
1445 char *ts_name;
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001446 u_int8_t sapi = rllh->link_id & 7;
Harald Welte59b04682009-06-10 05:40:52 +08001447
1448 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001449 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltede4477a2009-12-24 12:20:20 +01001450 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte59b04682009-06-10 05:40:52 +08001451
1452 switch (rllh->c.msg_type) {
1453 case RSL_MT_DATA_IND:
1454 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001455 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001456 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1457 rllh->data[0] == RSL_IE_L3_INFO) {
1458 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001459 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001460 }
1461 break;
1462 case RSL_MT_EST_IND:
1463 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte427dbc42009-08-10 00:26:10 +02001464 /* lchan is established, stop T3101 */
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001465 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Harald Welte427dbc42009-08-10 00:26:10 +02001466 bsc_del_timer(&msg->lchan->T3101);
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +02001467 if (msgb_l2len(msg) >
Harald Welte59b04682009-06-10 05:40:52 +08001468 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1469 rllh->data[0] == RSL_IE_L3_INFO) {
1470 msg->l3h = &rllh->data[3];
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001471 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001472 }
1473 break;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001474 case RSL_MT_EST_CONF:
Harald Welte61402172009-08-09 14:13:58 +02001475 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001476 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001477 rll_indication(msg->lchan, rllh->link_id,
1478 BSC_RLLR_IND_EST_CONF);
1479 break;
Harald Welte59b04682009-06-10 05:40:52 +08001480 case RSL_MT_REL_IND:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001481 /* BTS informs us of having received DISC from MS */
Harald Welteb6601442009-08-04 02:50:21 +02001482 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001483 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteed9a5ab2009-08-09 13:47:35 +02001484 rll_indication(msg->lchan, rllh->link_id,
1485 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001486 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001487 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001488 break;
1489 case RSL_MT_REL_CONF:
Harald Welte0f2e3c12009-08-08 13:15:07 +02001490 /* BTS informs us of having received UA from MS,
1491 * in response to DISC that we've sent earlier */
Harald Welteb6601442009-08-04 02:50:21 +02001492 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freytherd8318052009-10-28 14:23:39 +01001493 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freyther65f08522010-04-08 22:39:34 +02001494 rsl_handle_release(msg->lchan);
Holger Hans Peter Freyther3fdf5b92010-07-29 17:09:36 +08001495 rsl_lchan_rll_release(msg->lchan, rllh->link_id);
Harald Welte59b04682009-06-10 05:40:52 +08001496 break;
1497 case RSL_MT_ERROR_IND:
Harald Welte59b04682009-06-10 05:40:52 +08001498 rc = rsl_rx_rll_err_ind(msg);
1499 break;
1500 case RSL_MT_UNIT_DATA_IND:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001501 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1502 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001503 break;
1504 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001505 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1506 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001507 }
Harald Welte59b04682009-06-10 05:40:52 +08001508 return rc;
1509}
1510
Harald Welteb284b472009-12-02 01:58:23 +05301511static u_int8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Welte98d79f92009-07-28 18:11:56 +02001512{
Harald Welteb284b472009-12-02 01:58:23 +05301513 switch (lchan->tch_mode) {
Harald Welte98d79f92009-07-28 18:11:56 +02001514 case GSM48_CMODE_SPEECH_V1:
Harald Welteb284b472009-12-02 01:58:23 +05301515 switch (lchan->type) {
1516 case GSM_LCHAN_TCH_F:
1517 return 0x00;
1518 case GSM_LCHAN_TCH_H:
1519 return 0x03;
1520 default:
1521 break;
1522 }
Harald Welte98d79f92009-07-28 18:11:56 +02001523 case GSM48_CMODE_SPEECH_EFR:
Harald Welteb284b472009-12-02 01:58:23 +05301524 switch (lchan->type) {
1525 case GSM_LCHAN_TCH_F:
1526 return 0x01;
1527 /* there's no half-rate EFR */
1528 default:
1529 break;
1530 }
Harald Welte98d79f92009-07-28 18:11:56 +02001531 case GSM48_CMODE_SPEECH_AMR:
Harald Welteb284b472009-12-02 01:58:23 +05301532 switch (lchan->type) {
1533 case GSM_LCHAN_TCH_F:
1534 return 0x02;
1535 case GSM_LCHAN_TCH_H:
1536 return 0x05;
1537 default:
1538 break;
1539 }
1540 default:
1541 break;
Harald Welte98d79f92009-07-28 18:11:56 +02001542 }
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001543 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welteb284b472009-12-02 01:58:23 +05301544 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001545 return 0;
Harald Welte98d79f92009-07-28 18:11:56 +02001546}
1547
Sylvain Munaut1338a552009-12-20 22:06:40 +01001548static u_int8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
1549{
Holger Hans Peter Freyther6651b692010-11-14 21:09:08 +01001550 struct gsm_network *net = lchan->ts->trx->bts->network;
1551
1552 /* allow to hardcode the rtp payload */
1553 if (net->hardcoded_rtp_payload != 0)
1554 return net->hardcoded_rtp_payload;
1555
Sylvain Munaut1338a552009-12-20 22:06:40 +01001556 switch (lchan->tch_mode) {
1557 case GSM48_CMODE_SPEECH_V1:
1558 switch (lchan->type) {
1559 case GSM_LCHAN_TCH_F:
1560 return RTP_PT_GSM_FULL;
1561 case GSM_LCHAN_TCH_H:
1562 return RTP_PT_GSM_HALF;
1563 default:
1564 break;
1565 }
1566 case GSM48_CMODE_SPEECH_EFR:
1567 switch (lchan->type) {
1568 case GSM_LCHAN_TCH_F:
1569 return RTP_PT_GSM_EFR;
1570 /* there's no half-rate EFR */
1571 default:
1572 break;
1573 }
1574 case GSM48_CMODE_SPEECH_AMR:
1575 switch (lchan->type) {
1576 case GSM_LCHAN_TCH_F:
1577 return RTP_PT_AMR_FULL;
1578 case GSM_LCHAN_TCH_H:
1579 return RTP_PT_AMR_HALF;
1580 default:
1581 break;
1582 }
1583 default:
1584 break;
1585 }
1586 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1587 "tch_mode == 0x%02x\n & lchan_type == %d",
1588 lchan->tch_mode, lchan->type);
1589 return 0;
1590}
1591
Harald Welte59b04682009-06-10 05:40:52 +08001592/* ip.access specific RSL extensions */
Harald Weltebffa4992009-12-19 16:42:06 +01001593static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1594{
1595 struct in_addr ip;
1596 u_int16_t port, conn_id;
1597
1598 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
1599 ip.s_addr = *((u_int32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
1600 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1601 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1602 }
1603
1604 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
1605 port = *((u_int16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
1606 port = ntohs(port);
1607 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1608 lchan->abis_ip.bound_port = port;
1609 }
1610
1611 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
1612 conn_id = *((u_int16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
1613 conn_id = ntohs(conn_id);
1614 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1615 lchan->abis_ip.conn_id = conn_id;
1616 }
1617
1618 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1619 lchan->abis_ip.rtp_payload2 =
1620 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1621 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1622 lchan->abis_ip.rtp_payload2);
1623 }
1624
1625 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1626 lchan->abis_ip.speech_mode =
1627 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1628 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1629 lchan->abis_ip.speech_mode);
1630 }
1631
1632 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
1633 ip.s_addr = *((u_int32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
1634 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1635 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1636 }
1637
1638 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
1639 port = *((u_int16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
1640 port = ntohs(port);
1641 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1642 lchan->abis_ip.connect_port = port;
1643 }
1644}
1645
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001646int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte59b04682009-06-10 05:40:52 +08001647{
1648 struct msgb *msg = rsl_msgb_alloc();
1649 struct abis_rsl_dchan_hdr *dh;
1650
1651 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001652 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte59b04682009-06-10 05:40:52 +08001653 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1654 dh->chan_nr = lchan2chan_nr(lchan);
1655
Harald Welte98d79f92009-07-28 18:11:56 +02001656 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001657 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001658 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltebffa4992009-12-19 16:42:06 +01001659 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001660 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001661
Sylvain Munaut1338a552009-12-20 22:06:40 +01001662 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1663 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1664 lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001665
Harald Welte59b04682009-06-10 05:40:52 +08001666 msg->trx = lchan->ts->trx;
1667
1668 return abis_rsl_sendmsg(msg);
1669}
1670
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001671int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
Harald Weltebffa4992009-12-19 16:42:06 +01001672 u_int8_t rtp_payload2)
Harald Welte59b04682009-06-10 05:40:52 +08001673{
1674 struct msgb *msg = rsl_msgb_alloc();
1675 struct abis_rsl_dchan_hdr *dh;
Harald Weltebffa4992009-12-19 16:42:06 +01001676 u_int32_t *att_ip;
Harald Welte98d79f92009-07-28 18:11:56 +02001677 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +08001678
1679 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001680 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte59b04682009-06-10 05:40:52 +08001681 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1682 dh->chan_nr = lchan2chan_nr(lchan);
1683
Harald Weltebffa4992009-12-19 16:42:06 +01001684 /* we need to store these now as MDCX_ACK does not return them :( */
1685 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1686 lchan->abis_ip.connect_port = port;
1687 lchan->abis_ip.connect_ip = ip;
1688
Harald Weltefb4a9e92009-07-29 12:12:18 +02001689 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Weltebffa4992009-12-19 16:42:06 +01001690 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001691 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Weltefb4a9e92009-07-29 12:12:18 +02001692
Harald Welte98d79f92009-07-28 18:11:56 +02001693 ia.s_addr = htonl(ip);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001694 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1695 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1696 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1697 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Welte98d79f92009-07-28 18:11:56 +02001698
Harald Weltebffa4992009-12-19 16:42:06 +01001699 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1700 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
1701 att_ip = (u_int32_t *) msgb_put(msg, sizeof(ip));
1702 *att_ip = ia.s_addr;
1703 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1704 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munaut1338a552009-12-20 22:06:40 +01001705 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Welte98d79f92009-07-28 18:11:56 +02001706 if (rtp_payload2)
1707 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
1708
Harald Welte59b04682009-06-10 05:40:52 +08001709 msg->trx = lchan->ts->trx;
1710
1711 return abis_rsl_sendmsg(msg);
1712}
1713
Harald Welte9947d9f2009-12-20 16:51:09 +01001714/* tell BTS to connect RTP stream to our local RTP socket */
1715int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1716{
1717 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1718 int rc;
1719
1720 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1721 ntohs(rs->rtp.sin_local.sin_port),
1722 /* FIXME: use RTP payload of bound socket, not BTS*/
1723 lchan->abis_ip.rtp_payload2);
1724
1725 return rc;
1726}
1727
Harald Welte6f40df02010-12-23 12:59:52 +01001728int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welteaed946e2009-10-24 10:29:22 +02001729{
1730 struct msgb *msg = rsl_msgb_alloc();
1731 struct abis_rsl_dchan_hdr *dh;
Harald Welte2b361522010-03-28 14:42:09 +08001732 u_int8_t msg_type;
1733
1734 if (act)
1735 msg_type = RSL_MT_IPAC_PDCH_ACT;
1736 else
1737 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welteaed946e2009-10-24 10:29:22 +02001738
1739 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte2b361522010-03-28 14:42:09 +08001740 init_dchan_hdr(dh, msg_type);
Harald Welteaed946e2009-10-24 10:29:22 +02001741 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Welte6f40df02010-12-23 12:59:52 +01001742 dh->chan_nr = ts2chan_nr(ts, 0);
Harald Welteaed946e2009-10-24 10:29:22 +02001743
Harald Welte6f40df02010-12-23 12:59:52 +01001744 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte2b361522010-03-28 14:42:09 +08001745 act ? "" : "DE");
Harald Welteaed946e2009-10-24 10:29:22 +02001746
Harald Welte6f40df02010-12-23 12:59:52 +01001747 msg->trx = ts->trx;
Harald Welteaed946e2009-10-24 10:29:22 +02001748
1749 return abis_rsl_sendmsg(msg);
1750}
1751
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001752static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001753{
1754 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1755 struct tlv_parsed tv;
Harald Welte87504212009-12-02 01:56:49 +05301756 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001757
1758 /* the BTS has acknowledged a local bind, it now tells us the IP
1759 * address and port number to which it has bound the given logical
1760 * channel */
1761
1762 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1763 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1764 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welteb9498952009-07-12 09:45:05 +02001765 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001766 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte59b04682009-06-10 05:40:52 +08001767 return -EINVAL;
1768 }
Harald Welte50517742009-12-20 15:42:44 +01001769
Harald Weltebffa4992009-12-19 16:42:06 +01001770 ipac_parse_rtp(lchan, &tv);
Harald Welte50517742009-12-20 15:42:44 +01001771
1772 /* in case we don't use direct BTS-to-BTS RTP */
1773 if (!ipacc_rtp_direct) {
1774 int rc;
1775 /* the BTS has successfully bound a TCH to a local ip/port,
1776 * which means we can connect our UDP socket to it */
1777 if (lchan->abis_ip.rtp_socket) {
1778 rtp_socket_free(lchan->abis_ip.rtp_socket);
1779 lchan->abis_ip.rtp_socket = NULL;
1780 }
1781
1782 lchan->abis_ip.rtp_socket = rtp_socket_create();
1783 if (!lchan->abis_ip.rtp_socket)
1784 goto out_err;
1785
1786 rc = rtp_socket_connect(lchan->abis_ip.rtp_socket,
1787 lchan->abis_ip.bound_ip,
1788 lchan->abis_ip.bound_port);
1789 if (rc < 0)
1790 goto out_err;
1791 }
1792
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001793 dispatch_signal(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001794
1795 return 0;
Harald Welte50517742009-12-20 15:42:44 +01001796out_err:
1797 return -EIO;
Harald Welte59b04682009-06-10 05:40:52 +08001798}
1799
Harald Weltebffa4992009-12-19 16:42:06 +01001800static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1801{
1802 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1803 struct tlv_parsed tv;
1804 struct gsm_lchan *lchan = msg->lchan;
1805
1806 /* the BTS has acknowledged a remote connect request and
1807 * it now tells us the IP address and port number to which it has
1808 * connected the given logical channel */
1809
1810 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1811 ipac_parse_rtp(lchan, &tv);
1812 dispatch_signal(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
1813
1814 return 0;
1815}
1816
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001817static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +08001818{
1819 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1820 struct tlv_parsed tv;
Harald Welte50517742009-12-20 15:42:44 +01001821 struct gsm_lchan *lchan = msg->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001822
1823 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte59b04682009-06-10 05:40:52 +08001824
Harald Weltef1a168d2009-07-28 17:58:09 +02001825 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Weltede4477a2009-12-24 12:20:20 +01001826 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Weltef1a168d2009-07-28 17:58:09 +02001827 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte59b04682009-06-10 05:40:52 +08001828
Harald Welte50517742009-12-20 15:42:44 +01001829 /* the BTS tells us a RTP stream has been disconnected */
1830 if (lchan->abis_ip.rtp_socket) {
1831 rtp_socket_free(lchan->abis_ip.rtp_socket);
1832 lchan->abis_ip.rtp_socket = NULL;
1833 }
1834
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001835 dispatch_signal(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welteba4e58d2009-07-28 18:02:05 +02001836
Harald Welte59b04682009-06-10 05:40:52 +08001837 return 0;
1838}
1839
1840static int abis_rsl_rx_ipacc(struct msgb *msg)
1841{
1842 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltede4477a2009-12-24 12:20:20 +01001843 char *ts_name;
Harald Welte59b04682009-06-10 05:40:52 +08001844 int rc = 0;
1845
1846 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Welte (local)c4e9c9c2009-12-27 18:16:36 +01001847 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte59b04682009-06-10 05:40:52 +08001848
1849 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001850 case RSL_MT_IPAC_CRCX_ACK:
Harald Weltede4477a2009-12-24 12:20:20 +01001851 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001852 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001853 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001854 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001855 /* somehow the BTS was unable to bind the lchan to its local
1856 * port?!? */
Harald Weltede4477a2009-12-24 12:20:20 +01001857 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001858 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001859 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte59b04682009-06-10 05:40:52 +08001860 /* the BTS tells us that a connect operation was successful */
Harald Weltede4477a2009-12-24 12:20:20 +01001861 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Weltebffa4992009-12-19 16:42:06 +01001862 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001863 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001864 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte59b04682009-06-10 05:40:52 +08001865 /* somehow the BTS was unable to connect the lchan to a remote
1866 * port */
Harald Weltede4477a2009-12-24 12:20:20 +01001867 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte59b04682009-06-10 05:40:52 +08001868 break;
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001869 case RSL_MT_IPAC_DLCX_IND:
Harald Weltede4477a2009-12-24 12:20:20 +01001870 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther5ea7ea62009-11-18 21:06:12 +01001871 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte59b04682009-06-10 05:40:52 +08001872 break;
1873 default:
Harald Weltede4477a2009-12-24 12:20:20 +01001874 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001875 rllh->c.msg_type);
Harald Welte59b04682009-06-10 05:40:52 +08001876 break;
1877 }
1878 DEBUGPC(DRSL, "\n");
1879
1880 return rc;
1881}
1882
1883
1884/* Entry-point where L2 RSL from BTS enters */
1885int abis_rsl_rcvmsg(struct msgb *msg)
1886{
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001887 struct abis_rsl_common_hdr *rslh;
Harald Welte59b04682009-06-10 05:40:52 +08001888 int rc = 0;
1889
Holger Hans Peter Freytherc7d94092009-11-20 15:14:01 +01001890 if (!msg) {
1891 DEBUGP(DRSL, "Empty RSL msg?..\n");
1892 return -1;
1893 }
1894
1895 if (msgb_l2len(msg) < sizeof(*rslh)) {
1896 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
1897 return -1;
1898 }
1899
1900 rslh = msgb_l2(msg);
1901
Harald Welte59b04682009-06-10 05:40:52 +08001902 switch (rslh->msg_discr & 0xfe) {
1903 case ABIS_RSL_MDISC_RLL:
1904 rc = abis_rsl_rx_rll(msg);
1905 break;
1906 case ABIS_RSL_MDISC_DED_CHAN:
1907 rc = abis_rsl_rx_dchan(msg);
1908 break;
1909 case ABIS_RSL_MDISC_COM_CHAN:
1910 rc = abis_rsl_rx_cchan(msg);
1911 break;
1912 case ABIS_RSL_MDISC_TRX:
1913 rc = abis_rsl_rx_trx(msg);
1914 break;
1915 case ABIS_RSL_MDISC_LOC:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001916 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte59b04682009-06-10 05:40:52 +08001917 rslh->msg_discr);
1918 break;
1919 case ABIS_RSL_MDISC_IPACCESS:
1920 rc = abis_rsl_rx_ipacc(msg);
1921 break;
1922 default:
Harald Weltecf2ec4a2009-12-17 23:10:46 +01001923 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
1924 "0x%02x\n", rslh->msg_discr);
Harald Welte59b04682009-06-10 05:40:52 +08001925 return -EINVAL;
1926 }
1927 msgb_free(msg);
1928 return rc;
1929}
1930
Harald Welte59b04682009-06-10 05:40:52 +08001931/* From Table 10.5.33 of GSM 04.08 */
1932int rsl_number_of_paging_subchannels(struct gsm_bts *bts)
1933{
Harald Weltea54a2bb2009-12-01 18:04:30 +05301934 if (bts->si_common.chan_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) {
1935 return MAX(1, (3 - bts->si_common.chan_desc.bs_ag_blks_res))
1936 * (bts->si_common.chan_desc.bs_pa_mfrms + 2);
Harald Welte59b04682009-06-10 05:40:52 +08001937 } else {
Harald Weltea54a2bb2009-12-01 18:04:30 +05301938 return (9 - bts->si_common.chan_desc.bs_ag_blks_res)
1939 * (bts->si_common.chan_desc.bs_pa_mfrms + 2);
Harald Welte59b04682009-06-10 05:40:52 +08001940 }
1941}
Holger Hans Peter Freytherb67f4082010-07-21 15:54:32 +08001942
1943int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
1944 uint8_t cb_command, const uint8_t *data, int len)
1945{
1946 struct abis_rsl_dchan_hdr *dh;
1947 struct msgb *cb_cmd;
1948
1949 cb_cmd = rsl_msgb_alloc();
1950 if (!cb_cmd)
1951 return -1;
1952
1953 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
1954 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
1955 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
1956
1957 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
1958 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
1959
1960 cb_cmd->trx = bts->c0;
1961
1962 return abis_rsl_sendmsg(cb_cmd);
1963}