blob: 04d5c61b3dd0a47dd89715f36bf7944d1b9e6ee4 [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) {
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200670 struct e1inp_sign_link *sign_link = msg->dst;
671
Holger Hans Peter Freyther9d50a272011-12-28 12:11:40 +0100672 /*
673 * FIXME: GSM 04.08 gives us two options for the abnormal
674 * chanel release. This can be either like in the non-existent
675 * sub-lcuase 3.5.1 or for the main signalling link deactivate
676 * the SACCH, start timer T3109 and consider the channel as
677 * released.
678 *
679 * This code is doing the later for all raido links and not
680 * only the main link. Right now all SAPIs are released on the
681 * local end, the SACCH will be de-activated and right now the
682 * T3111 will be started. First T3109 should be started and then
683 * the T3111.
684 *
685 * TODO: Move this out of the function.
686 */
687
688 /*
689 * sacch de-activate and "local end release"
690 */
691 rsl_deact_sacch(lchan);
692 rsl_release_sapis_from(lchan, 0, RSL_REL_LOCAL_END);
693
694 /*
695 * TODO: start T3109 now.
696 */
Holger Hans Peter Freyther44752d92010-06-08 11:53:33 +0800697 rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800698 lchan->error_timer.data = lchan;
699 lchan->error_timer.cb = error_timeout_cb;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +0200700 osmo_timer_schedule(&lchan->error_timer,
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200701 sign_link->trx->bts->network->T3111 + 2, 0);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800702 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000703
Harald Weltee8bd9e82011-08-10 23:26:33 +0200704 /* Start another timer or assume the BTS sends a ACK/NACK? */
705 lchan->act_timer.cb = lchan_deact_tmr_cb;
706 lchan->act_timer.data = lchan;
707 osmo_timer_schedule(&lchan->act_timer, 4, 0);
708
Harald Weltefd355a32011-03-04 13:41:31 +0100709 rc = abis_rsl_sendmsg(msg);
710
Harald Welte115d1032009-08-10 11:43:22 +0200711 /* BTS will respond by RF CHAN REL ACK */
Harald Welte26d79072011-01-14 23:18:59 +0100712#ifdef HSL_SR_1_0
Harald Weltefd355a32011-03-04 13:41:31 +0100713 /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */
714 if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0)
715 rc = rsl_rx_rf_chan_rel_ack(lchan);
Harald Welte26d79072011-01-14 23:18:59 +0100716#endif
Harald Weltefd355a32011-03-04 13:41:31 +0100717
718 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000719}
720
Harald Welte64bb7542011-01-14 14:16:16 +0100721static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
722{
723
724 DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
725
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100726 /* Stop all pending timers */
Harald Weltee8bd9e82011-08-10 23:26:33 +0200727 osmo_timer_del(&lchan->act_timer);
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100728 osmo_timer_del(&lchan->T3111);
Harald Weltee8bd9e82011-08-10 23:26:33 +0200729
Harald Welte64bb7542011-01-14 14:16:16 +0100730 if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
731 LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
732 gsm_lchan_name(lchan),
733 gsm_lchans_name(lchan->state));
Holger Hans Peter Freyther93599a22012-12-06 19:09:58 +0100734 do_lchan_free(lchan);
Harald Welte64bb7542011-01-14 14:16:16 +0100735
736 return 0;
737}
738
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200739int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
740 uint8_t *ms_ident, uint8_t chan_needed)
Harald Welte52b1f982008-12-23 20:25:15 +0000741{
742 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000743 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000744
745 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
746 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
747 dh->chan_nr = RSL_CHAN_PCH_AGCH;
748
749 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
Harald Welte255539c2008-12-28 02:26:27 +0000750 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000751 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
752
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200753 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000754
755 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000756}
757
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200758int imsi_str2bcd(uint8_t *bcd_out, const char *str_in)
Harald Welte52b1f982008-12-23 20:25:15 +0000759{
760 int i, len = strlen(str_in);
761
762 for (i = 0; i < len; i++) {
763 int num = str_in[i] - 0x30;
764 if (num < 0 || num > 9)
765 return -1;
766 if (i % 2 == 0)
767 bcd_out[i/2] = num;
768 else
769 bcd_out[i/2] |= (num << 4);
770 }
771
772 return 0;
773}
774
Harald Welte702d8702008-12-26 20:25:35 +0000775/* Chapter 8.5.6 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200776int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val)
Harald Welte52b1f982008-12-23 20:25:15 +0000777{
Harald Welte8470bf22008-12-25 23:28:35 +0000778 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000779 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200780 uint8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000781
782 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
783 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
784 dh->chan_nr = RSL_CHAN_PCH_AGCH;
785
Harald Welte362322e2009-02-15 14:36:38 +0000786 switch (bts->type) {
787 case GSM_BTS_TYPE_BS11:
788 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
789 break;
790 default:
791 /* If phase 2, construct a FULL_IMM_ASS_INFO */
792 pad_macblock(buf, val, len);
793 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
794 break;
795 }
Harald Welte52b1f982008-12-23 20:25:15 +0000796
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200797 msg->dst = bts->c0->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000798
799 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000800}
801
Harald Welte67fa91b2009-08-10 09:51:40 +0200802/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte31c48932009-08-10 10:07:33 +0200803int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte67fa91b2009-08-10 09:51:40 +0200804{
805 struct msgb *msg = rsl_msgb_alloc();
806 struct abis_rsl_dchan_hdr *dh;
807
808 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
809 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
Harald Welte3c456d02009-08-10 11:26:14 +0200810 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +0200811 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200812 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(uint8_t *)mrpci);
Harald Welte67fa91b2009-08-10 09:51:40 +0200813
Harald Welte5b8ed432009-12-24 12:20:20 +0100814 DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200815 gsm_lchan_name(lchan), *(uint8_t *)mrpci);
Harald Welte3c456d02009-08-10 11:26:14 +0200816
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200817 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte3c456d02009-08-10 11:26:14 +0200818
Harald Welte67fa91b2009-08-10 09:51:40 +0200819 return abis_rsl_sendmsg(msg);
820}
821
822
Harald Welte8470bf22008-12-25 23:28:35 +0000823/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000824/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200825int rsl_data_request(struct msgb *msg, uint8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000826{
Harald Welte8470bf22008-12-25 23:28:35 +0000827 if (msg->lchan == NULL) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100828 LOGP(DRSL, LOGL_ERROR, "cannot send DATA REQUEST to unknown lchan\n");
Harald Welte8470bf22008-12-25 23:28:35 +0000829 return -EINVAL;
830 }
Harald Welte52b1f982008-12-23 20:25:15 +0000831
Harald Weltef6093a42011-06-25 10:02:33 +0200832 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, gsm_lchan2chan_nr(msg->lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100833 link_id, 1);
Harald Welte52b1f982008-12-23 20:25:15 +0000834
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200835 msg->dst = msg->lchan->ts->trx->rsl_link;
Harald Welte8470bf22008-12-25 23:28:35 +0000836
837 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000838}
839
Harald Welteedcc5272009-08-09 13:47:35 +0200840/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
841/* Chapter 8.3.1 */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200842int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id)
Harald Welteedcc5272009-08-09 13:47:35 +0200843{
Harald Welte3c9c5f92010-03-04 10:33:10 +0100844 struct msgb *msg;
Harald Welteedcc5272009-08-09 13:47:35 +0200845
Harald Weltef6093a42011-06-25 10:02:33 +0200846 msg = rsl_rll_simple(RSL_MT_EST_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100847 link_id, 0);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200848 msg->dst = lchan->ts->trx->rsl_link;
Harald Welteedcc5272009-08-09 13:47:35 +0200849
Harald Weltefda74ee2012-04-26 19:42:19 +0200850 DEBUGP(DRLL, "%s RSL RLL ESTABLISH REQ (link_id=0x%02x)\n",
851 gsm_lchan_name(lchan), link_id);
852
Harald Welteedcc5272009-08-09 13:47:35 +0200853 return abis_rsl_sendmsg(msg);
854}
855
Harald Welted2dc1de2009-08-08 13:15:07 +0200856/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
857 This is what higher layers should call. The BTS then responds with
858 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
859 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
860 lchan_free() */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100861int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
862 enum rsl_rel_mode release_mode)
Harald Welted2dc1de2009-08-08 13:15:07 +0200863{
Harald Welted2dc1de2009-08-08 13:15:07 +0200864
Harald Welte3c9c5f92010-03-04 10:33:10 +0100865 struct msgb *msg;
866
Harald Weltef6093a42011-06-25 10:02:33 +0200867 msg = rsl_rll_simple(RSL_MT_REL_REQ, gsm_lchan2chan_nr(lchan),
Harald Welte3c9c5f92010-03-04 10:33:10 +0100868 link_id, 0);
Holger Hans Peter Freyther4f5848d2010-06-08 11:57:45 +0800869 /* 0 is normal release, 1 is local end */
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100870 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, release_mode);
Harald Welted2dc1de2009-08-08 13:15:07 +0200871
Harald Welte8e93b792009-12-29 10:44:17 +0100872 /* FIXME: start some timer in case we don't receive a REL ACK ? */
873
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +0200874 msg->dst = lchan->ts->trx->rsl_link;
Harald Welted2dc1de2009-08-08 13:15:07 +0200875
Harald Weltefda74ee2012-04-26 19:42:19 +0200876 DEBUGP(DRLL, "%s RSL RLL RELEASE REQ (link_id=0x%02x, reason=%u)\n",
Holger Hans Peter Freyther5ca825e2012-12-06 12:01:38 +0100877 gsm_lchan_name(lchan), link_id, release_mode);
Harald Weltefda74ee2012-04-26 19:42:19 +0200878
Harald Welted2dc1de2009-08-08 13:15:07 +0200879 return abis_rsl_sendmsg(msg);
880}
881
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200882int rsl_lchan_set_state(struct gsm_lchan *lchan, int state)
883{
884 lchan->state = state;
885 return 0;
886}
887
Harald Welte702d8702008-12-26 20:25:35 +0000888/* Chapter 8.4.2: Channel Activate Acknowledge */
889static int rsl_rx_chan_act_ack(struct msgb *msg)
890{
891 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
892
893 /* BTS has confirmed channel activation, we now need
894 * to assign the activated channel to the MS */
Harald Welte4b634542008-12-27 01:55:51 +0000895 if (rslh->ie_chan != RSL_IE_CHAN_NR)
896 return -EINVAL;
Harald Welted011e8b2009-11-29 22:45:52 +0100897
Harald Weltee8bd9e82011-08-10 23:26:33 +0200898 osmo_timer_del(&msg->lchan->act_timer);
899
Harald Welte8e93b792009-12-29 10:44:17 +0100900 if (msg->lchan->state != LCHAN_S_ACT_REQ)
Harald Welte1887f9d2009-12-29 10:52:38 +0100901 LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
902 gsm_lchan_name(msg->lchan),
903 gsm_lchans_name(msg->lchan->state));
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200904 rsl_lchan_set_state(msg->lchan, LCHAN_S_ACTIVE);
Harald Welteb8bfc562009-12-21 13:27:11 +0100905
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +0800906 if (msg->lchan->rqd_ref) {
907 rsl_send_imm_assignment(msg->lchan);
908 talloc_free(msg->lchan->rqd_ref);
909 msg->lchan->rqd_ref = NULL;
910 msg->lchan->rqd_ta = 0;
911 }
912
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100913 send_lchan_signal(S_LCHAN_ACTIVATE_ACK, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +0100914
Harald Welte4b634542008-12-27 01:55:51 +0000915 return 0;
916}
Harald Welte702d8702008-12-26 20:25:35 +0000917
Harald Welte4b634542008-12-27 01:55:51 +0000918/* Chapter 8.4.3: Channel Activate NACK */
919static int rsl_rx_chan_act_nack(struct msgb *msg)
920{
Harald Welte6dab0552009-05-01 17:21:37 +0000921 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
922 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +0000923
Harald Weltee8bd9e82011-08-10 23:26:33 +0200924 osmo_timer_del(&msg->lchan->act_timer);
925
Daniel Willmann6fc6a122011-08-11 04:54:23 +0200926 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100927 gsm_lchan_name(msg->lchan));
Harald Welte (local)91b603d2009-12-27 11:48:11 +0100928
Harald Welte6dab0552009-05-01 17:21:37 +0000929 /* BTS has rejected channel activation ?!? */
930 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +0000931 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +0000932
933 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte (local)3e460312009-12-27 18:12:29 +0100934 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200935 const uint8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
Harald Welte (local)3e460312009-12-27 18:12:29 +0100936 print_rsl_cause(LOGL_ERROR, cause,
Harald Welte8830e072009-07-28 17:58:09 +0200937 TLVP_LEN(&tp, RSL_IE_CAUSE));
Holger Hans Peter Freyther638da512012-12-06 19:25:06 +0100938 msg->lchan->error_cause = *cause;
Harald Welte (local)3e460312009-12-27 18:12:29 +0100939 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther638da512012-12-06 19:25:06 +0100940 rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
Daniel Willmann7ddc3182011-08-11 04:47:11 +0200941 else
942 rsl_rf_chan_release(msg->lchan, 1);
943
Harald Welte (local)3e460312009-12-27 18:12:29 +0100944 } else
Holger Hans Peter Freyther638da512012-12-06 19:25:06 +0100945 rsl_lchan_set_state(msg->lchan, LCHAN_S_BROKEN);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200946
Harald Welte (local)91b603d2009-12-27 11:48:11 +0100947 LOGPC(DRSL, LOGL_ERROR, "\n");
948
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100949 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welte4b634542008-12-27 01:55:51 +0000950 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000951}
952
Harald Welte7f93cea2009-02-23 00:02:59 +0000953/* Chapter 8.4.4: Connection Failure Indication */
954static int rsl_rx_conn_fail(struct msgb *msg)
955{
956 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
957 struct tlv_parsed tp;
958
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100959 /* FIXME: print which channel */
Harald Welte (local)fc057502009-12-26 22:33:09 +0100960 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100961 gsm_lchan_name(msg->lchan));
Harald Welte7f93cea2009-02-23 00:02:59 +0000962
963 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
964
Harald Welte8830e072009-07-28 17:58:09 +0200965 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +0100966 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +0200967 TLVP_LEN(&tp, RSL_IE_CAUSE));
968
Harald Welte (local)fc057502009-12-26 22:33:09 +0100969 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000970 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200971 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800972 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte7f93cea2009-02-23 00:02:59 +0000973}
974
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100975static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
976 const char *prefix)
977{
Harald Welte6739dfb2009-12-16 16:52:07 +0100978 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
979 prefix, rxlev2dbm(mru->full.rx_lev),
980 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100981 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
982 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
983}
984
Harald Welte0c1bd612012-07-02 17:12:08 +0200985static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100986{
Harald Welte6739dfb2009-12-16 16:52:07 +0100987 int i;
Harald Welte0c1bd612012-07-02 17:12:08 +0200988 char *name = "";
Harald Welte6739dfb2009-12-16 16:52:07 +0100989
Harald Welte0c1bd612012-07-02 17:12:08 +0200990 if (lchan && lchan->conn && lchan->conn->subscr)
991 name = subscr_name(lchan->conn->subscr);
992
993 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100994
995 if (mr->flags & MEAS_REP_F_DL_DTX)
996 DEBUGPC(DMEAS, "DTXd ");
997
998 print_meas_rep_uni(&mr->ul, "ul");
999 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
1000 if (mr->flags & MEAS_REP_F_MS_TO)
1001 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
1002
1003 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte6739dfb2009-12-16 16:52:07 +01001004 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001005 DEBUGPC(DMEAS, "L1_FPC=%u ",
1006 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
1007 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
1008 }
1009
1010 if (mr->flags & MEAS_REP_F_UL_DTX)
1011 DEBUGPC(DMEAS, "DTXu ");
1012 if (mr->flags & MEAS_REP_F_BA1)
1013 DEBUGPC(DMEAS, "BA1 ");
1014 if (!(mr->flags & MEAS_REP_F_DL_VALID))
1015 DEBUGPC(DMEAS, "NOT VALID ");
1016 else
1017 print_meas_rep_uni(&mr->dl, "dl");
1018
1019 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte479015b2009-12-19 18:33:05 +01001020 if (mr->num_cell == 7)
1021 return;
Harald Welte6739dfb2009-12-16 16:52:07 +01001022 for (i = 0; i < mr->num_cell; i++) {
1023 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte303e5e02009-12-25 23:02:22 +01001024 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1025 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte6739dfb2009-12-16 16:52:07 +01001026 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001027}
1028
Harald Welte440fed02009-05-01 18:43:47 +00001029static int rsl_rx_meas_res(struct msgb *msg)
1030{
1031 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1032 struct tlv_parsed tp;
Harald Welted12b0fd2009-12-15 21:36:05 +01001033 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001034 uint8_t len;
1035 const uint8_t *val;
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001036 int rc;
Harald Welte440fed02009-05-01 18:43:47 +00001037
Harald Welteb8bfc562009-12-21 13:27:11 +01001038 /* check if this channel is actually active */
1039 /* FIXME: maybe this check should be way more generic/centralized */
Harald Welte8e93b792009-12-29 10:44:17 +01001040 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freytherc44db4a2010-07-29 14:50:57 +08001041 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Welte8e93b792009-12-29 10:44:17 +01001042 gsm_lchan_name(msg->lchan));
Harald Welteb8bfc562009-12-21 13:27:11 +01001043 return 0;
Harald Welte8e93b792009-12-29 10:44:17 +01001044 }
Harald Welteb8bfc562009-12-21 13:27:11 +01001045
Harald Welted12b0fd2009-12-15 21:36:05 +01001046 memset(mr, 0, sizeof(*mr));
Harald Welte33e65972009-12-16 23:29:34 +01001047 mr->lchan = msg->lchan;
Harald Weltedbb1d882009-11-30 19:16:47 +01001048
Harald Welte440fed02009-05-01 18:43:47 +00001049 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1050
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001051 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1052 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1053 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1054 return -EIO;
1055
1056 /* Mandatory Parts */
Harald Welted12b0fd2009-12-15 21:36:05 +01001057 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001058
1059 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1060 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1061 if (len >= 3) {
1062 if (val[0] & 0x40)
Harald Welted12b0fd2009-12-15 21:36:05 +01001063 mr->flags |= MEAS_REP_F_DL_DTX;
1064 mr->ul.full.rx_lev = val[0] & 0x3f;
1065 mr->ul.sub.rx_lev = val[1] & 0x3f;
1066 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1067 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte440fed02009-05-01 18:43:47 +00001068 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001069
Harald Welted12b0fd2009-12-15 21:36:05 +01001070 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001071
1072 /* Optional Parts */
Harald Welte440fed02009-05-01 18:43:47 +00001073 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welted12b0fd2009-12-15 21:36:05 +01001074 mr->ms_timing_offset =
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001075 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1076
Harald Weltefe9af262009-06-20 18:44:35 +02001077 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001078 struct e1inp_sign_link *sign_link = msg->dst;
1079
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001080 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001081 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001082 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001083 if (val[0] & 0x04)
Harald Welted12b0fd2009-12-15 21:36:05 +01001084 mr->flags |= MEAS_REP_F_FPC;
1085 mr->ms_l1.ta = val[1];
Andreas Eversberg3365cd12011-12-24 11:49:05 +01001086 /* BS11 and Nokia reports TA shifted by 2 bits */
1087 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1088 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg2957de92011-12-16 17:45:37 +01001089 mr->ms_l1.ta >>= 2;
Harald Weltefe9af262009-06-20 18:44:35 +02001090 }
Harald Weltef7c43522009-06-09 20:24:21 +00001091 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001092 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001093 rc = gsm48_parse_meas_rep(mr, msg);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001094 if (rc < 0)
1095 return rc;
1096 }
1097
Harald Welte0c1bd612012-07-02 17:12:08 +02001098 print_meas_rep(msg->lchan, mr);
Harald Welte60d68f12009-06-05 20:07:43 +00001099
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001100 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Weltedbb1d882009-11-30 19:16:47 +01001101
Harald Welte75d34a82009-05-23 06:11:13 +00001102 return 0;
Harald Welte440fed02009-05-01 18:43:47 +00001103}
1104
Harald Welted011e8b2009-11-29 22:45:52 +01001105/* Chapter 8.4.7 */
1106static int rsl_rx_hando_det(struct msgb *msg)
1107{
1108 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1109 struct tlv_parsed tp;
1110
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001111 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welted011e8b2009-11-29 22:45:52 +01001112
1113 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1114
1115 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1116 DEBUGPC(DRSL, "access delay = %u\n",
1117 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1118 else
1119 DEBUGPC(DRSL, "\n");
1120
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001121 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +01001122
1123 return 0;
1124}
1125
Harald Welte52b1f982008-12-23 20:25:15 +00001126static int abis_rsl_rx_dchan(struct msgb *msg)
1127{
Harald Welte8470bf22008-12-25 23:28:35 +00001128 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1129 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +00001130 char *ts_name;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001131 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001132
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001133 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001134 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltef325eb42009-02-19 17:07:39 +00001135
Harald Welte8470bf22008-12-25 23:28:35 +00001136 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001137 case RSL_MT_CHAN_ACTIV_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001138 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte4b634542008-12-27 01:55:51 +00001139 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001140 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001141 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte4b634542008-12-27 01:55:51 +00001142 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001143 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001144 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +00001145 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001146 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001147 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +00001148 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +00001149 break;
Harald Welted011e8b2009-11-29 22:45:52 +01001150 case RSL_MT_HANDO_DET:
1151 rc = rsl_rx_hando_det(msg);
1152 break;
Harald Welte2d5b6382008-12-27 19:46:06 +00001153 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte64bb7542011-01-14 14:16:16 +01001154 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +00001155 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001156 case RSL_MT_MODE_MODIFY_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001157 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001158 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001159 case RSL_MT_MODE_MODIFY_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001160 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001161 break;
Harald Welte9c880c92009-10-24 10:29:22 +02001162 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001163 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001164 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001165 break;
1166 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001167 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001168 break;
1169 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001170 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001171 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001172 break;
1173 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001174 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001175 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001176 case RSL_MT_PHY_CONTEXT_CONF:
1177 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +00001178 case RSL_MT_TALKER_DET:
1179 case RSL_MT_LISTENER_DET:
1180 case RSL_MT_REMOTE_CODEC_CONF_REP:
1181 case RSL_MT_MR_CODEC_MOD_ACK:
1182 case RSL_MT_MR_CODEC_MOD_NACK:
1183 case RSL_MT_MR_CODEC_MOD_PER:
Harald Welte5b8ed432009-12-24 12:20:20 +01001184 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1185 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001186 break;
1187 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001188 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1189 ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001190 return -EINVAL;
1191 }
Harald Weltef325eb42009-02-19 17:07:39 +00001192
Harald Welte8470bf22008-12-25 23:28:35 +00001193 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001194}
1195
Harald Welte702d8702008-12-26 20:25:35 +00001196static int rsl_rx_error_rep(struct msgb *msg)
1197{
1198 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +02001199 struct tlv_parsed tp;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001200 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte702d8702008-12-26 20:25:35 +00001201
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001202 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Welte8830e072009-07-28 17:58:09 +02001203
1204 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1205
1206 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001207 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001208 TLVP_LEN(&tp, RSL_IE_CAUSE));
1209
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001210 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001211
1212 return 0;
1213}
1214
Harald Welte52b1f982008-12-23 20:25:15 +00001215static int abis_rsl_rx_trx(struct msgb *msg)
1216{
Harald Welte702d8702008-12-26 20:25:35 +00001217 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001218 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte8470bf22008-12-25 23:28:35 +00001219 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001220
1221 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001222 case RSL_MT_ERROR_REPORT:
1223 rc = rsl_rx_error_rep(msg);
1224 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001225 case RSL_MT_RF_RES_IND:
1226 /* interference on idle channels of TRX */
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001227 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte8f5e2392009-02-03 12:57:37 +00001228 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001229 case RSL_MT_OVERLOAD:
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001230 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001231 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001232 gsm_trx_name(sign_link->trx));
Harald Welte52b1f982008-12-23 20:25:15 +00001233 break;
Dieter Spaar16646022011-07-28 00:01:50 +02001234 case 0x42: /* Nokia specific: SI End ACK */
1235 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1236 break;
1237 case 0x43: /* Nokia specific: SI End NACK */
1238 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1239 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001240 default:
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001241 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001242 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001243 return -EINVAL;
1244 }
Harald Welte8470bf22008-12-25 23:28:35 +00001245 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001246}
1247
Harald Welteb7e81162009-08-10 00:26:10 +02001248/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1249static void t3101_expired(void *data)
1250{
1251 struct gsm_lchan *lchan = data;
1252
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001253 rsl_rf_chan_release(lchan, 1);
Harald Welteb7e81162009-08-10 00:26:10 +02001254}
1255
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001256/* If T3111 expires, we will send the RF Channel Request */
1257static void t3111_expired(void *data)
1258{
1259 struct gsm_lchan *lchan = data;
1260
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001261 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001262}
1263
laforgecfa4a012010-06-21 12:08:52 +02001264#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1265
Harald Welte2862dca2010-12-23 14:39:29 +01001266/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1267static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1268 unsigned int num_req_refs,
1269 struct gsm48_req_ref *rqd_refs,
1270 uint8_t wait_ind)
1271{
1272 uint8_t buf[GSM_MACBLOCK_LEN];
1273 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1274
1275 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1276 memset(iar, 0, sizeof(*iar));
1277 iar->proto_discr = GSM48_PDISC_RR;
1278 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1279 iar->page_mode = GSM48_PM_SAME;
1280
1281 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1282 iar->wait_ind1 = wait_ind;
1283
1284 if (num_req_refs >= 2)
1285 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1286 else
1287 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1288 iar->wait_ind2 = wait_ind;
1289
1290 if (num_req_refs >= 3)
1291 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1292 else
1293 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1294 iar->wait_ind3 = wait_ind;
1295
1296 if (num_req_refs >= 4)
1297 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1298 else
1299 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1300 iar->wait_ind4 = wait_ind;
1301
1302 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1303}
1304
Harald Welte8470bf22008-12-25 23:28:35 +00001305/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001306static int rsl_rx_chan_rqd(struct msgb *msg)
1307{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001308 struct e1inp_sign_link *sign_link = msg->dst;
1309 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001310 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1311 struct gsm48_req_ref *rqd_ref;
Harald Welte8470bf22008-12-25 23:28:35 +00001312 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001313 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001314 struct gsm_lchan *lchan;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001315 uint8_t rqd_ta;
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001316 int is_lu;
Harald Welte8470bf22008-12-25 23:28:35 +00001317
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001318 uint16_t arfcn;
Holger Hans Peter Freytherc6d0a172012-02-03 20:10:13 +01001319 uint8_t subch;
Harald Welte52b1f982008-12-23 20:25:15 +00001320
Harald Welte8470bf22008-12-25 23:28:35 +00001321 /* parse request reference to be used in immediate assign */
1322 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1323 return -EINVAL;
1324
1325 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1326
1327 /* parse access delay and use as TA */
1328 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1329 return -EINVAL;
1330 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1331
1332 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1333 * request reference RA */
Holger Hans Peter Freyther78891072010-09-06 09:36:02 +08001334 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1335 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte2cbe0922008-12-29 04:09:31 +00001336
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001337 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte24ff6ee2009-12-22 00:41:05 +01001338
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001339 /*
1340 * We want LOCATION UPDATES to succeed and will assign a TCH
1341 * if we have no SDCCH available.
1342 */
1343 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1344
Harald Welte8470bf22008-12-25 23:28:35 +00001345 /* check availability / allocate channel */
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001346 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte8470bf22008-12-25 23:28:35 +00001347 if (!lchan) {
Harald Welte (local)2f5df852009-12-27 13:48:09 +01001348 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)ccd88452009-12-27 18:05:25 +01001349 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001350 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Welte2862dca2010-12-23 14:39:29 +01001351 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1352 if (bts->network->T3122)
1353 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte8470bf22008-12-25 23:28:35 +00001354 return -ENOMEM;
1355 }
1356
Harald Welte8e93b792009-12-29 10:44:17 +01001357 if (lchan->state != LCHAN_S_NONE)
1358 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welte1887f9d2009-12-29 10:52:38 +01001359 "in state %s\n", gsm_lchan_name(lchan),
1360 gsm_lchans_name(lchan->state));
Harald Welte (local)3e460312009-12-27 18:12:29 +01001361
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001362 /* save the RACH data as we need it after the CHAN ACT ACK */
1363 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1364 if (!lchan->rqd_ref) {
1365 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1366 lchan_free(lchan);
1367 return -ENOMEM;
1368 }
1369
Holger Hans Peter Freytherc0a66742011-12-29 23:33:04 +01001370 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001371 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1372 lchan->rqd_ta = rqd_ta;
1373
Harald Welte8470bf22008-12-25 23:28:35 +00001374 arfcn = lchan->ts->trx->arfcn;
1375 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001376
Harald Welte08d91a52009-08-30 15:37:11 +09001377 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)0e451d02009-08-13 10:14:26 +02001378 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte0b2124b2009-08-10 00:45:40 +02001379 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte9943c5b2009-07-29 15:41:29 +02001380 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte196d0522009-08-28 23:28:28 +09001381 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001382
Harald Weltee8bd9e82011-08-10 23:26:33 +02001383 /* Start another timer or assume the BTS sends a ACK/NACK? */
1384 lchan->act_timer.cb = lchan_act_tmr_cb;
1385 lchan->act_timer.data = lchan;
1386 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1387
Andreas Eversberg2957de92011-12-16 17:45:37 +01001388 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1389 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1390 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1391 rqd_ref->ra, rqd_ta);
1392
1393 /* BS11 requires TA shifted by 2 bits */
1394 if (bts->type == GSM_BTS_TYPE_BS11)
1395 rqd_ta <<= 2;
Harald Welte8d77b952009-12-17 00:31:10 +01001396 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001397
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001398 return 0;
1399}
1400
1401static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1402{
1403 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001404 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001405 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1406
Harald Welte52b1f982008-12-23 20:25:15 +00001407 /* create IMMEDIATE ASSIGN 04.08 messge */
laforge09108bf2010-06-20 15:18:46 +02001408 memset(ia, 0, sizeof(*ia));
laforgecfa4a012010-06-21 12:08:52 +02001409 /* we set ia->l2_plen once we know the length of the MA below */
laforge09108bf2010-06-20 15:18:46 +02001410 ia->proto_discr = GSM48_PDISC_RR;
1411 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1412 ia->page_mode = GSM48_PM_SAME;
1413 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea39b0f22010-06-14 22:26:10 +02001414
Harald Welte8470bf22008-12-25 23:28:35 +00001415 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001416 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1417 ia->timing_advance = lchan->rqd_ta;
Harald Weltea39b0f22010-06-14 22:26:10 +02001418 if (!lchan->ts->hopping.enabled) {
laforge09108bf2010-06-20 15:18:46 +02001419 ia->mob_alloc_len = 0;
Harald Weltea39b0f22010-06-14 22:26:10 +02001420 } else {
laforge09108bf2010-06-20 15:18:46 +02001421 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1422 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea39b0f22010-06-14 22:26:10 +02001423 }
Harald Weltea1d39a22010-06-28 18:41:27 +02001424 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1425 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte52b1f982008-12-23 20:25:15 +00001426
Harald Welteb7e81162009-08-10 00:26:10 +02001427 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1428 lchan->T3101.cb = t3101_expired;
1429 lchan->T3101.data = lchan;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001430 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Holger Freyther3186bf22008-12-29 06:23:49 +00001431
Harald Welte52b1f982008-12-23 20:25:15 +00001432 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001433 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte52b1f982008-12-23 20:25:15 +00001434}
1435
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001436/* current load on the CCCH */
Harald Welteea280442009-02-02 22:29:56 +00001437static int rsl_rx_ccch_load(struct msgb *msg)
1438{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001439 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001440 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001441 struct ccch_signal_data sd;
1442
1443 sd.bts = sign_link->trx->bts;
1444 sd.rach_slot_count = -1;
1445 sd.rach_busy_count = -1;
1446 sd.rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001447
1448 switch (rslh->data[0]) {
1449 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001450 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1451 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte38e9c822010-04-19 10:24:07 +02001452 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001453 sd.pg_buf_space = 50;
Harald Welte38e9c822010-04-19 10:24:07 +02001454 }
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001455 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1456 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welteea280442009-02-02 22:29:56 +00001457 break;
1458 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001459 if (msg->data_len >= 7) {
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001460 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1461 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1462 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1463 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Holger Freyther8c563cf2009-02-03 20:08:51 +00001464 }
Harald Welteea280442009-02-02 22:29:56 +00001465 break;
1466 default:
1467 break;
1468 }
1469
1470 return 0;
1471}
1472
Harald Welte52b1f982008-12-23 20:25:15 +00001473static int abis_rsl_rx_cchan(struct msgb *msg)
1474{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001475 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001476 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001477 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001478
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001479 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +00001480
1481 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001482 case RSL_MT_CHAN_RQD:
1483 /* MS has requested a channel on the RACH */
1484 rc = rsl_rx_chan_rqd(msg);
1485 break;
Harald Welteea280442009-02-02 22:29:56 +00001486 case RSL_MT_CCCH_LOAD_IND:
1487 /* current load on the CCCH */
1488 rc = rsl_rx_ccch_load(msg);
1489 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001490 case RSL_MT_DELETE_IND:
1491 /* CCCH overloaded, IMM_ASSIGN was dropped */
1492 case RSL_MT_CBCH_LOAD_IND:
1493 /* current load on the CBCH */
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001494 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1495 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001496 break;
1497 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001498 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1499 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001500 return -EINVAL;
1501 }
Harald Welte8470bf22008-12-25 23:28:35 +00001502
1503 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001504}
1505
Harald Welte4b634542008-12-27 01:55:51 +00001506static int rsl_rx_rll_err_ind(struct msgb *msg)
1507{
1508 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001509 uint8_t *rlm_cause = rllh->data;
Harald Welte4b634542008-12-27 01:55:51 +00001510
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001511 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001512 gsm_lchan_name(msg->lchan),
Harald Weltee95daf12010-03-25 12:13:02 +08001513 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteedcc5272009-08-09 13:47:35 +02001514
1515 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001516
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001517 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001518 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001519 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001520 }
Harald Welte81543bc2009-07-04 09:40:05 +02001521
Harald Welte4b634542008-12-27 01:55:51 +00001522 return 0;
1523}
Harald Weltef325eb42009-02-19 17:07:39 +00001524
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001525static void rsl_handle_release(struct gsm_lchan *lchan)
1526{
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001527 int sapi;
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001528 struct gsm_bts *bts;
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001529
Holger Hans Peter Freyther9d50a272011-12-28 12:11:40 +01001530 /*
1531 * Maybe only one link/SAPI was releasd or the error handling
1532 * was activated. Just return now and let the other code handle
1533 * it.
1534 */
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001535 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001536 return;
1537
1538 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1539 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1540 continue;
Harald Welte3a3c2772010-12-24 12:51:07 +01001541 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001542 gsm_lchan_name(lchan), sapi);
1543 return;
1544 }
1545
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001546
1547
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001548 /* wait a bit to send the RF Channel Release */
1549 lchan->T3111.cb = t3111_expired;
1550 lchan->T3111.data = lchan;
1551 bts = lchan->ts->trx->bts;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001552 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001553}
1554
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001555/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte52b1f982008-12-23 20:25:15 +00001556 0x02, 0x06,
1557 0x01, 0x20,
1558 0x02, 0x00,
1559 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1560
1561static int abis_rsl_rx_rll(struct msgb *msg)
1562{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001563 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001564 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001565 int rc = 0;
1566 char *ts_name;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001567 uint8_t sapi = rllh->link_id & 7;
Harald Welte8470bf22008-12-25 23:28:35 +00001568
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001569 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001570 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte5b8ed432009-12-24 12:20:20 +01001571 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte52b1f982008-12-23 20:25:15 +00001572
1573 switch (rllh->c.msg_type) {
1574 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001575 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001576 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001577 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1578 rllh->data[0] == RSL_IE_L3_INFO) {
1579 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001580 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001581 }
Harald Welte52b1f982008-12-23 20:25:15 +00001582 break;
1583 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001584 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welteb7e81162009-08-10 00:26:10 +02001585 /* lchan is established, stop T3101 */
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001586 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001587 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001588 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001589 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1590 rllh->data[0] == RSL_IE_L3_INFO) {
1591 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001592 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001593 }
Harald Welte52b1f982008-12-23 20:25:15 +00001594 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001595 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001596 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001597 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteedcc5272009-08-09 13:47:35 +02001598 rll_indication(msg->lchan, rllh->link_id,
1599 BSC_RLLR_IND_EST_CONF);
1600 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001601 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001602 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001603 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001604 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteedcc5272009-08-09 13:47:35 +02001605 rll_indication(msg->lchan, rllh->link_id,
1606 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001607 rsl_handle_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001608 break;
1609 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001610 /* BTS informs us of having received UA from MS,
1611 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001612 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001613 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001614 rsl_handle_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001615 break;
1616 case RSL_MT_ERROR_IND:
1617 rc = rsl_rx_rll_err_ind(msg);
1618 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001619 case RSL_MT_UNIT_DATA_IND:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001620 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1621 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001622 break;
1623 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001624 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1625 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001626 }
Harald Welte8470bf22008-12-25 23:28:35 +00001627 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001628}
1629
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001630static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Weltef4e79f22009-07-28 18:11:56 +02001631{
Harald Welte0603c9d2009-12-02 01:58:23 +05301632 switch (lchan->tch_mode) {
Harald Weltef4e79f22009-07-28 18:11:56 +02001633 case GSM48_CMODE_SPEECH_V1:
Harald Welte0603c9d2009-12-02 01:58:23 +05301634 switch (lchan->type) {
1635 case GSM_LCHAN_TCH_F:
1636 return 0x00;
1637 case GSM_LCHAN_TCH_H:
1638 return 0x03;
1639 default:
1640 break;
1641 }
Harald Weltef4e79f22009-07-28 18:11:56 +02001642 case GSM48_CMODE_SPEECH_EFR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301643 switch (lchan->type) {
1644 case GSM_LCHAN_TCH_F:
1645 return 0x01;
1646 /* there's no half-rate EFR */
1647 default:
1648 break;
1649 }
Harald Weltef4e79f22009-07-28 18:11:56 +02001650 case GSM48_CMODE_SPEECH_AMR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301651 switch (lchan->type) {
1652 case GSM_LCHAN_TCH_F:
1653 return 0x02;
1654 case GSM_LCHAN_TCH_H:
1655 return 0x05;
1656 default:
1657 break;
1658 }
1659 default:
1660 break;
Harald Weltef4e79f22009-07-28 18:11:56 +02001661 }
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001662 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welte0603c9d2009-12-02 01:58:23 +05301663 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001664 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001665}
1666
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001667static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munautb54dda42009-12-20 22:06:40 +01001668{
1669 switch (lchan->tch_mode) {
1670 case GSM48_CMODE_SPEECH_V1:
1671 switch (lchan->type) {
1672 case GSM_LCHAN_TCH_F:
1673 return RTP_PT_GSM_FULL;
1674 case GSM_LCHAN_TCH_H:
1675 return RTP_PT_GSM_HALF;
1676 default:
1677 break;
1678 }
1679 case GSM48_CMODE_SPEECH_EFR:
1680 switch (lchan->type) {
1681 case GSM_LCHAN_TCH_F:
1682 return RTP_PT_GSM_EFR;
1683 /* there's no half-rate EFR */
1684 default:
1685 break;
1686 }
1687 case GSM48_CMODE_SPEECH_AMR:
1688 switch (lchan->type) {
1689 case GSM_LCHAN_TCH_F:
Sylvain Munautb54dda42009-12-20 22:06:40 +01001690 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freythered999b22011-07-21 10:24:46 +02001691 return RTP_PT_AMR;
Sylvain Munautb54dda42009-12-20 22:06:40 +01001692 default:
1693 break;
1694 }
1695 default:
1696 break;
1697 }
1698 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1699 "tch_mode == 0x%02x\n & lchan_type == %d",
1700 lchan->tch_mode, lchan->type);
1701 return 0;
1702}
1703
Harald Welte75099262009-02-16 21:12:08 +00001704/* ip.access specific RSL extensions */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001705static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1706{
1707 struct in_addr ip;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001708 uint16_t port, conn_id;
Harald Welte5e3d91b2009-12-19 16:42:06 +01001709
1710 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001711 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001712 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1713 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1714 }
1715
1716 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001717 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001718 port = ntohs(port);
1719 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1720 lchan->abis_ip.bound_port = port;
1721 }
1722
1723 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001724 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001725 conn_id = ntohs(conn_id);
1726 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1727 lchan->abis_ip.conn_id = conn_id;
1728 }
1729
1730 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1731 lchan->abis_ip.rtp_payload2 =
1732 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1733 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1734 lchan->abis_ip.rtp_payload2);
1735 }
1736
1737 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1738 lchan->abis_ip.speech_mode =
1739 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1740 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1741 lchan->abis_ip.speech_mode);
1742 }
1743
1744 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001745 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001746 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1747 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1748 }
1749
1750 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001751 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001752 port = ntohs(port);
1753 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1754 lchan->abis_ip.connect_port = port;
1755 }
1756}
1757
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001758int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte75099262009-02-16 21:12:08 +00001759{
1760 struct msgb *msg = rsl_msgb_alloc();
1761 struct abis_rsl_dchan_hdr *dh;
1762
1763 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001764 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte75099262009-02-16 21:12:08 +00001765 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001766 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001767
Harald Weltef4e79f22009-07-28 18:11:56 +02001768 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001769 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001770 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001771 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001772 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001773
Sylvain Munautb54dda42009-12-20 22:06:40 +01001774 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1775 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1776 lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001777
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001778 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001779
1780 return abis_rsl_sendmsg(msg);
1781}
1782
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001783int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1784 uint8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001785{
1786 struct msgb *msg = rsl_msgb_alloc();
1787 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001788 uint32_t *att_ip;
Harald Weltef4e79f22009-07-28 18:11:56 +02001789 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001790
1791 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001792 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte75099262009-02-16 21:12:08 +00001793 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001794 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001795
Harald Welte5e3d91b2009-12-19 16:42:06 +01001796 /* we need to store these now as MDCX_ACK does not return them :( */
1797 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1798 lchan->abis_ip.connect_port = port;
1799 lchan->abis_ip.connect_ip = ip;
1800
Harald Welte58ca5b72009-07-29 12:12:18 +02001801 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001802 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001803 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte58ca5b72009-07-29 12:12:18 +02001804
Harald Weltef4e79f22009-07-28 18:11:56 +02001805 ia.s_addr = htonl(ip);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001806 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1807 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1808 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1809 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001810
Harald Welte5e3d91b2009-12-19 16:42:06 +01001811 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1812 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001813 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001814 *att_ip = ia.s_addr;
1815 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1816 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001817 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001818 if (rtp_payload2)
1819 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001820
1821 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001822
1823 return abis_rsl_sendmsg(msg);
1824}
1825
Harald Weltea72273e2009-12-20 16:51:09 +01001826/* tell BTS to connect RTP stream to our local RTP socket */
1827int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1828{
1829 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1830 int rc;
1831
1832 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1833 ntohs(rs->rtp.sin_local.sin_port),
1834 /* FIXME: use RTP payload of bound socket, not BTS*/
1835 lchan->abis_ip.rtp_payload2);
1836
1837 return rc;
1838}
1839
Harald Welte53cd7ac2010-12-23 12:59:52 +01001840int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welte9c880c92009-10-24 10:29:22 +02001841{
1842 struct msgb *msg = rsl_msgb_alloc();
1843 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001844 uint8_t msg_type;
Harald Welte4563eab2010-03-28 14:42:09 +08001845
1846 if (act)
1847 msg_type = RSL_MT_IPAC_PDCH_ACT;
1848 else
1849 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welte9c880c92009-10-24 10:29:22 +02001850
1851 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte4563eab2010-03-28 14:42:09 +08001852 init_dchan_hdr(dh, msg_type);
Harald Welte9c880c92009-10-24 10:29:22 +02001853 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +02001854 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welte9c880c92009-10-24 10:29:22 +02001855
Harald Welte53cd7ac2010-12-23 12:59:52 +01001856 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte4563eab2010-03-28 14:42:09 +08001857 act ? "" : "DE");
Harald Welte9c880c92009-10-24 10:29:22 +02001858
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001859 msg->dst = ts->trx->rsl_link;
Harald Welte9c880c92009-10-24 10:29:22 +02001860
1861 return abis_rsl_sendmsg(msg);
1862}
1863
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001864static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001865{
1866 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1867 struct tlv_parsed tv;
Harald Welte2c828992009-12-02 01:56:49 +05301868 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75099262009-02-16 21:12:08 +00001869
1870 /* the BTS has acknowledged a local bind, it now tells us the IP
1871 * address and port number to which it has bound the given logical
1872 * channel */
1873
1874 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1875 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1876 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02001877 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001878 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001879 return -EINVAL;
1880 }
Harald Welte17f5bf62009-12-20 15:42:44 +01001881
Harald Welte5e3d91b2009-12-19 16:42:06 +01001882 ipac_parse_rtp(lchan, &tv);
Harald Welte17f5bf62009-12-20 15:42:44 +01001883
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001884 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte167df882009-02-17 14:35:45 +00001885
Harald Welte75099262009-02-16 21:12:08 +00001886 return 0;
1887}
1888
Harald Welte5e3d91b2009-12-19 16:42:06 +01001889static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1890{
1891 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1892 struct tlv_parsed tv;
1893 struct gsm_lchan *lchan = msg->lchan;
1894
1895 /* the BTS has acknowledged a remote connect request and
1896 * it now tells us the IP address and port number to which it has
1897 * connected the given logical channel */
1898
1899 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1900 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001901 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001902
1903 return 0;
1904}
1905
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001906static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001907{
1908 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1909 struct tlv_parsed tv;
1910
1911 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00001912
Harald Welte8830e072009-07-28 17:58:09 +02001913 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001914 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001915 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001916
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001917 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welte888b1142009-07-28 18:02:05 +02001918
Harald Welte75099262009-02-16 21:12:08 +00001919 return 0;
1920}
1921
1922static int abis_rsl_rx_ipacc(struct msgb *msg)
1923{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001924 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte75099262009-02-16 21:12:08 +00001925 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Welte5b8ed432009-12-24 12:20:20 +01001926 char *ts_name;
Harald Welte75099262009-02-16 21:12:08 +00001927 int rc = 0;
1928
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001929 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001930 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte75099262009-02-16 21:12:08 +00001931
1932 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001933 case RSL_MT_IPAC_CRCX_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001934 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001935 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001936 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001937 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001938 /* somehow the BTS was unable to bind the lchan to its local
1939 * port?!? */
Harald Welte5b8ed432009-12-24 12:20:20 +01001940 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001941 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001942 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte75099262009-02-16 21:12:08 +00001943 /* the BTS tells us that a connect operation was successful */
Harald Welte5b8ed432009-12-24 12:20:20 +01001944 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001945 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001946 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001947 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001948 /* somehow the BTS was unable to connect the lchan to a remote
1949 * port */
Harald Welte5b8ed432009-12-24 12:20:20 +01001950 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001951 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001952 case RSL_MT_IPAC_DLCX_IND:
Harald Welte5b8ed432009-12-24 12:20:20 +01001953 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001954 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte75099262009-02-16 21:12:08 +00001955 break;
1956 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001957 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001958 rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001959 break;
1960 }
Harald Welte6dab0552009-05-01 17:21:37 +00001961 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001962
1963 return rc;
1964}
1965
1966
Harald Welte52b1f982008-12-23 20:25:15 +00001967/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001968int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001969{
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001970 struct abis_rsl_common_hdr *rslh;
Harald Welte8f5e2392009-02-03 12:57:37 +00001971 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001972
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001973 if (!msg) {
1974 DEBUGP(DRSL, "Empty RSL msg?..\n");
1975 return -1;
1976 }
1977
1978 if (msgb_l2len(msg) < sizeof(*rslh)) {
1979 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltef25b55e2012-05-31 20:22:34 +02001980 msgb_free(msg);
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001981 return -1;
1982 }
1983
1984 rslh = msgb_l2(msg);
1985
Harald Welte52b1f982008-12-23 20:25:15 +00001986 switch (rslh->msg_discr & 0xfe) {
1987 case ABIS_RSL_MDISC_RLL:
1988 rc = abis_rsl_rx_rll(msg);
1989 break;
1990 case ABIS_RSL_MDISC_DED_CHAN:
1991 rc = abis_rsl_rx_dchan(msg);
1992 break;
1993 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00001994 rc = abis_rsl_rx_cchan(msg);
1995 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001996 case ABIS_RSL_MDISC_TRX:
1997 rc = abis_rsl_rx_trx(msg);
1998 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001999 case ABIS_RSL_MDISC_LOC:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002000 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte8f5e2392009-02-03 12:57:37 +00002001 rslh->msg_discr);
2002 break;
Harald Welte75099262009-02-16 21:12:08 +00002003 case ABIS_RSL_MDISC_IPACCESS:
2004 rc = abis_rsl_rx_ipacc(msg);
2005 break;
Harald Welte52b1f982008-12-23 20:25:15 +00002006 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002007 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
2008 "0x%02x\n", rslh->msg_discr);
Harald Weltef25b55e2012-05-31 20:22:34 +02002009 rc = -EINVAL;
Harald Welte52b1f982008-12-23 20:25:15 +00002010 }
Harald Welte4f4a3902008-12-26 00:04:49 +00002011 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00002012 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00002013}
Holger Freyther3b72a892009-02-04 00:31:39 +00002014
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002015int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
2016 uint8_t cb_command, const uint8_t *data, int len)
2017{
2018 struct abis_rsl_dchan_hdr *dh;
2019 struct msgb *cb_cmd;
2020
2021 cb_cmd = rsl_msgb_alloc();
2022 if (!cb_cmd)
2023 return -1;
2024
2025 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2026 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2027 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2028
2029 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2030 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2031
2032 cb_cmd->trx = bts->c0;
2033
2034 return abis_rsl_sendmsg(cb_cmd);
2035}
Dieter Spaar16646022011-07-28 00:01:50 +02002036
2037int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2038{
2039 struct abis_rsl_common_hdr *ch;
2040 struct msgb *msg = rsl_msgb_alloc();
2041
2042 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2043 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2044 ch->msg_type = 0x40; /* Nokia SI Begin */
2045
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002046 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002047
2048 return abis_rsl_sendmsg(msg);
2049}
2050
2051int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2052{
2053 struct abis_rsl_common_hdr *ch;
2054 struct msgb *msg = rsl_msgb_alloc();
2055
2056 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2057 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2058 ch->msg_type = 0x41; /* Nokia SI End */
2059
2060 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2061
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002062 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002063
2064 return abis_rsl_sendmsg(msg);
2065}
2066
2067int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2068{
2069 struct abis_rsl_common_hdr *ch;
2070 struct msgb *msg = rsl_msgb_alloc();
2071
2072 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2073 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2074 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2075
2076 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2077 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2078
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002079 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002080
2081 return abis_rsl_sendmsg(msg);
2082}
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +01002083
2084/**
2085 * Release all allocated SAPIs starting from @param start and
2086 * release them with the given release mode. Once the release
2087 * confirmation arrives it will be attempted to release the
2088 * the RF channel.
2089 */
2090int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
2091 enum rsl_rel_mode release_mode)
2092{
2093 int no_sapi = 1;
2094 int sapi;
2095
2096 for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
2097 uint8_t link_id;
2098 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
2099 continue;
2100
2101 link_id = sapi;
2102 if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
2103 link_id |= 0x40;
2104 rsl_release_request(lchan, link_id, release_mode);
2105 no_sapi = 0;
2106 }
2107
2108 return no_sapi;
2109}