blob: 6785be2e809fc7fa6d2cd919a61e74b202dd7173 [file] [log] [blame]
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001/* GSM Radio Signalling Link messages on the A-bis interface
Harald Welte52b1f982008-12-23 20:25:15 +00002 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Welte3c9c5f92010-03-04 10:33:10 +01004/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +01005 * (C) 2012 by Holger Hans Peter Freyther
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-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 Welte52b1f982008-12-23 20:25:15 +000012 * (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 Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Welte52b1f982008-12-23 20:25:15 +000018 *
Harald Welte9af6ddf2011-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 Welte52b1f982008-12-23 20:25:15 +000021 *
22 */
23
24#include <stdio.h>
Harald Welte8470bf22008-12-25 23:28:35 +000025#include <stdlib.h>
Harald Welte52b1f982008-12-23 20:25:15 +000026#include <errno.h>
Harald Welte75099262009-02-16 21:12:08 +000027#include <netinet/in.h>
Harald Welte167df882009-02-17 14:35:45 +000028#include <arpa/inet.h>
Harald Welte52b1f982008-12-23 20:25:15 +000029
Harald Welte8470bf22008-12-25 23:28:35 +000030#include <openbsc/gsm_data.h>
31#include <openbsc/gsm_04_08.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010032#include <osmocom/gsm/gsm_utils.h>
Harald Welte8470bf22008-12-25 23:28:35 +000033#include <openbsc/abis_rsl.h>
34#include <openbsc/chan_alloc.h>
Harald Welteedcc5272009-08-09 13:47:35 +020035#include <openbsc/bsc_rll.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010037#include <osmocom/gsm/tlv.h>
Holger Freyther392209c2009-02-10 00:06:19 +000038#include <openbsc/paging.h>
Harald Welte167df882009-02-17 14:35:45 +000039#include <openbsc/signal.h>
Harald Welte3c7dc6e2009-11-29 19:07:28 +010040#include <openbsc/meas_rep.h>
Harald Welte17f5bf62009-12-20 15:42:44 +010041#include <openbsc/rtp_proxy.h>
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020042#include <osmocom/abis/e1_input.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010043#include <osmocom/gsm/rsl.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010044#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080045
Harald Welte8470bf22008-12-25 23:28:35 +000046#define RSL_ALLOC_SIZE 1024
47#define RSL_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000048
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +080049static int rsl_send_imm_assignment(struct gsm_lchan *lchan);
50
Holger Hans Peter Freyther08eebd52010-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 Ayusobbc5b992011-05-06 12:12:31 +020057 osmo_signal_dispatch(SS_LCHAN, sig_no, &sig);
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +010058}
59
Holger Hans Peter Freyther93599a22012-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 Freytherc42ad8b2011-04-18 17:04:00 +020068static uint8_t mdisc_by_msgtype(uint8_t msg_type)
Harald Welte52b1f982008-12-23 20:25:15 +000069{
70 /* mask off the transparent bit ? */
71 msg_type &= 0xfe;
72
Harald Welte8470bf22008-12-25 23:28:35 +000073 if ((msg_type & 0xf0) == 0x00)
Harald Welte52b1f982008-12-23 20:25:15 +000074 return ABIS_RSL_MDISC_RLL;
Harald Welte8470bf22008-12-25 23:28:35 +000075 if ((msg_type & 0xf0) == 0x10) {
Harald Welte52b1f982008-12-23 20:25:15 +000076 if (msg_type >= 0x19 && msg_type <= 0x22)
77 return ABIS_RSL_MDISC_TRX;
78 else
79 return ABIS_RSL_MDISC_COM_CHAN;
80 }
Harald Welte2d5b6382008-12-27 19:46:06 +000081 if ((msg_type & 0xe0) == 0x20)
Harald Welte52b1f982008-12-23 20:25:15 +000082 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 Freytherc42ad8b2011-04-18 17:04:00 +020088 uint8_t msg_type)
Harald Welte52b1f982008-12-23 20:25:15 +000089{
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 Welte8470bf22008-12-25 23:28:35 +000095/* determine logical channel based on TRX and channel number IE */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020096struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr)
Harald Welte8470bf22008-12-25 23:28:35 +000097{
98 struct gsm_lchan *lchan;
Holger Hans Peter Freytherc42ad8b2011-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 Welte8470bf22008-12-25 23:28:35 +0000102 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
103
104 if (cbits == 0x01) {
105 lch_idx = 0; /* TCH/F */
Harald Weltea1499d02009-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 Welteb1d4c8e2009-12-17 23:10:46 +0100109 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000110 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 Welteb1d4c8e2009-12-17 23:10:46 +0100114 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000115 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 Welteb1d4c8e2009-12-17 23:10:46 +0100119 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000120 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 Welteb1d4c8e2009-12-17 23:10:46 +0100124 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000125 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 Welteb1d4c8e2009-12-17 23:10:46 +0100130 LOGP(DRSL, LOGL_ERROR, "chan_nr=0x%02x but pchan=%u\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000131 chan_nr, ts->pchan);
132 /* FIXME: we should not return first sdcch4 !!! */
133 } else {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100134 LOGP(DRSL, LOGL_ERROR, "unknown chan_nr=0x%02x\n", chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +0000135 return NULL;
136 }
137
138 lchan = &ts->lchan[lch_idx];
Harald Weltedc5062b2010-03-26 21:28:59 +0800139 log_set_context(BSC_CTX_LCHAN, lchan);
Holger Hans Peter Freyther2412a072010-06-28 15:47:12 +0800140 if (lchan->conn)
141 log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr);
Harald Welte8470bf22008-12-25 23:28:35 +0000142
143 return lchan;
144}
145
Harald Welte52b1f982008-12-23 20:25:15 +0000146/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200147uint64_t str_to_imsi(const char *imsi_str)
Harald Welte52b1f982008-12-23 20:25:15 +0000148{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200149 uint64_t ret;
Harald Welte52b1f982008-12-23 20:25:15 +0000150
151 ret = strtoull(imsi_str, NULL, 10);
152
153 return ret;
154}
155
Harald Welte8470bf22008-12-25 23:28:35 +0000156static struct msgb *rsl_msgb_alloc(void)
157{
Harald Welte966636f2009-06-26 19:39:35 +0200158 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
159 "RSL");
Harald Welte8470bf22008-12-25 23:28:35 +0000160}
161
Harald Welte362322e2009-02-15 14:36:38 +0000162#define MACBLOCK_SIZE 23
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200163static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
Harald Welte362322e2009-02-15 14:36:38 +0000164{
165 memcpy(out, in, len);
166
167 if (len < MACBLOCK_SIZE)
168 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
169}
170
Harald Welte08d91a52009-08-30 15:37:11 +0900171/* Chapter 9.3.7: Encryption Information */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200172static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
Harald Welte08d91a52009-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 Freytherc42ad8b2011-04-18 17:04:00 +0200180static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
Harald Welte8830e072009-07-28 17:58:09 +0200181{
Harald Welte7f93cea2009-02-23 00:02:59 +0000182 int i;
183
Harald Welte5b8ed432009-12-24 12:20:20 +0100184 LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
Harald Welte8830e072009-07-28 17:58:09 +0200185 cause_v[0], rsl_err_name(cause_v[0]));
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200186 for (i = 1; i < cause_len-1; i++)
Harald Welte5b8ed432009-12-24 12:20:20 +0100187 LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
Harald Welte7f93cea2009-02-23 00:02:59 +0000188}
189
Harald Weltee8bd9e82011-08-10 23:26:33 +0200190static void lchan_act_tmr_cb(void *data)
191{
192 struct gsm_lchan *lchan = data;
193
Holger Hans Peter Freyther1411c062012-12-06 19:00:35 +0100194 LOGP(DRSL, LOGL_ERROR, "%s Timeout during activation!\n",
Harald Weltee8bd9e82011-08-10 23:26:33 +0200195 gsm_lchan_name(lchan));
196
Daniel Willmann513da172011-08-11 04:44:12 +0200197 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
198 lchan_free(lchan);
Harald Weltee8bd9e82011-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 Freyther1411c062012-12-06 19:00:35 +0100205 LOGP(DRSL, LOGL_ERROR, "%s Timeout during deactivation!\n",
Harald Weltee8bd9e82011-08-10 23:26:33 +0200206 gsm_lchan_name(lchan));
207
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100208 do_lchan_free(lchan);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200209}
210
211
Harald Welte52b1f982008-12-23 20:25:15 +0000212/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Holger Hans Peter Freytherc42ad8b2011-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 Welte52b1f982008-12-23 20:25:15 +0000215{
216 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000217 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000218
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 Ayuso7abecfc2011-08-17 22:43:54 +0200226 msg->dst = trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000227
228 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000229}
230
Holger Hans Peter Freytherc42ad8b2011-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 Welte52b1f982008-12-23 20:25:15 +0000233{
234 struct abis_rsl_common_hdr *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000235 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000236
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);
Harald Welte702d8702008-12-26 20:25:35 +0000242 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
Harald Welte52b1f982008-12-23 20:25:15 +0000243
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200244 msg->dst = trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000245
246 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000247}
248
Holger Hans Peter Freytherc42ad8b2011-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 Welte7a69cf02011-01-13 23:16:03 +0100251{
252 struct abis_rsl_dchan_hdr *dh;
253 struct msgb *msg = rsl_msgb_alloc();
Harald Weltef6093a42011-06-25 10:02:33 +0200254 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte7a69cf02011-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 Ayuso7abecfc2011-08-17 22:43:54 +0200263 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte7a69cf02011-01-13 23:16:03 +0100264
265 return abis_rsl_sendmsg(msg);
266}
267
Harald Weltefcd24452009-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 Welteeab33352009-06-27 03:09:08 +0200271 struct msgb *msg;
Harald Weltef6093a42011-06-25 10:02:33 +0200272 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Weltefcd24452009-06-20 18:15:19 +0200273
274 db = abs(db);
275 if (db > 30)
276 return -EINVAL;
277
Harald Welteeab33352009-06-27 03:09:08 +0200278 msg = rsl_msgb_alloc();
279
Harald Weltefcd24452009-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 Ayuso7abecfc2011-08-17 22:43:54 +0200290 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltefcd24452009-06-20 18:15:19 +0200291
292 return abis_rsl_sendmsg(msg);
293}
294
Harald Weltefcd24452009-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 Welteeab33352009-06-27 03:09:08 +0200298 struct msgb *msg;
Harald Weltef6093a42011-06-25 10:02:33 +0200299 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Weltefcd24452009-06-20 18:15:19 +0200300 int ctl_lvl;
301
Harald Welte66b6a8d2009-08-09 14:45:18 +0200302 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Weltefcd24452009-06-20 18:15:19 +0200303 if (ctl_lvl < 0)
304 return ctl_lvl;
305
Harald Welteeab33352009-06-27 03:09:08 +0200306 msg = rsl_msgb_alloc();
307
Harald Weltefcd24452009-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 Ayuso7abecfc2011-08-17 22:43:54 +0200319 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltefcd24452009-06-20 18:15:19 +0200320
321 return abis_rsl_sendmsg(msg);
322}
323
Harald Welte9943c5b2009-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 Freyther5a3a61d2010-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 Welte9943c5b2009-07-29 15:41:29 +0200334
335 /* set TCH Speech/Data */
336 cm->spd_ind = lchan->rsl_cmode;
337
Harald Welte1a79d362009-11-27 08:55:16 +0100338 if (lchan->rsl_cmode == RSL_CMOD_SPD_SIGN &&
339 lchan->tch_mode != GSM48_CMODE_SIGN)
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100340 LOGP(DRSL, LOGL_ERROR, "unsupported: rsl_mode == signalling, "
Harald Welte1a79d362009-11-27 08:55:16 +0100341 "but tch_mode != signalling\n");
342
Harald Welte9943c5b2009-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 Welte9943c5b2009-07-29 15:41:29 +0200373 case GSM48_CMODE_DATA_12k0:
Harald Welte9943c5b2009-07-29 15:41:29 +0200374 case GSM48_CMODE_DATA_6k0:
Harald Weltee4227982012-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 Welte9943c5b2009-07-29 15:41:29 +0200420 default:
421 return -EINVAL;
422 }
423
424 return 0;
425}
426
Harald Welte52b1f982008-12-23 20:25:15 +0000427/* Chapter 8.4.1 */
Harald Welteddab3c72009-02-28 13:19:15 +0000428#if 0
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200429int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
430 uint8_t act_type,
Harald Welte52b1f982008-12-23 20:25:15 +0000431 struct rsl_ie_chan_mode *chan_mode,
432 struct rsl_ie_chan_ident *chan_ident,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200433 uint8_t bs_power, uint8_t ms_power,
434 uint8_t ta)
Harald Welte52b1f982008-12-23 20:25:15 +0000435{
436 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000437 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000438
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 Freytherc42ad8b2011-04-18 17:04:00 +0200446 (uint8_t *) chan_mode);
Harald Welte52b1f982008-12-23 20:25:15 +0000447 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200448 (uint8_t *) chan_ident);
Harald Welte702d8702008-12-26 20:25:35 +0000449#if 0
Harald Welte52b1f982008-12-23 20:25:15 +0000450 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200451 (uint8_t *) &encr_info);
Harald Welte702d8702008-12-26 20:25:35 +0000452#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000453 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
Harald Welte52b1f982008-12-23 20:25:15 +0000454 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
455 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
456
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200457 msg->dst = trx->rsl_link;
Harald Weltee79769b2009-02-07 00:48:17 +0000458
Harald Welte8470bf22008-12-25 23:28:35 +0000459 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000460}
Harald Welteddab3c72009-02-28 13:19:15 +0000461#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000462
Holger Hans Peter Freytherc42ad8b2011-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 Welte4b634542008-12-27 01:55:51 +0000465{
466 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200467 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200468 int rc;
Harald Welte93d50e62010-06-29 17:53:45 +0200469 uint8_t *len;
Harald Welte4b634542008-12-27 01:55:51 +0000470
Harald Weltef6093a42011-06-25 10:02:33 +0200471 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000472 struct rsl_ie_chan_mode cm;
laforge694a5cf2010-06-20 21:38:19 +0200473 struct gsm48_chan_desc cd;
Harald Welte4b634542008-12-27 01:55:51 +0000474
Harald Welte9943c5b2009-07-29 15:41:29 +0200475 rc = channel_mode_from_lchan(&cm, lchan);
476 if (rc < 0)
477 return rc;
Harald Welte4b634542008-12-27 01:55:51 +0000478
Holger Hans Peter Freythere38bd6c2010-06-30 11:56:43 +0800479 memset(&cd, 0, sizeof(cd));
laforge694a5cf2010-06-20 21:38:19 +0200480 gsm48_lchan2chan_desc(&cd, lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000481
Harald Welteeab33352009-06-27 03:09:08 +0200482 msg = rsl_msgb_alloc();
Harald Welte4b634542008-12-27 01:55:51 +0000483 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 Welte4b634542008-12-27 01:55:51 +0000488 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200489 (uint8_t *) &cm);
Holger Hans Peter Freythere38bd6c2010-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 */
laforge694a5cf2010-06-20 21:38:19 +0200498 msgb_v_put(msg, RSL_IE_CHAN_IDENT);
Harald Welte93d50e62010-06-29 17:53:45 +0200499 len = msgb_put(msg, 1);
Dieter Spaareabb6e32011-07-27 23:40:33 +0200500 msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
Holger Hans Peter Freyther0379c6d2010-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 Freythere38bd6c2010-06-30 11:56:43 +0800507
508 /* update the calculated size */
509 msg->l3h = len + 1;
510 *len = msgb_l3len(msg);
511
Harald Welte08d91a52009-08-30 15:37:11 +0900512 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200513 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welte08d91a52009-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 Welte8d77b952009-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 Welted4c9bf32009-02-15 16:56:18 +0000528 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
529 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
Harald Welte4b634542008-12-27 01:55:51 +0000530 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
531
Holger Hans Peter Freyther93b6c652010-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 Freytherc42ad8b2011-04-18 17:04:00 +0200534 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freyther93b6c652010-01-28 04:45:05 +0100535
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200536 msg->dst = lchan->ts->trx->rsl_link;
Harald Weltee79769b2009-02-07 00:48:17 +0000537
Harald Welte4b634542008-12-27 01:55:51 +0000538 return abis_rsl_sendmsg(msg);
539}
540
Harald Welte470abb72009-07-29 11:38:15 +0200541/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welteda783762009-02-18 03:29:53 +0000542int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
543{
544 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200545 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200546 int rc;
Harald Welteda783762009-02-18 03:29:53 +0000547
Harald Weltef6093a42011-06-25 10:02:33 +0200548 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteda783762009-02-18 03:29:53 +0000549 struct rsl_ie_chan_mode cm;
550
Harald Welte9943c5b2009-07-29 15:41:29 +0200551 rc = channel_mode_from_lchan(&cm, lchan);
552 if (rc < 0)
553 return rc;
Harald Welteda783762009-02-18 03:29:53 +0000554
Harald Welteeab33352009-06-27 03:09:08 +0200555 msg = rsl_msgb_alloc();
Harald Welteda783762009-02-18 03:29:53 +0000556 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 Freytherc42ad8b2011-04-18 17:04:00 +0200561 (uint8_t *) &cm);
Harald Welte08d91a52009-08-30 15:37:11 +0900562
563 if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200564 uint8_t encr_info[MAX_A5_KEY_LEN+2];
Harald Welte08d91a52009-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 Freytherea528022009-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 Freytherc42ad8b2011-04-18 17:04:00 +0200572 (uint8_t *) &lchan->mr_conf);
Holger Hans Peter Freytherea528022009-11-18 22:57:02 +0100573 }
574
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200575 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte08d91a52009-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 Weltef6093a42011-06-25 10:02:33 +0200585 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200586 uint8_t encr_info[MAX_A5_KEY_LEN+2];
587 uint8_t l3_len = msg->len;
Harald Welte08d91a52009-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 Welteda783762009-02-18 03:29:53 +0000606
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200607 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteda783762009-02-18 03:29:53 +0000608
609 return abis_rsl_sendmsg(msg);
610}
611
Harald Welte115d1032009-08-10 11:43:22 +0200612/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteae0f2362009-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 Weltef6093a42011-06-25 10:02:33 +0200620 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welteae0f2362009-07-19 18:36:49 +0200621
622 msg->lchan = lchan;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200623 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteae0f2362009-07-19 18:36:49 +0200624
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100625 DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
Harald Welteae0f2362009-07-19 18:36:49 +0200626
627 return abis_rsl_sendmsg(msg);
628}
629
Holger Hans Peter Freyther4b4dd102010-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 Freyther44752d92010-06-08 11:53:33 +0800641 rsl_lchan_set_state(lchan, LCHAN_S_NONE);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800642}
643
Harald Weltefd355a32011-03-04 13:41:31 +0100644static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan);
645
Harald Welte115d1032009-08-10 11:43:22 +0200646/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800647static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
Harald Welte52b1f982008-12-23 20:25:15 +0000648{
649 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800650 struct msgb *msg;
Harald Weltefd355a32011-03-04 13:41:31 +0100651 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000652
Holger Hans Peter Freyther4b4dd102010-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 Welte52b1f982008-12-23 20:25:15 +0000660 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
661 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Weltef6093a42011-06-25 10:02:33 +0200662 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +0000663
Harald Welte8470bf22008-12-25 23:28:35 +0000664 msg->lchan = lchan;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200665 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000666
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800667 DEBUGP(DRSL, "%s RF Channel Release CMD due error %d\n", gsm_lchan_name(lchan), error);
668
669 if (error) {
670 /*
671 * the nanoBTS sends RLL release indications after the channel release. This can
672 * be a problem when we have reassigned the channel to someone else and then can
673 * not figure out who used this channel.
674 */
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200675 struct e1inp_sign_link *sign_link = msg->dst;
676
Holger Hans Peter Freyther44752d92010-06-08 11:53:33 +0800677 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800678 lchan->error_timer.data = lchan;
679 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200680 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200681 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800682 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000683
Harald Weltee8bd9e82011-08-10 23:26:33 +0200684 /* Start another timer or assume the BTS sends a ACK/NACK? */
685 lchan->act_timer.cb = lchan_deact_tmr_cb;
686 lchan->act_timer.data = lchan;
687 osmo_timer_schedule(&lchan->act_timer, 4, 0);
688
Harald Weltefd355a32011-03-04 13:41:31 +0100689 rc = abis_rsl_sendmsg(msg);
690
Harald Welte115d1032009-08-10 11:43:22 +0200691 /* BTS will respond by RF CHAN REL ACK */
Harald Welte26d79072011-01-14 23:18:59 +0100692#ifdef HSL_SR_1_0
Harald Weltefd355a32011-03-04 13:41:31 +0100693 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
694 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
695 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte26d79072011-01-14 23:18:59 +0100696#endif
Harald Weltefd355a32011-03-04 13:41:31 +0100697
698 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000699}
700
Harald Welte64bb7542011-01-14 14:16:16 +0100701static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
702{
703
704 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
705
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100706 /* Stop all pending timers */
Harald Weltee8bd9e82011-08-10 23:26:33 +0200707 osmo_timer_del(&lchan->act_timer);
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100708 osmo_timer_del(&lchan->T3111);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200709
Harald Welte64bb7542011-01-14 14:16:16 +0100710 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
711 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
712 gsm_lchan_name(lchan),
713 gsm_lchans_name(lchan->state));
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100714 do_lchan_free(lchan);
Harald Welte64bb7542011-01-14 14:16:16 +0100715
716 return 0;
717}
718
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200719int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
720 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte52b1f982008-12-23 20:25:15 +0000721{
722 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000723 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000724
725 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
726 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
727 dh->chan_nr = RSL_CHAN_PCH_AGCH;
728
729 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
Harald Welte255539c2008-12-28 02:26:27 +0000730 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000731 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
732
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200733 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000734
735 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000736}
737
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200738int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte52b1f982008-12-23 20:25:15 +0000739{
740 int i, len = strlen(str_in);
741
742 for (i = 0; i < len; i++) {
743 int num = str_in[i] - 0x30;
744 if (num < 0 || num > 9)
745 return -1;
746 if (i % 2 == 0)
747 bcd_out[i/2] = num;
748 else
749 bcd_out[i/2] |= (num << 4);
750 }
751
752 return 0;
753}
754
Harald Welte702d8702008-12-26 20:25:35 +0000755/* Chapter 8.5.6 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200756int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte52b1f982008-12-23 20:25:15 +0000757{
Harald Welte8470bf22008-12-25 23:28:35 +0000758 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000759 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200760 uint8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000761
762 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
763 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
764 dh->chan_nr = RSL_CHAN_PCH_AGCH;
765
Harald Welte362322e2009-02-15 14:36:38 +0000766 switch (bts->type) {
767 case GSM_BTS_TYPE_BS11:
768 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
769 break;
770 default:
771 /* If phase 2, construct a FULL_IMM_ASS_INFO */
772 pad_macblock(buf, val, len);
773 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
774 break;
775 }
Harald Welte52b1f982008-12-23 20:25:15 +0000776
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200777 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000778
779 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000780}
781
Harald Welte67fa91b2009-08-10 09:51:40 +0200782/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte31c48932009-08-10 10:07:33 +0200783int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte67fa91b2009-08-10 09:51:40 +0200784{
785 struct msgb *msg = rsl_msgb_alloc();
786 struct abis_rsl_dchan_hdr *dh;
787
788 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
789 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte3c456d02009-08-10 11:26:14 +0200790 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +0200791 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200792 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte67fa91b2009-08-10 09:51:40 +0200793
Harald Welte5b8ed432009-12-24 12:20:20 +0100794 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200795 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte3c456d02009-08-10 11:26:14 +0200796
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200797 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte3c456d02009-08-10 11:26:14 +0200798
Harald Welte67fa91b2009-08-10 09:51:40 +0200799 return abis_rsl_sendmsg(msg);
800}
801
802
Harald Welte8470bf22008-12-25 23:28:35 +0000803/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000804/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200805int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000806{
Harald Welte8470bf22008-12-25 23:28:35 +0000807 if (msg->lchan == NULL) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100808 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte8470bf22008-12-25 23:28:35 +0000809 return -EINVAL;
810 }
Harald Welte52b1f982008-12-23 20:25:15 +0000811
Harald Weltef6093a42011-06-25 10:02:33 +0200812 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100813 link_id, 1);
Harald Welte52b1f982008-12-23 20:25:15 +0000814
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200815 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000816
817 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000818}
819
Harald Welteedcc5272009-08-09 13:47:35 +0200820/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
821/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200822int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteedcc5272009-08-09 13:47:35 +0200823{
Harald Welte3c9c5f92010-03-04 10:33:10 +0100824 struct msgb *msg;
Harald Welteedcc5272009-08-09 13:47:35 +0200825
Harald Weltef6093a42011-06-25 10:02:33 +0200826 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100827 link_id, 0);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200828 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteedcc5272009-08-09 13:47:35 +0200829
Harald Weltefda74ee2012-04-26 19:42:19 +0200830 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
831 gsm_lchan_name(lchan), link_id);
832
Harald Welteedcc5272009-08-09 13:47:35 +0200833 return abis_rsl_sendmsg(msg);
834}
835
Harald Welted2dc1de2009-08-08 13:15:07 +0200836/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
837 This is what higher layers should call. The BTS then responds with
838 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
839 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
840 lchan_free() */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100841int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
842 enum rsl_rel_mode release_mode)
Harald Welted2dc1de2009-08-08 13:15:07 +0200843{
Harald Welted2dc1de2009-08-08 13:15:07 +0200844
Harald Welte3c9c5f92010-03-04 10:33:10 +0100845 struct msgb *msg;
846
Harald Weltef6093a42011-06-25 10:02:33 +0200847 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100848 link_id, 0);
Holger Hans Peter Freyther4f5848d2010-06-08 11:57:45 +0800849 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100850 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welted2dc1de2009-08-08 13:15:07 +0200851
Harald Welte8e93b792009-12-29 10:44:17 +0100852 /* FIXME: start some timer in case we don't receive a REL ACK ? */
853
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200854 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dc1de2009-08-08 13:15:07 +0200855
Harald Weltefda74ee2012-04-26 19:42:19 +0200856 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100857 gsm_lchan_name(lchan), link_id, release_mode);
Harald Weltefda74ee2012-04-26 19:42:19 +0200858
Harald Welted2dc1de2009-08-08 13:15:07 +0200859 return abis_rsl_sendmsg(msg);
860}
861
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200862int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
863{
864 lchan->state = state;
865 return 0;
866}
867
Harald Welte702d8702008-12-26 20:25:35 +0000868/* Chapter 8.4.2: Channel Activate Acknowledge */
869static int rsl_rx_chan_act_ack(struct msgb *msg)
870{
871 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
872
873 /* BTS has confirmed channel activation, we now need
874 * to assign the activated channel to the MS */
Harald Welte4b634542008-12-27 01:55:51 +0000875 if (rslh->ie_chan != RSL_IE_CHAN_NR)
876 return -EINVAL;
Harald Welted011e8b2009-11-29 22:45:52 +0100877
Harald Weltee8bd9e82011-08-10 23:26:33 +0200878 osmo_timer_del(&msg->lchan->act_timer);
879
Harald Welte8e93b792009-12-29 10:44:17 +0100880 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welte1887f9d2009-12-29 10:52:38 +0100881 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
882 gsm_lchan_name(msg->lchan),
883 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200884 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welteb8bfc562009-12-21 13:27:11 +0100885
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +0800886 if (msg->lchan->rqd_ref) {
887 rsl_send_imm_assignment(msg->lchan);
888 talloc_free(msg->lchan->rqd_ref);
889 msg->lchan->rqd_ref = NULL;
890 msg->lchan->rqd_ta = 0;
891 }
892
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100893 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +0100894
Harald Welte4b634542008-12-27 01:55:51 +0000895 return 0;
896}
Harald Welte702d8702008-12-26 20:25:35 +0000897
Harald Welte4b634542008-12-27 01:55:51 +0000898/* Chapter 8.4.3: Channel Activate NACK */
899static int rsl_rx_chan_act_nack(struct msgb *msg)
900{
Harald Welte6dab0552009-05-01 17:21:37 +0000901 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
902 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +0000903
Harald Weltee8bd9e82011-08-10 23:26:33 +0200904 osmo_timer_del(&msg->lchan->act_timer);
905
Daniel Willmann6fc6a122011-08-11 04:54:23 +0200906 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100907 gsm_lchan_name(msg->lchan));
Harald Welte (local)91b603d2009-12-27 11:48:11 +0100908
Harald Welte6dab0552009-05-01 17:21:37 +0000909 /* BTS has rejected channel activation ?!? */
910 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +0000911 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +0000912
913 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)3e460312009-12-27 18:12:29 +0100914 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200915 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)3e460312009-12-27 18:12:29 +0100916 print_rsl_cause(LOGL_ERROR, cause,
Harald Welte8830e072009-07-28 17:58:09 +0200917 TLVP_LEN(&tp, RSL_IE_CAUSE));
Harald Welte (local)3e460312009-12-27 18:12:29 +0100918 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200919 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Daniel Willmann7ddc3182011-08-11 04:47:11 +0200920 else
921 rsl_rf_chan_release(msg->lchan, 1);
922
Harald Welte (local)3e460312009-12-27 18:12:29 +0100923 } else
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200924 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200925
Harald Welte (local)91b603d2009-12-27 11:48:11 +0100926 LOGPC(DRSL, LOGL_ERROR, "\n");
927
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100928 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +0100929
Harald Welte3073a9f2009-08-09 19:50:08 +0200930 lchan_free(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000931 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000932}
933
Harald Welte7f93cea2009-02-23 00:02:59 +0000934/* Chapter 8.4.4: Connection Failure Indication */
935static int rsl_rx_conn_fail(struct msgb *msg)
936{
937 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
938 struct tlv_parsed tp;
939
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100940 /* FIXME: print which channel */
Harald Welte (local)fc057502009-12-26 22:33:09 +0100941 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100942 gsm_lchan_name(msg->lchan));
Harald Welte7f93cea2009-02-23 00:02:59 +0000943
944 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
945
Harald Welte8830e072009-07-28 17:58:09 +0200946 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +0100947 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +0200948 TLVP_LEN(&tp, RSL_IE_CAUSE));
949
Harald Welte (local)fc057502009-12-26 22:33:09 +0100950 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000951 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200952 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800953 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte7f93cea2009-02-23 00:02:59 +0000954}
955
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100956static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
957 const char *prefix)
958{
Harald Welte6739dfb2009-12-16 16:52:07 +0100959 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
960 prefix, rxlev2dbm(mru->full.rx_lev),
961 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100962 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
963 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
964}
965
Harald Welte0c1bd612012-07-02 17:12:08 +0200966static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100967{
Harald Welte6739dfb2009-12-16 16:52:07 +0100968 int i;
Harald Welte0c1bd612012-07-02 17:12:08 +0200969 char *name = "";
Harald Welte6739dfb2009-12-16 16:52:07 +0100970
Harald Welte0c1bd612012-07-02 17:12:08 +0200971 if (lchan && lchan->conn && lchan->conn->subscr)
972 name = subscr_name(lchan->conn->subscr);
973
974 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100975
976 if (mr->flags & MEAS_REP_F_DL_DTX)
977 DEBUGPC(DMEAS, "DTXd ");
978
979 print_meas_rep_uni(&mr->ul, "ul");
980 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
981 if (mr->flags & MEAS_REP_F_MS_TO)
982 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
983
984 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte6739dfb2009-12-16 16:52:07 +0100985 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100986 DEBUGPC(DMEAS, "L1_FPC=%u ",
987 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
988 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
989 }
990
991 if (mr->flags & MEAS_REP_F_UL_DTX)
992 DEBUGPC(DMEAS, "DTXu ");
993 if (mr->flags & MEAS_REP_F_BA1)
994 DEBUGPC(DMEAS, "BA1 ");
995 if (!(mr->flags & MEAS_REP_F_DL_VALID))
996 DEBUGPC(DMEAS, "NOT VALID ");
997 else
998 print_meas_rep_uni(&mr->dl, "dl");
999
1000 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte479015b2009-12-19 18:33:05 +01001001 if (mr->num_cell == 7)
1002 return;
Harald Welte6739dfb2009-12-16 16:52:07 +01001003 for (i = 0; i < mr->num_cell; i++) {
1004 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte303e5e02009-12-25 23:02:22 +01001005 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1006 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte6739dfb2009-12-16 16:52:07 +01001007 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001008}
1009
Harald Welte440fed02009-05-01 18:43:47 +00001010static int rsl_rx_meas_res(struct msgb *msg)
1011{
1012 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1013 struct tlv_parsed tp;
Harald Welted12b0fd2009-12-15 21:36:05 +01001014 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001015 uint8_t len;
1016 const uint8_t *val;
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001017 int rc;
Harald Welte440fed02009-05-01 18:43:47 +00001018
Harald Welteb8bfc562009-12-21 13:27:11 +01001019 /* check if this channel is actually active */
1020 /* FIXME: maybe this check should be way more generic/centralized */
Harald Welte8e93b792009-12-29 10:44:17 +01001021 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freytherc44db4a2010-07-29 14:50:57 +08001022 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Welte8e93b792009-12-29 10:44:17 +01001023 gsm_lchan_name(msg->lchan));
Harald Welteb8bfc562009-12-21 13:27:11 +01001024 return 0;
Harald Welte8e93b792009-12-29 10:44:17 +01001025 }
Harald Welteb8bfc562009-12-21 13:27:11 +01001026
Harald Welted12b0fd2009-12-15 21:36:05 +01001027 memset(mr, 0, sizeof(*mr));
Harald Welte33e65972009-12-16 23:29:34 +01001028 mr->lchan = msg->lchan;
Harald Weltedbb1d882009-11-30 19:16:47 +01001029
Harald Welte440fed02009-05-01 18:43:47 +00001030 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1031
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001032 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1033 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1034 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1035 return -EIO;
1036
1037 /* Mandatory Parts */
Harald Welted12b0fd2009-12-15 21:36:05 +01001038 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001039
1040 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1041 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1042 if (len >= 3) {
1043 if (val[0] & 0x40)
Harald Welted12b0fd2009-12-15 21:36:05 +01001044 mr->flags |= MEAS_REP_F_DL_DTX;
1045 mr->ul.full.rx_lev = val[0] & 0x3f;
1046 mr->ul.sub.rx_lev = val[1] & 0x3f;
1047 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1048 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte440fed02009-05-01 18:43:47 +00001049 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001050
Harald Welted12b0fd2009-12-15 21:36:05 +01001051 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001052
1053 /* Optional Parts */
Harald Welte440fed02009-05-01 18:43:47 +00001054 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welted12b0fd2009-12-15 21:36:05 +01001055 mr->ms_timing_offset =
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001056 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1057
Harald Weltefe9af262009-06-20 18:44:35 +02001058 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001059 struct e1inp_sign_link *sign_link = msg->dst;
1060
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001061 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001062 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001063 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001064 if (val[0] & 0x04)
Harald Welted12b0fd2009-12-15 21:36:05 +01001065 mr->flags |= MEAS_REP_F_FPC;
1066 mr->ms_l1.ta = val[1];
Andreas Eversberg3365cd12011-12-24 11:49:05 +01001067 /* BS11 and Nokia reports TA shifted by 2 bits */
1068 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1069 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg2957de92011-12-16 17:45:37 +01001070 mr->ms_l1.ta >>= 2;
Harald Weltefe9af262009-06-20 18:44:35 +02001071 }
Harald Weltef7c43522009-06-09 20:24:21 +00001072 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001073 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001074 rc = gsm48_parse_meas_rep(mr, msg);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001075 if (rc < 0)
1076 return rc;
1077 }
1078
Harald Welte0c1bd612012-07-02 17:12:08 +02001079 print_meas_rep(msg->lchan, mr);
Harald Welte60d68f12009-06-05 20:07:43 +00001080
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001081 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Weltedbb1d882009-11-30 19:16:47 +01001082
Harald Welte75d34a82009-05-23 06:11:13 +00001083 return 0;
Harald Welte440fed02009-05-01 18:43:47 +00001084}
1085
Harald Welted011e8b2009-11-29 22:45:52 +01001086/* Chapter 8.4.7 */
1087static int rsl_rx_hando_det(struct msgb *msg)
1088{
1089 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1090 struct tlv_parsed tp;
1091
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001092 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welted011e8b2009-11-29 22:45:52 +01001093
1094 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1095
1096 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1097 DEBUGPC(DRSL, "access delay = %u\n",
1098 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1099 else
1100 DEBUGPC(DRSL, "\n");
1101
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001102 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +01001103
1104 return 0;
1105}
1106
Harald Welte52b1f982008-12-23 20:25:15 +00001107static int abis_rsl_rx_dchan(struct msgb *msg)
1108{
Harald Welte8470bf22008-12-25 23:28:35 +00001109 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1110 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +00001111 char *ts_name;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001112 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001113
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001114 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001115 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltef325eb42009-02-19 17:07:39 +00001116
Harald Welte8470bf22008-12-25 23:28:35 +00001117 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001118 case RSL_MT_CHAN_ACTIV_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001119 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte4b634542008-12-27 01:55:51 +00001120 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001121 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001122 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte4b634542008-12-27 01:55:51 +00001123 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001124 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001125 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +00001126 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001127 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001128 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +00001129 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +00001130 break;
Harald Welted011e8b2009-11-29 22:45:52 +01001131 case RSL_MT_HANDO_DET:
1132 rc = rsl_rx_hando_det(msg);
1133 break;
Harald Welte2d5b6382008-12-27 19:46:06 +00001134 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte64bb7542011-01-14 14:16:16 +01001135 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +00001136 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001137 case RSL_MT_MODE_MODIFY_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001138 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001139 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001140 case RSL_MT_MODE_MODIFY_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001141 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001142 break;
Harald Welte9c880c92009-10-24 10:29:22 +02001143 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001144 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001145 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001146 break;
1147 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001148 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001149 break;
1150 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001151 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001152 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001153 break;
1154 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001155 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001156 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001157 case RSL_MT_PHY_CONTEXT_CONF:
1158 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +00001159 case RSL_MT_TALKER_DET:
1160 case RSL_MT_LISTENER_DET:
1161 case RSL_MT_REMOTE_CODEC_CONF_REP:
1162 case RSL_MT_MR_CODEC_MOD_ACK:
1163 case RSL_MT_MR_CODEC_MOD_NACK:
1164 case RSL_MT_MR_CODEC_MOD_PER:
Harald Welte5b8ed432009-12-24 12:20:20 +01001165 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1166 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001167 break;
1168 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001169 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1170 ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001171 return -EINVAL;
1172 }
Harald Weltef325eb42009-02-19 17:07:39 +00001173
Harald Welte8470bf22008-12-25 23:28:35 +00001174 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001175}
1176
Harald Welte702d8702008-12-26 20:25:35 +00001177static int rsl_rx_error_rep(struct msgb *msg)
1178{
1179 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +02001180 struct tlv_parsed tp;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001181 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte702d8702008-12-26 20:25:35 +00001182
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001183 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Welte8830e072009-07-28 17:58:09 +02001184
1185 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1186
1187 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001188 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001189 TLVP_LEN(&tp, RSL_IE_CAUSE));
1190
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001191 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001192
1193 return 0;
1194}
1195
Harald Welte52b1f982008-12-23 20:25:15 +00001196static int abis_rsl_rx_trx(struct msgb *msg)
1197{
Harald Welte702d8702008-12-26 20:25:35 +00001198 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001199 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte8470bf22008-12-25 23:28:35 +00001200 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001201
1202 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001203 case RSL_MT_ERROR_REPORT:
1204 rc = rsl_rx_error_rep(msg);
1205 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001206 case RSL_MT_RF_RES_IND:
1207 /* interference on idle channels of TRX */
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001208 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte8f5e2392009-02-03 12:57:37 +00001209 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001210 case RSL_MT_OVERLOAD:
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001211 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001212 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001213 gsm_trx_name(sign_link->trx));
Harald Welte52b1f982008-12-23 20:25:15 +00001214 break;
Dieter Spaar16646022011-07-28 00:01:50 +02001215 case 0x42: /* Nokia specific: SI End ACK */
1216 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1217 break;
1218 case 0x43: /* Nokia specific: SI End NACK */
1219 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1220 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001221 default:
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001222 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001223 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001224 return -EINVAL;
1225 }
Harald Welte8470bf22008-12-25 23:28:35 +00001226 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001227}
1228
Harald Welteb7e81162009-08-10 00:26:10 +02001229/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1230static void t3101_expired(void *data)
1231{
1232 struct gsm_lchan *lchan = data;
1233
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001234 rsl_rf_chan_release(lchan, 1);
Harald Welteb7e81162009-08-10 00:26:10 +02001235}
1236
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001237/* If T3111 expires, we will send the RF Channel Request */
1238static void t3111_expired(void *data)
1239{
1240 struct gsm_lchan *lchan = data;
1241
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001242 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001243}
1244
laforgecfa4a012010-06-21 12:08:52 +02001245#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1246
Harald Welte2862dca2010-12-23 14:39:29 +01001247/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1248static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1249 unsigned int num_req_refs,
1250 struct gsm48_req_ref *rqd_refs,
1251 uint8_t wait_ind)
1252{
1253 uint8_t buf[GSM_MACBLOCK_LEN];
1254 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1255
1256 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1257 memset(iar, 0, sizeof(*iar));
1258 iar->proto_discr = GSM48_PDISC_RR;
1259 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1260 iar->page_mode = GSM48_PM_SAME;
1261
1262 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1263 iar->wait_ind1 = wait_ind;
1264
1265 if (num_req_refs >= 2)
1266 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1267 else
1268 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1269 iar->wait_ind2 = wait_ind;
1270
1271 if (num_req_refs >= 3)
1272 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1273 else
1274 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1275 iar->wait_ind3 = wait_ind;
1276
1277 if (num_req_refs >= 4)
1278 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1279 else
1280 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1281 iar->wait_ind4 = wait_ind;
1282
1283 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1284}
1285
Harald Welte8470bf22008-12-25 23:28:35 +00001286/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001287static int rsl_rx_chan_rqd(struct msgb *msg)
1288{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001289 struct e1inp_sign_link *sign_link = msg->dst;
1290 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001291 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1292 struct gsm48_req_ref *rqd_ref;
Harald Welte8470bf22008-12-25 23:28:35 +00001293 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001294 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001295 struct gsm_lchan *lchan;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001296 uint8_t rqd_ta;
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001297 int is_lu;
Harald Welte8470bf22008-12-25 23:28:35 +00001298
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001299 uint16_t arfcn;
Holger Hans Peter Freytherc6d0a172012-02-03 20:10:13 +01001300 uint8_t subch;
Harald Welte52b1f982008-12-23 20:25:15 +00001301
Harald Welte8470bf22008-12-25 23:28:35 +00001302 /* parse request reference to be used in immediate assign */
1303 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1304 return -EINVAL;
1305
1306 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1307
1308 /* parse access delay and use as TA */
1309 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1310 return -EINVAL;
1311 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1312
1313 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1314 * request reference RA */
Holger Hans Peter Freyther78891072010-09-06 09:36:02 +08001315 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1316 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte2cbe0922008-12-29 04:09:31 +00001317
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001318 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte24ff6ee2009-12-22 00:41:05 +01001319
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001320 /*
1321 * We want LOCATION UPDATES to succeed and will assign a TCH
1322 * if we have no SDCCH available.
1323 */
1324 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1325
Harald Welte8470bf22008-12-25 23:28:35 +00001326 /* check availability / allocate channel */
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001327 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte8470bf22008-12-25 23:28:35 +00001328 if (!lchan) {
Harald Welte (local)2f5df852009-12-27 13:48:09 +01001329 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)ccd88452009-12-27 18:05:25 +01001330 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001331 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Welte2862dca2010-12-23 14:39:29 +01001332 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1333 if (bts->network->T3122)
1334 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte8470bf22008-12-25 23:28:35 +00001335 return -ENOMEM;
1336 }
1337
Harald Welte8e93b792009-12-29 10:44:17 +01001338 if (lchan->state != LCHAN_S_NONE)
1339 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welte1887f9d2009-12-29 10:52:38 +01001340 "in state %s\n", gsm_lchan_name(lchan),
1341 gsm_lchans_name(lchan->state));
Harald Welte (local)3e460312009-12-27 18:12:29 +01001342
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001343 /* save the RACH data as we need it after the CHAN ACT ACK */
1344 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1345 if (!lchan->rqd_ref) {
1346 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1347 lchan_free(lchan);
1348 return -ENOMEM;
1349 }
1350
Holger Hans Peter Freytherc0a66742011-12-29 23:33:04 +01001351 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001352 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1353 lchan->rqd_ta = rqd_ta;
1354
Harald Welte8470bf22008-12-25 23:28:35 +00001355 arfcn = lchan->ts->trx->arfcn;
1356 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001357
Harald Welte08d91a52009-08-30 15:37:11 +09001358 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)0e451d02009-08-13 10:14:26 +02001359 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte0b2124b2009-08-10 00:45:40 +02001360 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte9943c5b2009-07-29 15:41:29 +02001361 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte196d0522009-08-28 23:28:28 +09001362 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001363
Harald Weltee8bd9e82011-08-10 23:26:33 +02001364 /* Start another timer or assume the BTS sends a ACK/NACK? */
1365 lchan->act_timer.cb = lchan_act_tmr_cb;
1366 lchan->act_timer.data = lchan;
1367 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1368
Andreas Eversberg2957de92011-12-16 17:45:37 +01001369 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1370 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1371 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1372 rqd_ref->ra, rqd_ta);
1373
1374 /* BS11 requires TA shifted by 2 bits */
1375 if (bts->type == GSM_BTS_TYPE_BS11)
1376 rqd_ta <<= 2;
Harald Welte8d77b952009-12-17 00:31:10 +01001377 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001378
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001379 return 0;
1380}
1381
1382static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1383{
1384 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001385 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001386 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1387
Harald Welte52b1f982008-12-23 20:25:15 +00001388 /* create IMMEDIATE ASSIGN 04.08 messge */
laforge09108bf2010-06-20 15:18:46 +02001389 memset(ia, 0, sizeof(*ia));
laforgecfa4a012010-06-21 12:08:52 +02001390 /* we set ia->l2_plen once we know the length of the MA below */
laforge09108bf2010-06-20 15:18:46 +02001391 ia->proto_discr = GSM48_PDISC_RR;
1392 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1393 ia->page_mode = GSM48_PM_SAME;
1394 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea39b0f22010-06-14 22:26:10 +02001395
Harald Welte8470bf22008-12-25 23:28:35 +00001396 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001397 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1398 ia->timing_advance = lchan->rqd_ta;
Harald Weltea39b0f22010-06-14 22:26:10 +02001399 if (!lchan->ts->hopping.enabled) {
laforge09108bf2010-06-20 15:18:46 +02001400 ia->mob_alloc_len = 0;
Harald Weltea39b0f22010-06-14 22:26:10 +02001401 } else {
laforge09108bf2010-06-20 15:18:46 +02001402 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1403 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea39b0f22010-06-14 22:26:10 +02001404 }
Harald Weltea1d39a22010-06-28 18:41:27 +02001405 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1406 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte52b1f982008-12-23 20:25:15 +00001407
Harald Welteb7e81162009-08-10 00:26:10 +02001408 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1409 lchan->T3101.cb = t3101_expired;
1410 lchan->T3101.data = lchan;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001411 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Holger Freyther3186bf22008-12-29 06:23:49 +00001412
Harald Welte52b1f982008-12-23 20:25:15 +00001413 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001414 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte52b1f982008-12-23 20:25:15 +00001415}
1416
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001417/* current load on the CCCH */
Harald Welteea280442009-02-02 22:29:56 +00001418static int rsl_rx_ccch_load(struct msgb *msg)
1419{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001420 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001421 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001422 struct ccch_signal_data sd;
1423
1424 sd.bts = sign_link->trx->bts;
1425 sd.rach_slot_count = -1;
1426 sd.rach_busy_count = -1;
1427 sd.rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001428
1429 switch (rslh->data[0]) {
1430 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001431 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1432 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte38e9c822010-04-19 10:24:07 +02001433 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001434 sd.pg_buf_space = 50;
Harald Welte38e9c822010-04-19 10:24:07 +02001435 }
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001436 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1437 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welteea280442009-02-02 22:29:56 +00001438 break;
1439 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001440 if (msg->data_len >= 7) {
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001441 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1442 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1443 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1444 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Holger Freyther8c563cf2009-02-03 20:08:51 +00001445 }
Harald Welteea280442009-02-02 22:29:56 +00001446 break;
1447 default:
1448 break;
1449 }
1450
1451 return 0;
1452}
1453
Harald Welte52b1f982008-12-23 20:25:15 +00001454static int abis_rsl_rx_cchan(struct msgb *msg)
1455{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001456 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001457 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001458 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001459
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001460 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +00001461
1462 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001463 case RSL_MT_CHAN_RQD:
1464 /* MS has requested a channel on the RACH */
1465 rc = rsl_rx_chan_rqd(msg);
1466 break;
Harald Welteea280442009-02-02 22:29:56 +00001467 case RSL_MT_CCCH_LOAD_IND:
1468 /* current load on the CCCH */
1469 rc = rsl_rx_ccch_load(msg);
1470 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001471 case RSL_MT_DELETE_IND:
1472 /* CCCH overloaded, IMM_ASSIGN was dropped */
1473 case RSL_MT_CBCH_LOAD_IND:
1474 /* current load on the CBCH */
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001475 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1476 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001477 break;
1478 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001479 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1480 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001481 return -EINVAL;
1482 }
Harald Welte8470bf22008-12-25 23:28:35 +00001483
1484 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001485}
1486
Harald Welte4b634542008-12-27 01:55:51 +00001487static int rsl_rx_rll_err_ind(struct msgb *msg)
1488{
1489 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001490 uint8_t *rlm_cause = rllh->data;
Harald Welte4b634542008-12-27 01:55:51 +00001491
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001492 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001493 gsm_lchan_name(msg->lchan),
Harald Weltee95daf12010-03-25 12:13:02 +08001494 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteedcc5272009-08-09 13:47:35 +02001495
1496 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001497
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001498 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001499 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001500 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001501 }
Harald Welte81543bc2009-07-04 09:40:05 +02001502
Harald Welte4b634542008-12-27 01:55:51 +00001503 return 0;
1504}
Harald Weltef325eb42009-02-19 17:07:39 +00001505
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001506static void rsl_handle_release(struct gsm_lchan *lchan)
1507{
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001508 int sapi;
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001509 struct gsm_bts *bts;
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001510
1511 /* maybe we have only brought down one RLL */
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001512 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001513 return;
1514
1515 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1516 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1517 continue;
Harald Welte3a3c2772010-12-24 12:51:07 +01001518 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001519 gsm_lchan_name(lchan), sapi);
1520 return;
1521 }
1522
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001523
1524
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001525 /* wait a bit to send the RF Channel Release */
1526 lchan->T3111.cb = t3111_expired;
1527 lchan->T3111.data = lchan;
1528 bts = lchan->ts->trx->bts;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001529 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001530}
1531
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001532/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte52b1f982008-12-23 20:25:15 +00001533 0x02, 0x06,
1534 0x01, 0x20,
1535 0x02, 0x00,
1536 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1537
1538static int abis_rsl_rx_rll(struct msgb *msg)
1539{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001540 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001541 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001542 int rc = 0;
1543 char *ts_name;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001544 uint8_t sapi = rllh->link_id & 7;
Harald Welte8470bf22008-12-25 23:28:35 +00001545
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001546 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001547 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte5b8ed432009-12-24 12:20:20 +01001548 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte52b1f982008-12-23 20:25:15 +00001549
1550 switch (rllh->c.msg_type) {
1551 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001552 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001553 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001554 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1555 rllh->data[0] == RSL_IE_L3_INFO) {
1556 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001557 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001558 }
Harald Welte52b1f982008-12-23 20:25:15 +00001559 break;
1560 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001561 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welteb7e81162009-08-10 00:26:10 +02001562 /* lchan is established, stop T3101 */
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001563 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001564 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001565 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001566 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1567 rllh->data[0] == RSL_IE_L3_INFO) {
1568 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001569 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001570 }
Harald Welte52b1f982008-12-23 20:25:15 +00001571 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001572 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001573 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001574 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteedcc5272009-08-09 13:47:35 +02001575 rll_indication(msg->lchan, rllh->link_id,
1576 BSC_RLLR_IND_EST_CONF);
1577 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001578 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001579 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001580 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001581 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteedcc5272009-08-09 13:47:35 +02001582 rll_indication(msg->lchan, rllh->link_id,
1583 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001584 rsl_handle_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001585 break;
1586 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001587 /* BTS informs us of having received UA from MS,
1588 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001589 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001590 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001591 rsl_handle_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001592 break;
1593 case RSL_MT_ERROR_IND:
1594 rc = rsl_rx_rll_err_ind(msg);
1595 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001596 case RSL_MT_UNIT_DATA_IND:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001597 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1598 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001599 break;
1600 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001601 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1602 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001603 }
Harald Welte8470bf22008-12-25 23:28:35 +00001604 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001605}
1606
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001607static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Weltef4e79f22009-07-28 18:11:56 +02001608{
Harald Welte0603c9d2009-12-02 01:58:23 +05301609 switch (lchan->tch_mode) {
Harald Weltef4e79f22009-07-28 18:11:56 +02001610 case GSM48_CMODE_SPEECH_V1:
Harald Welte0603c9d2009-12-02 01:58:23 +05301611 switch (lchan->type) {
1612 case GSM_LCHAN_TCH_F:
1613 return 0x00;
1614 case GSM_LCHAN_TCH_H:
1615 return 0x03;
1616 default:
1617 break;
1618 }
Harald Weltef4e79f22009-07-28 18:11:56 +02001619 case GSM48_CMODE_SPEECH_EFR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301620 switch (lchan->type) {
1621 case GSM_LCHAN_TCH_F:
1622 return 0x01;
1623 /* there's no half-rate EFR */
1624 default:
1625 break;
1626 }
Harald Weltef4e79f22009-07-28 18:11:56 +02001627 case GSM48_CMODE_SPEECH_AMR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301628 switch (lchan->type) {
1629 case GSM_LCHAN_TCH_F:
1630 return 0x02;
1631 case GSM_LCHAN_TCH_H:
1632 return 0x05;
1633 default:
1634 break;
1635 }
1636 default:
1637 break;
Harald Weltef4e79f22009-07-28 18:11:56 +02001638 }
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001639 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welte0603c9d2009-12-02 01:58:23 +05301640 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001641 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001642}
1643
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001644static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munautb54dda42009-12-20 22:06:40 +01001645{
1646 switch (lchan->tch_mode) {
1647 case GSM48_CMODE_SPEECH_V1:
1648 switch (lchan->type) {
1649 case GSM_LCHAN_TCH_F:
1650 return RTP_PT_GSM_FULL;
1651 case GSM_LCHAN_TCH_H:
1652 return RTP_PT_GSM_HALF;
1653 default:
1654 break;
1655 }
1656 case GSM48_CMODE_SPEECH_EFR:
1657 switch (lchan->type) {
1658 case GSM_LCHAN_TCH_F:
1659 return RTP_PT_GSM_EFR;
1660 /* there's no half-rate EFR */
1661 default:
1662 break;
1663 }
1664 case GSM48_CMODE_SPEECH_AMR:
1665 switch (lchan->type) {
1666 case GSM_LCHAN_TCH_F:
Sylvain Munautb54dda42009-12-20 22:06:40 +01001667 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freythered999b22011-07-21 10:24:46 +02001668 return RTP_PT_AMR;
Sylvain Munautb54dda42009-12-20 22:06:40 +01001669 default:
1670 break;
1671 }
1672 default:
1673 break;
1674 }
1675 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1676 "tch_mode == 0x%02x\n & lchan_type == %d",
1677 lchan->tch_mode, lchan->type);
1678 return 0;
1679}
1680
Harald Welte75099262009-02-16 21:12:08 +00001681/* ip.access specific RSL extensions */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001682static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1683{
1684 struct in_addr ip;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001685 uint16_t port, conn_id;
Harald Welte5e3d91b2009-12-19 16:42:06 +01001686
1687 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001688 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001689 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1690 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1691 }
1692
1693 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001694 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001695 port = ntohs(port);
1696 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1697 lchan->abis_ip.bound_port = port;
1698 }
1699
1700 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001701 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001702 conn_id = ntohs(conn_id);
1703 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1704 lchan->abis_ip.conn_id = conn_id;
1705 }
1706
1707 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1708 lchan->abis_ip.rtp_payload2 =
1709 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1710 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1711 lchan->abis_ip.rtp_payload2);
1712 }
1713
1714 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1715 lchan->abis_ip.speech_mode =
1716 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1717 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1718 lchan->abis_ip.speech_mode);
1719 }
1720
1721 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001722 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001723 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1724 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1725 }
1726
1727 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001728 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001729 port = ntohs(port);
1730 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1731 lchan->abis_ip.connect_port = port;
1732 }
1733}
1734
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001735int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte75099262009-02-16 21:12:08 +00001736{
1737 struct msgb *msg = rsl_msgb_alloc();
1738 struct abis_rsl_dchan_hdr *dh;
1739
1740 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001741 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte75099262009-02-16 21:12:08 +00001742 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001743 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001744
Harald Weltef4e79f22009-07-28 18:11:56 +02001745 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001746 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001747 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001748 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001749 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001750
Sylvain Munautb54dda42009-12-20 22:06:40 +01001751 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1752 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1753 lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001754
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001755 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001756
1757 return abis_rsl_sendmsg(msg);
1758}
1759
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001760int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1761 uint8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001762{
1763 struct msgb *msg = rsl_msgb_alloc();
1764 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001765 uint32_t *att_ip;
Harald Weltef4e79f22009-07-28 18:11:56 +02001766 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001767
1768 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001769 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte75099262009-02-16 21:12:08 +00001770 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001771 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001772
Harald Welte5e3d91b2009-12-19 16:42:06 +01001773 /* we need to store these now as MDCX_ACK does not return them :( */
1774 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1775 lchan->abis_ip.connect_port = port;
1776 lchan->abis_ip.connect_ip = ip;
1777
Harald Welte58ca5b72009-07-29 12:12:18 +02001778 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001779 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001780 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte58ca5b72009-07-29 12:12:18 +02001781
Harald Weltef4e79f22009-07-28 18:11:56 +02001782 ia.s_addr = htonl(ip);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001783 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1784 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1785 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1786 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001787
Harald Welte5e3d91b2009-12-19 16:42:06 +01001788 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1789 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001790 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001791 *att_ip = ia.s_addr;
1792 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1793 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001794 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001795 if (rtp_payload2)
1796 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001797
1798 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001799
1800 return abis_rsl_sendmsg(msg);
1801}
1802
Harald Weltea72273e2009-12-20 16:51:09 +01001803/* tell BTS to connect RTP stream to our local RTP socket */
1804int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1805{
1806 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1807 int rc;
1808
1809 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1810 ntohs(rs->rtp.sin_local.sin_port),
1811 /* FIXME: use RTP payload of bound socket, not BTS*/
1812 lchan->abis_ip.rtp_payload2);
1813
1814 return rc;
1815}
1816
Harald Welte53cd7ac2010-12-23 12:59:52 +01001817int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welte9c880c92009-10-24 10:29:22 +02001818{
1819 struct msgb *msg = rsl_msgb_alloc();
1820 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001821 uint8_t msg_type;
Harald Welte4563eab2010-03-28 14:42:09 +08001822
1823 if (act)
1824 msg_type = RSL_MT_IPAC_PDCH_ACT;
1825 else
1826 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welte9c880c92009-10-24 10:29:22 +02001827
1828 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte4563eab2010-03-28 14:42:09 +08001829 init_dchan_hdr(dh, msg_type);
Harald Welte9c880c92009-10-24 10:29:22 +02001830 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +02001831 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welte9c880c92009-10-24 10:29:22 +02001832
Harald Welte53cd7ac2010-12-23 12:59:52 +01001833 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte4563eab2010-03-28 14:42:09 +08001834 act ? "" : "DE");
Harald Welte9c880c92009-10-24 10:29:22 +02001835
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001836 msg->dst = ts->trx->rsl_link;
Harald Welte9c880c92009-10-24 10:29:22 +02001837
1838 return abis_rsl_sendmsg(msg);
1839}
1840
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001841static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001842{
1843 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1844 struct tlv_parsed tv;
Harald Welte2c828992009-12-02 01:56:49 +05301845 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75099262009-02-16 21:12:08 +00001846
1847 /* the BTS has acknowledged a local bind, it now tells us the IP
1848 * address and port number to which it has bound the given logical
1849 * channel */
1850
1851 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1852 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1853 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02001854 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001855 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001856 return -EINVAL;
1857 }
Harald Welte17f5bf62009-12-20 15:42:44 +01001858
Harald Welte5e3d91b2009-12-19 16:42:06 +01001859 ipac_parse_rtp(lchan, &tv);
Harald Welte17f5bf62009-12-20 15:42:44 +01001860
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001861 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte167df882009-02-17 14:35:45 +00001862
Harald Welte75099262009-02-16 21:12:08 +00001863 return 0;
1864}
1865
Harald Welte5e3d91b2009-12-19 16:42:06 +01001866static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1867{
1868 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1869 struct tlv_parsed tv;
1870 struct gsm_lchan *lchan = msg->lchan;
1871
1872 /* the BTS has acknowledged a remote connect request and
1873 * it now tells us the IP address and port number to which it has
1874 * connected the given logical channel */
1875
1876 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1877 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001878 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001879
1880 return 0;
1881}
1882
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001883static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001884{
1885 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1886 struct tlv_parsed tv;
1887
1888 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00001889
Harald Welte8830e072009-07-28 17:58:09 +02001890 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001891 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001892 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001893
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001894 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welte888b1142009-07-28 18:02:05 +02001895
Harald Welte75099262009-02-16 21:12:08 +00001896 return 0;
1897}
1898
1899static int abis_rsl_rx_ipacc(struct msgb *msg)
1900{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001901 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte75099262009-02-16 21:12:08 +00001902 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Welte5b8ed432009-12-24 12:20:20 +01001903 char *ts_name;
Harald Welte75099262009-02-16 21:12:08 +00001904 int rc = 0;
1905
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001906 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001907 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte75099262009-02-16 21:12:08 +00001908
1909 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001910 case RSL_MT_IPAC_CRCX_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001911 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001912 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001913 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001914 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001915 /* somehow the BTS was unable to bind the lchan to its local
1916 * port?!? */
Harald Welte5b8ed432009-12-24 12:20:20 +01001917 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001918 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001919 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte75099262009-02-16 21:12:08 +00001920 /* the BTS tells us that a connect operation was successful */
Harald Welte5b8ed432009-12-24 12:20:20 +01001921 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001922 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001923 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001924 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001925 /* somehow the BTS was unable to connect the lchan to a remote
1926 * port */
Harald Welte5b8ed432009-12-24 12:20:20 +01001927 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001928 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001929 case RSL_MT_IPAC_DLCX_IND:
Harald Welte5b8ed432009-12-24 12:20:20 +01001930 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001931 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte75099262009-02-16 21:12:08 +00001932 break;
1933 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001934 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001935 rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001936 break;
1937 }
Harald Welte6dab0552009-05-01 17:21:37 +00001938 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001939
1940 return rc;
1941}
1942
1943
Harald Welte52b1f982008-12-23 20:25:15 +00001944/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001945int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001946{
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001947 struct abis_rsl_common_hdr *rslh;
Harald Welte8f5e2392009-02-03 12:57:37 +00001948 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001949
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001950 if (!msg) {
1951 DEBUGP(DRSL, "Empty RSL msg?..\n");
1952 return -1;
1953 }
1954
1955 if (msgb_l2len(msg) < sizeof(*rslh)) {
1956 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltef25b55e2012-05-31 20:22:34 +02001957 msgb_free(msg);
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001958 return -1;
1959 }
1960
1961 rslh = msgb_l2(msg);
1962
Harald Welte52b1f982008-12-23 20:25:15 +00001963 switch (rslh->msg_discr & 0xfe) {
1964 case ABIS_RSL_MDISC_RLL:
1965 rc = abis_rsl_rx_rll(msg);
1966 break;
1967 case ABIS_RSL_MDISC_DED_CHAN:
1968 rc = abis_rsl_rx_dchan(msg);
1969 break;
1970 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00001971 rc = abis_rsl_rx_cchan(msg);
1972 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001973 case ABIS_RSL_MDISC_TRX:
1974 rc = abis_rsl_rx_trx(msg);
1975 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001976 case ABIS_RSL_MDISC_LOC:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001977 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte8f5e2392009-02-03 12:57:37 +00001978 rslh->msg_discr);
1979 break;
Harald Welte75099262009-02-16 21:12:08 +00001980 case ABIS_RSL_MDISC_IPACCESS:
1981 rc = abis_rsl_rx_ipacc(msg);
1982 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001983 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001984 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
1985 "0x%02x\n", rslh->msg_discr);
Harald Weltef25b55e2012-05-31 20:22:34 +02001986 rc = -EINVAL;
Harald Welte52b1f982008-12-23 20:25:15 +00001987 }
Harald Welte4f4a3902008-12-26 00:04:49 +00001988 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001989 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001990}
Holger Freyther3b72a892009-02-04 00:31:39 +00001991
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08001992int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
1993 uint8_t cb_command, const uint8_t *data, int len)
1994{
1995 struct abis_rsl_dchan_hdr *dh;
1996 struct msgb *cb_cmd;
1997
1998 cb_cmd = rsl_msgb_alloc();
1999 if (!cb_cmd)
2000 return -1;
2001
2002 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2003 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2004 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2005
2006 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2007 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2008
2009 cb_cmd->trx = bts->c0;
2010
2011 return abis_rsl_sendmsg(cb_cmd);
2012}
Dieter Spaar16646022011-07-28 00:01:50 +02002013
2014int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2015{
2016 struct abis_rsl_common_hdr *ch;
2017 struct msgb *msg = rsl_msgb_alloc();
2018
2019 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2020 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2021 ch->msg_type = 0x40; /* Nokia SI Begin */
2022
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002023 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002024
2025 return abis_rsl_sendmsg(msg);
2026}
2027
2028int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2029{
2030 struct abis_rsl_common_hdr *ch;
2031 struct msgb *msg = rsl_msgb_alloc();
2032
2033 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2034 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2035 ch->msg_type = 0x41; /* Nokia SI End */
2036
2037 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2038
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002039 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002040
2041 return abis_rsl_sendmsg(msg);
2042}
2043
2044int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2045{
2046 struct abis_rsl_common_hdr *ch;
2047 struct msgb *msg = rsl_msgb_alloc();
2048
2049 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2050 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2051 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2052
2053 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2054 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2055
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002056 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002057
2058 return abis_rsl_sendmsg(msg);
2059}
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +01002060
2061/**
2062 * Release all allocated SAPIs starting from @param start and
2063 * release them with the given release mode. Once the release
2064 * confirmation arrives it will be attempted to release the
2065 * the RF channel.
2066 */
2067int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
2068 enum rsl_rel_mode release_mode)
2069{
2070 int no_sapi = 1;
2071 int sapi;
2072
2073 for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
2074 uint8_t link_id;
2075 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
2076 continue;
2077
2078 link_id = sapi;
2079 if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
2080 link_id |= 0x40;
2081 rsl_release_request(lchan, link_id, release_mode);
2082 no_sapi = 0;
2083 }
2084
2085 return no_sapi;
2086}