blob: 09f24f606deb0e5d5210413d23af82c90d95c558 [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));
Harald Welte (local)3e460312009-12-27 18:12:29 +0100938 if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200939 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Daniel Willmann7ddc3182011-08-11 04:47:11 +0200940 else
941 rsl_rf_chan_release(msg->lchan, 1);
942
Harald Welte (local)3e460312009-12-27 18:12:29 +0100943 } else
Holger Hans Peter Freyther74419492010-04-10 00:12:31 +0200944 rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200945
Harald Welte (local)91b603d2009-12-27 11:48:11 +0100946 LOGPC(DRSL, LOGL_ERROR, "\n");
947
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +0100948 send_lchan_signal(S_LCHAN_ACTIVATE_NACK, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +0100949
Harald Welte3073a9f2009-08-09 19:50:08 +0200950 lchan_free(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000951 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000952}
953
Harald Welte7f93cea2009-02-23 00:02:59 +0000954/* Chapter 8.4.4: Connection Failure Indication */
955static int rsl_rx_conn_fail(struct msgb *msg)
956{
957 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
958 struct tlv_parsed tp;
959
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100960 /* FIXME: print which channel */
Harald Welte (local)fc057502009-12-26 22:33:09 +0100961 LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +0100962 gsm_lchan_name(msg->lchan));
Harald Welte7f93cea2009-02-23 00:02:59 +0000963
964 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
965
Harald Welte8830e072009-07-28 17:58:09 +0200966 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +0100967 print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +0200968 TLVP_LEN(&tp, RSL_IE_CAUSE));
969
Harald Welte (local)fc057502009-12-26 22:33:09 +0100970 LOGPC(DRSL, LOGL_NOTICE, "\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000971 /* FIXME: only free it after channel release ACK */
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200972 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rf_fail);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +0800973 return rsl_rf_chan_release(msg->lchan, 1);
Harald Welte7f93cea2009-02-23 00:02:59 +0000974}
975
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100976static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru,
977 const char *prefix)
978{
Harald Welte6739dfb2009-12-16 16:52:07 +0100979 DEBUGPC(DMEAS, "RXL-FULL-%s=%3ddBm RXL-SUB-%s=%3ddBm ",
980 prefix, rxlev2dbm(mru->full.rx_lev),
981 prefix, rxlev2dbm(mru->sub.rx_lev));
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100982 DEBUGPC(DMEAS, "RXQ-FULL-%s=%d RXQ-SUB-%s=%d ",
983 prefix, mru->full.rx_qual, prefix, mru->sub.rx_qual);
984}
985
Harald Welte0c1bd612012-07-02 17:12:08 +0200986static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100987{
Harald Welte6739dfb2009-12-16 16:52:07 +0100988 int i;
Harald Welte0c1bd612012-07-02 17:12:08 +0200989 char *name = "";
Harald Welte6739dfb2009-12-16 16:52:07 +0100990
Harald Welte0c1bd612012-07-02 17:12:08 +0200991 if (lchan && lchan->conn && lchan->conn->subscr)
992 name = subscr_name(lchan->conn->subscr);
993
994 DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +0100995
996 if (mr->flags & MEAS_REP_F_DL_DTX)
997 DEBUGPC(DMEAS, "DTXd ");
998
999 print_meas_rep_uni(&mr->ul, "ul");
1000 DEBUGPC(DMEAS, "BS_POWER=%d ", mr->bs_power);
1001 if (mr->flags & MEAS_REP_F_MS_TO)
1002 DEBUGPC(DMEAS, "MS_TO=%d ", mr->ms_timing_offset);
1003
1004 if (mr->flags & MEAS_REP_F_MS_L1) {
Harald Welte6739dfb2009-12-16 16:52:07 +01001005 DEBUGPC(DMEAS, "L1_MS_PWR=%3ddBm ", mr->ms_l1.pwr);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001006 DEBUGPC(DMEAS, "L1_FPC=%u ",
1007 mr->flags & MEAS_REP_F_FPC ? 1 : 0);
1008 DEBUGPC(DMEAS, "L1_TA=%u ", mr->ms_l1.ta);
1009 }
1010
1011 if (mr->flags & MEAS_REP_F_UL_DTX)
1012 DEBUGPC(DMEAS, "DTXu ");
1013 if (mr->flags & MEAS_REP_F_BA1)
1014 DEBUGPC(DMEAS, "BA1 ");
1015 if (!(mr->flags & MEAS_REP_F_DL_VALID))
1016 DEBUGPC(DMEAS, "NOT VALID ");
1017 else
1018 print_meas_rep_uni(&mr->dl, "dl");
1019
1020 DEBUGPC(DMEAS, "NUM_NEIGH=%u\n", mr->num_cell);
Harald Welte479015b2009-12-19 18:33:05 +01001021 if (mr->num_cell == 7)
1022 return;
Harald Welte6739dfb2009-12-16 16:52:07 +01001023 for (i = 0; i < mr->num_cell; i++) {
1024 struct gsm_meas_rep_cell *mrc = &mr->cell[i];
Harald Welte303e5e02009-12-25 23:02:22 +01001025 DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
1026 mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
Harald Welte6739dfb2009-12-16 16:52:07 +01001027 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001028}
1029
Harald Welte440fed02009-05-01 18:43:47 +00001030static int rsl_rx_meas_res(struct msgb *msg)
1031{
1032 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1033 struct tlv_parsed tp;
Harald Welted12b0fd2009-12-15 21:36:05 +01001034 struct gsm_meas_rep *mr = lchan_next_meas_rep(msg->lchan);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001035 uint8_t len;
1036 const uint8_t *val;
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001037 int rc;
Harald Welte440fed02009-05-01 18:43:47 +00001038
Harald Welteb8bfc562009-12-21 13:27:11 +01001039 /* check if this channel is actually active */
1040 /* FIXME: maybe this check should be way more generic/centralized */
Harald Welte8e93b792009-12-29 10:44:17 +01001041 if (msg->lchan->state != LCHAN_S_ACTIVE) {
Holger Hans Peter Freytherc44db4a2010-07-29 14:50:57 +08001042 LOGP(DRSL, LOGL_DEBUG, "%s: MEAS RES for inactive channel\n",
Harald Welte8e93b792009-12-29 10:44:17 +01001043 gsm_lchan_name(msg->lchan));
Harald Welteb8bfc562009-12-21 13:27:11 +01001044 return 0;
Harald Welte8e93b792009-12-29 10:44:17 +01001045 }
Harald Welteb8bfc562009-12-21 13:27:11 +01001046
Harald Welted12b0fd2009-12-15 21:36:05 +01001047 memset(mr, 0, sizeof(*mr));
Harald Welte33e65972009-12-16 23:29:34 +01001048 mr->lchan = msg->lchan;
Harald Weltedbb1d882009-11-30 19:16:47 +01001049
Harald Welte440fed02009-05-01 18:43:47 +00001050 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1051
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001052 if (!TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR) ||
1053 !TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS) ||
1054 !TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
1055 return -EIO;
1056
1057 /* Mandatory Parts */
Harald Welted12b0fd2009-12-15 21:36:05 +01001058 mr->nr = *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001059
1060 len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
1061 val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
1062 if (len >= 3) {
1063 if (val[0] & 0x40)
Harald Welted12b0fd2009-12-15 21:36:05 +01001064 mr->flags |= MEAS_REP_F_DL_DTX;
1065 mr->ul.full.rx_lev = val[0] & 0x3f;
1066 mr->ul.sub.rx_lev = val[1] & 0x3f;
1067 mr->ul.full.rx_qual = val[2]>>3 & 0x7;
1068 mr->ul.sub.rx_qual = val[2] & 0x7;
Harald Welte440fed02009-05-01 18:43:47 +00001069 }
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001070
Harald Welted12b0fd2009-12-15 21:36:05 +01001071 mr->bs_power = *TLVP_VAL(&tp, RSL_IE_BS_POWER);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001072
1073 /* Optional Parts */
Harald Welte440fed02009-05-01 18:43:47 +00001074 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welted12b0fd2009-12-15 21:36:05 +01001075 mr->ms_timing_offset =
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001076 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET);
1077
Harald Weltefe9af262009-06-20 18:44:35 +02001078 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001079 struct e1inp_sign_link *sign_link = msg->dst;
1080
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001081 val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001082 mr->flags |= MEAS_REP_F_MS_L1;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001083 mr->ms_l1.pwr = ms_pwr_dbm(sign_link->trx->bts->band, val[0] >> 3);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001084 if (val[0] & 0x04)
Harald Welted12b0fd2009-12-15 21:36:05 +01001085 mr->flags |= MEAS_REP_F_FPC;
1086 mr->ms_l1.ta = val[1];
Andreas Eversberg3365cd12011-12-24 11:49:05 +01001087 /* BS11 and Nokia reports TA shifted by 2 bits */
1088 if (msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11
1089 || msg->lchan->ts->trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE)
Andreas Eversberg2957de92011-12-16 17:45:37 +01001090 mr->ms_l1.ta >>= 2;
Harald Weltefe9af262009-06-20 18:44:35 +02001091 }
Harald Weltef7c43522009-06-09 20:24:21 +00001092 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001093 msg->l3h = (uint8_t *) TLVP_VAL(&tp, RSL_IE_L3_INFO);
Harald Welted12b0fd2009-12-15 21:36:05 +01001094 rc = gsm48_parse_meas_rep(mr, msg);
Harald Welte3c7dc6e2009-11-29 19:07:28 +01001095 if (rc < 0)
1096 return rc;
1097 }
1098
Harald Welte0c1bd612012-07-02 17:12:08 +02001099 print_meas_rep(msg->lchan, mr);
Harald Welte60d68f12009-06-05 20:07:43 +00001100
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001101 send_lchan_signal(S_LCHAN_MEAS_REP, msg->lchan, mr);
Harald Weltedbb1d882009-11-30 19:16:47 +01001102
Harald Welte75d34a82009-05-23 06:11:13 +00001103 return 0;
Harald Welte440fed02009-05-01 18:43:47 +00001104}
1105
Harald Welted011e8b2009-11-29 22:45:52 +01001106/* Chapter 8.4.7 */
1107static int rsl_rx_hando_det(struct msgb *msg)
1108{
1109 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1110 struct tlv_parsed tp;
1111
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001112 DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
Harald Welted011e8b2009-11-29 22:45:52 +01001113
1114 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
1115
1116 if (TLVP_PRESENT(&tp, RSL_IE_ACCESS_DELAY))
1117 DEBUGPC(DRSL, "access delay = %u\n",
1118 *TLVP_VAL(&tp, RSL_IE_ACCESS_DELAY));
1119 else
1120 DEBUGPC(DRSL, "\n");
1121
Holger Hans Peter Freyther08eebd52010-12-27 13:28:20 +01001122 send_lchan_signal(S_LCHAN_HANDOVER_DETECT, msg->lchan, NULL);
Harald Welted011e8b2009-11-29 22:45:52 +01001123
1124 return 0;
1125}
1126
Harald Welte52b1f982008-12-23 20:25:15 +00001127static int abis_rsl_rx_dchan(struct msgb *msg)
1128{
Harald Welte8470bf22008-12-25 23:28:35 +00001129 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1130 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +00001131 char *ts_name;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001132 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001133
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001134 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001135 ts_name = gsm_lchan_name(msg->lchan);
Harald Weltef325eb42009-02-19 17:07:39 +00001136
Harald Welte8470bf22008-12-25 23:28:35 +00001137 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001138 case RSL_MT_CHAN_ACTIV_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001139 DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
Harald Welte4b634542008-12-27 01:55:51 +00001140 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001141 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001142 case RSL_MT_CHAN_ACTIV_NACK:
Harald Welte4b634542008-12-27 01:55:51 +00001143 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001144 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001145 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +00001146 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001147 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001148 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +00001149 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +00001150 break;
Harald Welted011e8b2009-11-29 22:45:52 +01001151 case RSL_MT_HANDO_DET:
1152 rc = rsl_rx_hando_det(msg);
1153 break;
Harald Welte2d5b6382008-12-27 19:46:06 +00001154 case RSL_MT_RF_CHAN_REL_ACK:
Harald Welte64bb7542011-01-14 14:16:16 +01001155 rc = rsl_rx_rf_chan_rel_ack(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +00001156 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001157 case RSL_MT_MODE_MODIFY_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001158 DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001159 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001160 case RSL_MT_MODE_MODIFY_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001161 LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
Harald Welteda783762009-02-18 03:29:53 +00001162 break;
Harald Welte9c880c92009-10-24 10:29:22 +02001163 case RSL_MT_IPAC_PDCH_ACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001164 DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001165 msg->lchan->ts->flags |= TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001166 break;
1167 case RSL_MT_IPAC_PDCH_ACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001168 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001169 break;
1170 case RSL_MT_IPAC_PDCH_DEACT_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001171 DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
Harald Welte4563eab2010-03-28 14:42:09 +08001172 msg->lchan->ts->flags &= ~TS_F_PDCH_MODE;
Harald Welte9c880c92009-10-24 10:29:22 +02001173 break;
1174 case RSL_MT_IPAC_PDCH_DEACT_NACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001175 LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
Harald Welte9c880c92009-10-24 10:29:22 +02001176 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001177 case RSL_MT_PHY_CONTEXT_CONF:
1178 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +00001179 case RSL_MT_TALKER_DET:
1180 case RSL_MT_LISTENER_DET:
1181 case RSL_MT_REMOTE_CODEC_CONF_REP:
1182 case RSL_MT_MR_CODEC_MOD_ACK:
1183 case RSL_MT_MR_CODEC_MOD_NACK:
1184 case RSL_MT_MR_CODEC_MOD_PER:
Harald Welte5b8ed432009-12-24 12:20:20 +01001185 LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
1186 "msg 0x%02x\n", ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001187 break;
1188 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001189 LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
1190 ts_name, rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001191 return -EINVAL;
1192 }
Harald Weltef325eb42009-02-19 17:07:39 +00001193
Harald Welte8470bf22008-12-25 23:28:35 +00001194 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001195}
1196
Harald Welte702d8702008-12-26 20:25:35 +00001197static int rsl_rx_error_rep(struct msgb *msg)
1198{
1199 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +02001200 struct tlv_parsed tp;
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001201 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte702d8702008-12-26 20:25:35 +00001202
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001203 LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(sign_link->trx));
Harald Welte8830e072009-07-28 17:58:09 +02001204
1205 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1206
1207 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001208 print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001209 TLVP_LEN(&tp, RSL_IE_CAUSE));
1210
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001211 LOGPC(DRSL, LOGL_ERROR, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001212
1213 return 0;
1214}
1215
Harald Welte52b1f982008-12-23 20:25:15 +00001216static int abis_rsl_rx_trx(struct msgb *msg)
1217{
Harald Welte702d8702008-12-26 20:25:35 +00001218 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001219 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte8470bf22008-12-25 23:28:35 +00001220 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001221
1222 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001223 case RSL_MT_ERROR_REPORT:
1224 rc = rsl_rx_error_rep(msg);
1225 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001226 case RSL_MT_RF_RES_IND:
1227 /* interference on idle channels of TRX */
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001228 //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(sign_link->trx));
Harald Welte8f5e2392009-02-03 12:57:37 +00001229 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001230 case RSL_MT_OVERLOAD:
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001231 /* indicate CCCH / ACCH / processor overload */
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001232 LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001233 gsm_trx_name(sign_link->trx));
Harald Welte52b1f982008-12-23 20:25:15 +00001234 break;
Dieter Spaar16646022011-07-28 00:01:50 +02001235 case 0x42: /* Nokia specific: SI End ACK */
1236 LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
1237 break;
1238 case 0x43: /* Nokia specific: SI End NACK */
1239 LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
1240 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001241 default:
Harald Welte (local)d48f4eb2009-12-28 23:14:22 +01001242 LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001243 "type 0x%02x\n", gsm_trx_name(sign_link->trx), rslh->msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001244 return -EINVAL;
1245 }
Harald Welte8470bf22008-12-25 23:28:35 +00001246 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001247}
1248
Harald Welteb7e81162009-08-10 00:26:10 +02001249/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1250static void t3101_expired(void *data)
1251{
1252 struct gsm_lchan *lchan = data;
1253
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001254 rsl_rf_chan_release(lchan, 1);
Harald Welteb7e81162009-08-10 00:26:10 +02001255}
1256
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001257/* If T3111 expires, we will send the RF Channel Request */
1258static void t3111_expired(void *data)
1259{
1260 struct gsm_lchan *lchan = data;
1261
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001262 rsl_rf_chan_release(lchan, 0);
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001263}
1264
laforgecfa4a012010-06-21 12:08:52 +02001265#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
1266
Harald Welte2862dca2010-12-23 14:39:29 +01001267/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
1268static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
1269 unsigned int num_req_refs,
1270 struct gsm48_req_ref *rqd_refs,
1271 uint8_t wait_ind)
1272{
1273 uint8_t buf[GSM_MACBLOCK_LEN];
1274 struct gsm48_imm_ass_rej *iar = (struct gsm48_imm_ass_rej *)buf;
1275
1276 /* create IMMEDIATE ASSIGN REJECT 04.08 message */
1277 memset(iar, 0, sizeof(*iar));
1278 iar->proto_discr = GSM48_PDISC_RR;
1279 iar->msg_type = GSM48_MT_RR_IMM_ASS;
1280 iar->page_mode = GSM48_PM_SAME;
1281
1282 memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
1283 iar->wait_ind1 = wait_ind;
1284
1285 if (num_req_refs >= 2)
1286 memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
1287 else
1288 memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
1289 iar->wait_ind2 = wait_ind;
1290
1291 if (num_req_refs >= 3)
1292 memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
1293 else
1294 memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
1295 iar->wait_ind3 = wait_ind;
1296
1297 if (num_req_refs >= 4)
1298 memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
1299 else
1300 memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
1301 iar->wait_ind4 = wait_ind;
1302
1303 return rsl_imm_assign_cmd(bts, sizeof(iar), (uint8_t *) iar);
1304}
1305
Harald Welte8470bf22008-12-25 23:28:35 +00001306/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001307static int rsl_rx_chan_rqd(struct msgb *msg)
1308{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001309 struct e1inp_sign_link *sign_link = msg->dst;
1310 struct gsm_bts *bts = sign_link->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001311 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1312 struct gsm48_req_ref *rqd_ref;
Harald Welte8470bf22008-12-25 23:28:35 +00001313 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001314 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001315 struct gsm_lchan *lchan;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001316 uint8_t rqd_ta;
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001317 int is_lu;
Harald Welte8470bf22008-12-25 23:28:35 +00001318
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001319 uint16_t arfcn;
Holger Hans Peter Freytherc6d0a172012-02-03 20:10:13 +01001320 uint8_t subch;
Harald Welte52b1f982008-12-23 20:25:15 +00001321
Harald Welte8470bf22008-12-25 23:28:35 +00001322 /* parse request reference to be used in immediate assign */
1323 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1324 return -EINVAL;
1325
1326 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1327
1328 /* parse access delay and use as TA */
1329 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1330 return -EINVAL;
1331 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1332
1333 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1334 * request reference RA */
Holger Hans Peter Freyther78891072010-09-06 09:36:02 +08001335 lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
1336 chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
Harald Welte2cbe0922008-12-29 04:09:31 +00001337
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001338 osmo_counter_inc(bts->network->stats.chreq.total);
Harald Welte24ff6ee2009-12-22 00:41:05 +01001339
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001340 /*
1341 * We want LOCATION UPDATES to succeed and will assign a TCH
1342 * if we have no SDCCH available.
1343 */
1344 is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
1345
Harald Welte8470bf22008-12-25 23:28:35 +00001346 /* check availability / allocate channel */
Holger Hans Peter Freyther457c2a82010-09-06 08:58:42 +08001347 lchan = lchan_alloc(bts, lctype, is_lu);
Harald Welte8470bf22008-12-25 23:28:35 +00001348 if (!lchan) {
Harald Welte (local)2f5df852009-12-27 13:48:09 +01001349 LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
Harald Welte (local)ccd88452009-12-27 18:05:25 +01001350 msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001351 osmo_counter_inc(bts->network->stats.chreq.no_channel);
Harald Welte2862dca2010-12-23 14:39:29 +01001352 /* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
1353 if (bts->network->T3122)
1354 rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
Harald Welte8470bf22008-12-25 23:28:35 +00001355 return -ENOMEM;
1356 }
1357
Harald Welte8e93b792009-12-29 10:44:17 +01001358 if (lchan->state != LCHAN_S_NONE)
1359 LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
Harald Welte1887f9d2009-12-29 10:52:38 +01001360 "in state %s\n", gsm_lchan_name(lchan),
1361 gsm_lchans_name(lchan->state));
Harald Welte (local)3e460312009-12-27 18:12:29 +01001362
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001363 /* save the RACH data as we need it after the CHAN ACT ACK */
1364 lchan->rqd_ref = talloc_zero(bts, struct gsm48_req_ref);
1365 if (!lchan->rqd_ref) {
1366 LOGP(DRSL, LOGL_ERROR, "Failed to allocate gsm48_req_ref.\n");
1367 lchan_free(lchan);
1368 return -ENOMEM;
1369 }
1370
Holger Hans Peter Freytherc0a66742011-12-29 23:33:04 +01001371 rsl_lchan_set_state(lchan, LCHAN_S_ACT_REQ);
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001372 memcpy(lchan->rqd_ref, rqd_ref, sizeof(*rqd_ref));
1373 lchan->rqd_ta = rqd_ta;
1374
Harald Welte8470bf22008-12-25 23:28:35 +00001375 arfcn = lchan->ts->trx->arfcn;
1376 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001377
Harald Welte08d91a52009-08-30 15:37:11 +09001378 lchan->encr.alg_id = RSL_ENC_ALG_A5(0); /* no encryption */
Harald Welte (local)0e451d02009-08-13 10:14:26 +02001379 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
Harald Welte0b2124b2009-08-10 00:45:40 +02001380 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte9943c5b2009-07-29 15:41:29 +02001381 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
Harald Welte196d0522009-08-28 23:28:28 +09001382 lchan->tch_mode = GSM48_CMODE_SIGN;
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001383
Harald Weltee8bd9e82011-08-10 23:26:33 +02001384 /* Start another timer or assume the BTS sends a ACK/NACK? */
1385 lchan->act_timer.cb = lchan_act_tmr_cb;
1386 lchan->act_timer.data = lchan;
1387 osmo_timer_schedule(&lchan->act_timer, 4, 0);
1388
Andreas Eversberg2957de92011-12-16 17:45:37 +01001389 DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
1390 "r=%s ra=0x%02x ta=%d\n", gsm_lchan_name(lchan), arfcn, subch,
1391 gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
1392 rqd_ref->ra, rqd_ta);
1393
1394 /* BS11 requires TA shifted by 2 bits */
1395 if (bts->type == GSM_BTS_TYPE_BS11)
1396 rqd_ta <<= 2;
Harald Welte8d77b952009-12-17 00:31:10 +01001397 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
Harald Welte52b1f982008-12-23 20:25:15 +00001398
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001399 return 0;
1400}
1401
1402static int rsl_send_imm_assignment(struct gsm_lchan *lchan)
1403{
1404 struct gsm_bts *bts = lchan->ts->trx->bts;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001405 uint8_t buf[GSM_MACBLOCK_LEN];
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001406 struct gsm48_imm_ass *ia = (struct gsm48_imm_ass *) buf;
1407
Harald Welte52b1f982008-12-23 20:25:15 +00001408 /* create IMMEDIATE ASSIGN 04.08 messge */
laforge09108bf2010-06-20 15:18:46 +02001409 memset(ia, 0, sizeof(*ia));
laforgecfa4a012010-06-21 12:08:52 +02001410 /* we set ia->l2_plen once we know the length of the MA below */
laforge09108bf2010-06-20 15:18:46 +02001411 ia->proto_discr = GSM48_PDISC_RR;
1412 ia->msg_type = GSM48_MT_RR_IMM_ASS;
1413 ia->page_mode = GSM48_PM_SAME;
1414 gsm48_lchan2chan_desc(&ia->chan_desc, lchan);
Harald Weltea39b0f22010-06-14 22:26:10 +02001415
Harald Welte8470bf22008-12-25 23:28:35 +00001416 /* use request reference extracted from CHAN_RQD */
Holger Hans Peter Freyther5ba05f42010-06-22 12:11:59 +08001417 memcpy(&ia->req_ref, lchan->rqd_ref, sizeof(ia->req_ref));
1418 ia->timing_advance = lchan->rqd_ta;
Harald Weltea39b0f22010-06-14 22:26:10 +02001419 if (!lchan->ts->hopping.enabled) {
laforge09108bf2010-06-20 15:18:46 +02001420 ia->mob_alloc_len = 0;
Harald Weltea39b0f22010-06-14 22:26:10 +02001421 } else {
laforge09108bf2010-06-20 15:18:46 +02001422 ia->mob_alloc_len = lchan->ts->hopping.ma_len;
1423 memcpy(ia->mob_alloc, lchan->ts->hopping.ma_data, ia->mob_alloc_len);
Harald Weltea39b0f22010-06-14 22:26:10 +02001424 }
Harald Weltea1d39a22010-06-28 18:41:27 +02001425 /* we need to subtract 1 byte from sizeof(*ia) since ia includes the l2_plen field */
1426 ia->l2_plen = GSM48_LEN2PLEN((sizeof(*ia)-1) + ia->mob_alloc_len);
Harald Welte52b1f982008-12-23 20:25:15 +00001427
Harald Welteb7e81162009-08-10 00:26:10 +02001428 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1429 lchan->T3101.cb = t3101_expired;
1430 lchan->T3101.data = lchan;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001431 osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0);
Holger Freyther3186bf22008-12-29 06:23:49 +00001432
Harald Welte52b1f982008-12-23 20:25:15 +00001433 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001434 return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia);
Harald Welte52b1f982008-12-23 20:25:15 +00001435}
1436
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001437/* current load on the CCCH */
Harald Welteea280442009-02-02 22:29:56 +00001438static int rsl_rx_ccch_load(struct msgb *msg)
1439{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001440 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001441 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001442 struct ccch_signal_data sd;
1443
1444 sd.bts = sign_link->trx->bts;
1445 sd.rach_slot_count = -1;
1446 sd.rach_busy_count = -1;
1447 sd.rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001448
1449 switch (rslh->data[0]) {
1450 case RSL_IE_PAGING_LOAD:
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001451 sd.pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
1452 if (is_ipaccess_bts(sign_link->trx->bts) && sd.pg_buf_space == 0xffff) {
Harald Welte38e9c822010-04-19 10:24:07 +02001453 /* paging load below configured threshold, use 50 as default */
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001454 sd.pg_buf_space = 50;
Harald Welte38e9c822010-04-19 10:24:07 +02001455 }
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001456 paging_update_buffer_space(sign_link->trx->bts, sd.pg_buf_space);
1457 osmo_signal_dispatch(SS_CCCH, S_CCCH_PAGING_LOAD, &sd);
Harald Welteea280442009-02-02 22:29:56 +00001458 break;
1459 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001460 if (msg->data_len >= 7) {
Holger Hans Peter Freyther54fa2c72012-02-03 20:26:25 +01001461 sd.rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1462 sd.rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1463 sd.rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1464 osmo_signal_dispatch(SS_CCCH, S_CCCH_RACH_LOAD, &sd);
Holger Freyther8c563cf2009-02-03 20:08:51 +00001465 }
Harald Welteea280442009-02-02 22:29:56 +00001466 break;
1467 default:
1468 break;
1469 }
1470
1471 return 0;
1472}
1473
Harald Welte52b1f982008-12-23 20:25:15 +00001474static int abis_rsl_rx_cchan(struct msgb *msg)
1475{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001476 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welteea280442009-02-02 22:29:56 +00001477 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001478 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001479
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001480 msg->lchan = lchan_lookup(sign_link->trx, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +00001481
1482 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001483 case RSL_MT_CHAN_RQD:
1484 /* MS has requested a channel on the RACH */
1485 rc = rsl_rx_chan_rqd(msg);
1486 break;
Harald Welteea280442009-02-02 22:29:56 +00001487 case RSL_MT_CCCH_LOAD_IND:
1488 /* current load on the CCCH */
1489 rc = rsl_rx_ccch_load(msg);
1490 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001491 case RSL_MT_DELETE_IND:
1492 /* CCCH overloaded, IMM_ASSIGN was dropped */
1493 case RSL_MT_CBCH_LOAD_IND:
1494 /* current load on the CBCH */
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001495 LOGP(DRSL, LOGL_NOTICE, "Unimplemented Abis RSL TRX message "
1496 "type 0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001497 break;
1498 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001499 LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message type "
1500 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001501 return -EINVAL;
1502 }
Harald Welte8470bf22008-12-25 23:28:35 +00001503
1504 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001505}
1506
Harald Welte4b634542008-12-27 01:55:51 +00001507static int rsl_rx_rll_err_ind(struct msgb *msg)
1508{
1509 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001510 uint8_t *rlm_cause = rllh->data;
Harald Welte4b634542008-12-27 01:55:51 +00001511
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001512 LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001513 gsm_lchan_name(msg->lchan),
Harald Weltee95daf12010-03-25 12:13:02 +08001514 rsl_rlm_cause_name(rlm_cause[1]));
Harald Welteedcc5272009-08-09 13:47:35 +02001515
1516 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte (local)9538efc2009-12-26 23:55:00 +01001517
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001518 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) {
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +02001519 osmo_counter_inc(msg->lchan->ts->trx->bts->network->stats.chan.rll_err);
Holger Hans Peter Freyther4b4dd102010-05-31 21:38:24 +08001520 return rsl_rf_chan_release(msg->lchan, 1);
Holger Hans Peter Freyther3ba36d52010-04-17 06:48:29 +02001521 }
Harald Welte81543bc2009-07-04 09:40:05 +02001522
Harald Welte4b634542008-12-27 01:55:51 +00001523 return 0;
1524}
Harald Weltef325eb42009-02-19 17:07:39 +00001525
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001526static void rsl_handle_release(struct gsm_lchan *lchan)
1527{
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001528 int sapi;
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001529 struct gsm_bts *bts;
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001530
Holger Hans Peter Freyther9d50a272011-12-28 12:11:40 +01001531 /*
1532 * Maybe only one link/SAPI was releasd or the error handling
1533 * was activated. Just return now and let the other code handle
1534 * it.
1535 */
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001536 if (lchan->state != LCHAN_S_REL_REQ)
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001537 return;
1538
1539 for (sapi = 0; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
1540 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
1541 continue;
Harald Welte3a3c2772010-12-24 12:51:07 +01001542 LOGP(DRSL, LOGL_DEBUG, "%s waiting for SAPI=%d to be released.\n",
Holger Hans Peter Freyther4b85a322010-07-29 17:09:36 +08001543 gsm_lchan_name(lchan), sapi);
1544 return;
1545 }
1546
Holger Hans Peter Freytherd7fd3062010-04-08 22:47:44 +02001547
1548
Holger Hans Peter Freytherf30c0dc2010-05-31 21:33:15 +08001549 /* wait a bit to send the RF Channel Release */
1550 lchan->T3111.cb = t3111_expired;
1551 lchan->T3111.data = lchan;
1552 bts = lchan->ts->trx->bts;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001553 osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001554}
1555
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001556/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
Harald Welte52b1f982008-12-23 20:25:15 +00001557 0x02, 0x06,
1558 0x01, 0x20,
1559 0x02, 0x00,
1560 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1561
1562static int abis_rsl_rx_rll(struct msgb *msg)
1563{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001564 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte52b1f982008-12-23 20:25:15 +00001565 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001566 int rc = 0;
1567 char *ts_name;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001568 uint8_t sapi = rllh->link_id & 7;
Harald Welte8470bf22008-12-25 23:28:35 +00001569
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001570 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001571 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte5b8ed432009-12-24 12:20:20 +01001572 DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
Harald Welte52b1f982008-12-23 20:25:15 +00001573
1574 switch (rllh->c.msg_type) {
1575 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001576 DEBUGPC(DRLL, "DATA INDICATION\n");
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001577 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001578 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1579 rllh->data[0] == RSL_IE_L3_INFO) {
1580 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001581 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001582 }
Harald Welte52b1f982008-12-23 20:25:15 +00001583 break;
1584 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001585 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welteb7e81162009-08-10 00:26:10 +02001586 /* lchan is established, stop T3101 */
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001587 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS;
Pablo Neira Ayusobf540cb2011-05-06 12:11:06 +02001588 osmo_timer_del(&msg->lchan->T3101);
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +02001589 if (msgb_l2len(msg) >
Harald Welte4a543e82009-02-28 13:17:55 +00001590 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1591 rllh->data[0] == RSL_IE_L3_INFO) {
1592 msg->l3h = &rllh->data[3];
Harald Welte (local)daef6062009-08-14 11:41:12 +02001593 return gsm0408_rcvmsg(msg, rllh->link_id);
Harald Welte4a543e82009-02-28 13:17:55 +00001594 }
Harald Welte52b1f982008-12-23 20:25:15 +00001595 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001596 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001597 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001598 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_NET;
Harald Welteedcc5272009-08-09 13:47:35 +02001599 rll_indication(msg->lchan, rllh->link_id,
1600 BSC_RLLR_IND_EST_CONF);
1601 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001602 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001603 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001604 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001605 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Harald Welteedcc5272009-08-09 13:47:35 +02001606 rll_indication(msg->lchan, rllh->link_id,
1607 BSC_RLLR_IND_REL_IND);
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001608 rsl_handle_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001609 break;
1610 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001611 /* BTS informs us of having received UA from MS,
1612 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001613 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Holger Hans Peter Freyther5ba6f482009-10-28 14:23:39 +01001614 msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_UNUSED;
Holger Hans Peter Freytherdbc5fae2010-04-08 22:39:34 +02001615 rsl_handle_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001616 break;
1617 case RSL_MT_ERROR_IND:
1618 rc = rsl_rx_rll_err_ind(msg);
1619 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001620 case RSL_MT_UNIT_DATA_IND:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001621 LOGP(DRLL, LOGL_NOTICE, "unimplemented Abis RLL message "
1622 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001623 break;
1624 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001625 LOGP(DRLL, LOGL_NOTICE, "unknown Abis RLL message "
1626 "type 0x%02x\n", rllh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001627 }
Harald Welte8470bf22008-12-25 23:28:35 +00001628 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001629}
1630
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001631static uint8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
Harald Weltef4e79f22009-07-28 18:11:56 +02001632{
Harald Welte0603c9d2009-12-02 01:58:23 +05301633 switch (lchan->tch_mode) {
Harald Weltef4e79f22009-07-28 18:11:56 +02001634 case GSM48_CMODE_SPEECH_V1:
Harald Welte0603c9d2009-12-02 01:58:23 +05301635 switch (lchan->type) {
1636 case GSM_LCHAN_TCH_F:
1637 return 0x00;
1638 case GSM_LCHAN_TCH_H:
1639 return 0x03;
1640 default:
1641 break;
1642 }
Harald Weltef4e79f22009-07-28 18:11:56 +02001643 case GSM48_CMODE_SPEECH_EFR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301644 switch (lchan->type) {
1645 case GSM_LCHAN_TCH_F:
1646 return 0x01;
1647 /* there's no half-rate EFR */
1648 default:
1649 break;
1650 }
Harald Weltef4e79f22009-07-28 18:11:56 +02001651 case GSM48_CMODE_SPEECH_AMR:
Harald Welte0603c9d2009-12-02 01:58:23 +05301652 switch (lchan->type) {
1653 case GSM_LCHAN_TCH_F:
1654 return 0x02;
1655 case GSM_LCHAN_TCH_H:
1656 return 0x05;
1657 default:
1658 break;
1659 }
1660 default:
1661 break;
Harald Weltef4e79f22009-07-28 18:11:56 +02001662 }
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001663 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access speech mode for "
Harald Welte0603c9d2009-12-02 01:58:23 +05301664 "tch_mode == 0x%02x\n", lchan->tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001665 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001666}
1667
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001668static uint8_t ipa_rtp_pt_for_lchan(struct gsm_lchan *lchan)
Sylvain Munautb54dda42009-12-20 22:06:40 +01001669{
1670 switch (lchan->tch_mode) {
1671 case GSM48_CMODE_SPEECH_V1:
1672 switch (lchan->type) {
1673 case GSM_LCHAN_TCH_F:
1674 return RTP_PT_GSM_FULL;
1675 case GSM_LCHAN_TCH_H:
1676 return RTP_PT_GSM_HALF;
1677 default:
1678 break;
1679 }
1680 case GSM48_CMODE_SPEECH_EFR:
1681 switch (lchan->type) {
1682 case GSM_LCHAN_TCH_F:
1683 return RTP_PT_GSM_EFR;
1684 /* there's no half-rate EFR */
1685 default:
1686 break;
1687 }
1688 case GSM48_CMODE_SPEECH_AMR:
1689 switch (lchan->type) {
1690 case GSM_LCHAN_TCH_F:
Sylvain Munautb54dda42009-12-20 22:06:40 +01001691 case GSM_LCHAN_TCH_H:
Holger Hans Peter Freythered999b22011-07-21 10:24:46 +02001692 return RTP_PT_AMR;
Sylvain Munautb54dda42009-12-20 22:06:40 +01001693 default:
1694 break;
1695 }
1696 default:
1697 break;
1698 }
1699 LOGP(DRSL, LOGL_ERROR, "Cannot determine ip.access rtp payload type for "
1700 "tch_mode == 0x%02x\n & lchan_type == %d",
1701 lchan->tch_mode, lchan->type);
1702 return 0;
1703}
1704
Harald Welte75099262009-02-16 21:12:08 +00001705/* ip.access specific RSL extensions */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001706static void ipac_parse_rtp(struct gsm_lchan *lchan, struct tlv_parsed *tv)
1707{
1708 struct in_addr ip;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001709 uint16_t port, conn_id;
Harald Welte5e3d91b2009-12-19 16:42:06 +01001710
1711 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_IP)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001712 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001713 DEBUGPC(DRSL, "LOCAL_IP=%s ", inet_ntoa(ip));
1714 lchan->abis_ip.bound_ip = ntohl(ip.s_addr);
1715 }
1716
1717 if (TLVP_PRESENT(tv, RSL_IE_IPAC_LOCAL_PORT)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001718 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_LOCAL_PORT));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001719 port = ntohs(port);
1720 DEBUGPC(DRSL, "LOCAL_PORT=%u ", port);
1721 lchan->abis_ip.bound_port = port;
1722 }
1723
1724 if (TLVP_PRESENT(tv, RSL_IE_IPAC_CONN_ID)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001725 conn_id = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_CONN_ID));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001726 conn_id = ntohs(conn_id);
1727 DEBUGPC(DRSL, "CON_ID=%u ", conn_id);
1728 lchan->abis_ip.conn_id = conn_id;
1729 }
1730
1731 if (TLVP_PRESENT(tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1732 lchan->abis_ip.rtp_payload2 =
1733 *TLVP_VAL(tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1734 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1735 lchan->abis_ip.rtp_payload2);
1736 }
1737
1738 if (TLVP_PRESENT(tv, RSL_IE_IPAC_SPEECH_MODE)) {
1739 lchan->abis_ip.speech_mode =
1740 *TLVP_VAL(tv, RSL_IE_IPAC_SPEECH_MODE);
1741 DEBUGPC(DRSL, "speech_mode=0x%02x ",
1742 lchan->abis_ip.speech_mode);
1743 }
1744
1745 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_IP)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001746 ip.s_addr = *((uint32_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_IP));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001747 DEBUGPC(DRSL, "REMOTE_IP=%s ", inet_ntoa(ip));
1748 lchan->abis_ip.connect_ip = ntohl(ip.s_addr);
1749 }
1750
1751 if (TLVP_PRESENT(tv, RSL_IE_IPAC_REMOTE_PORT)) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001752 port = *((uint16_t *) TLVP_VAL(tv, RSL_IE_IPAC_REMOTE_PORT));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001753 port = ntohs(port);
1754 DEBUGPC(DRSL, "REMOTE_PORT=%u ", port);
1755 lchan->abis_ip.connect_port = port;
1756 }
1757}
1758
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001759int rsl_ipacc_crcx(struct gsm_lchan *lchan)
Harald Welte75099262009-02-16 21:12:08 +00001760{
1761 struct msgb *msg = rsl_msgb_alloc();
1762 struct abis_rsl_dchan_hdr *dh;
1763
1764 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001765 init_dchan_hdr(dh, RSL_MT_IPAC_CRCX);
Harald Welte75099262009-02-16 21:12:08 +00001766 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001767 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001768
Harald Weltef4e79f22009-07-28 18:11:56 +02001769 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001770 lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001771 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001772 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001773 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001774
Sylvain Munautb54dda42009-12-20 22:06:40 +01001775 DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x RTP_PAYLOAD=%d\n",
1776 gsm_lchan_name(lchan), lchan->abis_ip.speech_mode,
1777 lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001778
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001779 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001780
1781 return abis_rsl_sendmsg(msg);
1782}
1783
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001784int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip, uint16_t port,
1785 uint8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001786{
1787 struct msgb *msg = rsl_msgb_alloc();
1788 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001789 uint32_t *att_ip;
Harald Weltef4e79f22009-07-28 18:11:56 +02001790 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001791
1792 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001793 init_dchan_hdr(dh, RSL_MT_IPAC_MDCX);
Harald Welte75099262009-02-16 21:12:08 +00001794 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
Harald Weltef6093a42011-06-25 10:02:33 +02001795 dh->chan_nr = gsm_lchan2chan_nr(lchan);
Harald Welte75099262009-02-16 21:12:08 +00001796
Harald Welte5e3d91b2009-12-19 16:42:06 +01001797 /* we need to store these now as MDCX_ACK does not return them :( */
1798 lchan->abis_ip.rtp_payload2 = rtp_payload2;
1799 lchan->abis_ip.connect_port = port;
1800 lchan->abis_ip.connect_ip = ip;
1801
Harald Welte58ca5b72009-07-29 12:12:18 +02001802 /* 0x0- == both directions, 0x-1 == EFR codec */
Harald Welte5e3d91b2009-12-19 16:42:06 +01001803 lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001804 lchan->abis_ip.rtp_payload = ipa_rtp_pt_for_lchan(lchan);
Harald Welte58ca5b72009-07-29 12:12:18 +02001805
Harald Weltef4e79f22009-07-28 18:11:56 +02001806 ia.s_addr = htonl(ip);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001807 DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD=%d RTP_PAYLOAD2=%d "
1808 "CONN_ID=%d speech_mode=0x%02x\n", gsm_lchan_name(lchan),
1809 inet_ntoa(ia), port, lchan->abis_ip.rtp_payload, rtp_payload2,
1810 lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001811
Harald Welte5e3d91b2009-12-19 16:42:06 +01001812 msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
1813 msgb_v_put(msg, RSL_IE_IPAC_REMOTE_IP);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001814 att_ip = (uint32_t *) msgb_put(msg, sizeof(ip));
Harald Welte5e3d91b2009-12-19 16:42:06 +01001815 *att_ip = ia.s_addr;
1816 msgb_tv16_put(msg, RSL_IE_IPAC_REMOTE_PORT, port);
1817 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
Sylvain Munautb54dda42009-12-20 22:06:40 +01001818 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD, lchan->abis_ip.rtp_payload);
Harald Weltef4e79f22009-07-28 18:11:56 +02001819 if (rtp_payload2)
1820 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001821
1822 msg->dst = lchan->ts->trx->rsl_link;
Harald Welte75099262009-02-16 21:12:08 +00001823
1824 return abis_rsl_sendmsg(msg);
1825}
1826
Harald Weltea72273e2009-12-20 16:51:09 +01001827/* tell BTS to connect RTP stream to our local RTP socket */
1828int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan)
1829{
1830 struct rtp_socket *rs = lchan->abis_ip.rtp_socket;
1831 int rc;
1832
1833 rc = rsl_ipacc_mdcx(lchan, ntohl(rs->rtp.sin_local.sin_addr.s_addr),
1834 ntohs(rs->rtp.sin_local.sin_port),
1835 /* FIXME: use RTP payload of bound socket, not BTS*/
1836 lchan->abis_ip.rtp_payload2);
1837
1838 return rc;
1839}
1840
Harald Welte53cd7ac2010-12-23 12:59:52 +01001841int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act)
Harald Welte9c880c92009-10-24 10:29:22 +02001842{
1843 struct msgb *msg = rsl_msgb_alloc();
1844 struct abis_rsl_dchan_hdr *dh;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +02001845 uint8_t msg_type;
Harald Welte4563eab2010-03-28 14:42:09 +08001846
1847 if (act)
1848 msg_type = RSL_MT_IPAC_PDCH_ACT;
1849 else
1850 msg_type = RSL_MT_IPAC_PDCH_DEACT;
Harald Welte9c880c92009-10-24 10:29:22 +02001851
1852 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
Harald Welte4563eab2010-03-28 14:42:09 +08001853 init_dchan_hdr(dh, msg_type);
Harald Welte9c880c92009-10-24 10:29:22 +02001854 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
Harald Weltef6093a42011-06-25 10:02:33 +02001855 dh->chan_nr = gsm_ts2chan_nr(ts, 0);
Harald Welte9c880c92009-10-24 10:29:22 +02001856
Harald Welte53cd7ac2010-12-23 12:59:52 +01001857 DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_ts_name(ts),
Harald Welte4563eab2010-03-28 14:42:09 +08001858 act ? "" : "DE");
Harald Welte9c880c92009-10-24 10:29:22 +02001859
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001860 msg->dst = ts->trx->rsl_link;
Harald Welte9c880c92009-10-24 10:29:22 +02001861
1862 return abis_rsl_sendmsg(msg);
1863}
1864
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001865static int abis_rsl_rx_ipacc_crcx_ack(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001866{
1867 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1868 struct tlv_parsed tv;
Harald Welte2c828992009-12-02 01:56:49 +05301869 struct gsm_lchan *lchan = msg->lchan;
Harald Welte75099262009-02-16 21:12:08 +00001870
1871 /* the BTS has acknowledged a local bind, it now tells us the IP
1872 * address and port number to which it has bound the given logical
1873 * channel */
1874
1875 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1876 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1877 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02001878 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001879 LOGP(DRSL, LOGL_NOTICE, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001880 return -EINVAL;
1881 }
Harald Welte17f5bf62009-12-20 15:42:44 +01001882
Harald Welte5e3d91b2009-12-19 16:42:06 +01001883 ipac_parse_rtp(lchan, &tv);
Harald Welte17f5bf62009-12-20 15:42:44 +01001884
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001885 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_CRCX_ACK, msg->lchan);
Harald Welte167df882009-02-17 14:35:45 +00001886
Harald Welte75099262009-02-16 21:12:08 +00001887 return 0;
1888}
1889
Harald Welte5e3d91b2009-12-19 16:42:06 +01001890static int abis_rsl_rx_ipacc_mdcx_ack(struct msgb *msg)
1891{
1892 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1893 struct tlv_parsed tv;
1894 struct gsm_lchan *lchan = msg->lchan;
1895
1896 /* the BTS has acknowledged a remote connect request and
1897 * it now tells us the IP address and port number to which it has
1898 * connected the given logical channel */
1899
1900 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1901 ipac_parse_rtp(lchan, &tv);
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001902 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_MDCX_ACK, msg->lchan);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001903
1904 return 0;
1905}
1906
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001907static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
Harald Welte75099262009-02-16 21:12:08 +00001908{
1909 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1910 struct tlv_parsed tv;
1911
1912 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00001913
Harald Welte8830e072009-07-28 17:58:09 +02001914 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
Harald Welte5b8ed432009-12-24 12:20:20 +01001915 print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
Harald Welte8830e072009-07-28 17:58:09 +02001916 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001917
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +02001918 osmo_signal_dispatch(SS_ABISIP, S_ABISIP_DLCX_IND, msg->lchan);
Harald Welte888b1142009-07-28 18:02:05 +02001919
Harald Welte75099262009-02-16 21:12:08 +00001920 return 0;
1921}
1922
1923static int abis_rsl_rx_ipacc(struct msgb *msg)
1924{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001925 struct e1inp_sign_link *sign_link = msg->dst;
Harald Welte75099262009-02-16 21:12:08 +00001926 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Welte5b8ed432009-12-24 12:20:20 +01001927 char *ts_name;
Harald Welte75099262009-02-16 21:12:08 +00001928 int rc = 0;
1929
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001930 msg->lchan = lchan_lookup(sign_link->trx, rllh->chan_nr);
Harald Welte (local)19ef62a2009-12-27 18:16:36 +01001931 ts_name = gsm_lchan_name(msg->lchan);
Harald Welte75099262009-02-16 21:12:08 +00001932
1933 switch (rllh->c.msg_type) {
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001934 case RSL_MT_IPAC_CRCX_ACK:
Harald Welte5b8ed432009-12-24 12:20:20 +01001935 DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001936 rc = abis_rsl_rx_ipacc_crcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001937 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001938 case RSL_MT_IPAC_CRCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001939 /* somehow the BTS was unable to bind the lchan to its local
1940 * port?!? */
Harald Welte5b8ed432009-12-24 12:20:20 +01001941 LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001942 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001943 case RSL_MT_IPAC_MDCX_ACK:
Harald Welte75099262009-02-16 21:12:08 +00001944 /* the BTS tells us that a connect operation was successful */
Harald Welte5b8ed432009-12-24 12:20:20 +01001945 DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
Harald Welte5e3d91b2009-12-19 16:42:06 +01001946 rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
Harald Welte75099262009-02-16 21:12:08 +00001947 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001948 case RSL_MT_IPAC_MDCX_NACK:
Harald Welte75099262009-02-16 21:12:08 +00001949 /* somehow the BTS was unable to connect the lchan to a remote
1950 * port */
Harald Welte5b8ed432009-12-24 12:20:20 +01001951 LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
Harald Welte75099262009-02-16 21:12:08 +00001952 break;
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001953 case RSL_MT_IPAC_DLCX_IND:
Harald Welte5b8ed432009-12-24 12:20:20 +01001954 DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
Holger Hans Peter Freyther231163d2009-11-18 21:06:12 +01001955 rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
Harald Welte75099262009-02-16 21:12:08 +00001956 break;
1957 default:
Harald Welte5b8ed432009-12-24 12:20:20 +01001958 LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001959 rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001960 break;
1961 }
Harald Welte6dab0552009-05-01 17:21:37 +00001962 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001963
1964 return rc;
1965}
1966
1967
Harald Welte52b1f982008-12-23 20:25:15 +00001968/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001969int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001970{
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001971 struct abis_rsl_common_hdr *rslh;
Harald Welte8f5e2392009-02-03 12:57:37 +00001972 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001973
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001974 if (!msg) {
1975 DEBUGP(DRSL, "Empty RSL msg?..\n");
1976 return -1;
1977 }
1978
1979 if (msgb_l2len(msg) < sizeof(*rslh)) {
1980 DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
Harald Weltef25b55e2012-05-31 20:22:34 +02001981 msgb_free(msg);
Holger Hans Peter Freyther19bab732009-11-20 15:14:01 +01001982 return -1;
1983 }
1984
1985 rslh = msgb_l2(msg);
1986
Harald Welte52b1f982008-12-23 20:25:15 +00001987 switch (rslh->msg_discr & 0xfe) {
1988 case ABIS_RSL_MDISC_RLL:
1989 rc = abis_rsl_rx_rll(msg);
1990 break;
1991 case ABIS_RSL_MDISC_DED_CHAN:
1992 rc = abis_rsl_rx_dchan(msg);
1993 break;
1994 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00001995 rc = abis_rsl_rx_cchan(msg);
1996 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001997 case ABIS_RSL_MDISC_TRX:
1998 rc = abis_rsl_rx_trx(msg);
1999 break;
Harald Welte52b1f982008-12-23 20:25:15 +00002000 case ABIS_RSL_MDISC_LOC:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002001 LOGP(DRSL, LOGL_NOTICE, "unimplemented RSL msg disc 0x%02x\n",
Harald Welte8f5e2392009-02-03 12:57:37 +00002002 rslh->msg_discr);
2003 break;
Harald Welte75099262009-02-16 21:12:08 +00002004 case ABIS_RSL_MDISC_IPACCESS:
2005 rc = abis_rsl_rx_ipacc(msg);
2006 break;
Harald Welte52b1f982008-12-23 20:25:15 +00002007 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01002008 LOGP(DRSL, LOGL_NOTICE, "unknown RSL message discriminator "
2009 "0x%02x\n", rslh->msg_discr);
Harald Weltef25b55e2012-05-31 20:22:34 +02002010 rc = -EINVAL;
Harald Welte52b1f982008-12-23 20:25:15 +00002011 }
Harald Welte4f4a3902008-12-26 00:04:49 +00002012 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00002013 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00002014}
Holger Freyther3b72a892009-02-04 00:31:39 +00002015
Holger Hans Peter Freyther8cb4a0f2010-07-21 15:54:32 +08002016int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
2017 uint8_t cb_command, const uint8_t *data, int len)
2018{
2019 struct abis_rsl_dchan_hdr *dh;
2020 struct msgb *cb_cmd;
2021
2022 cb_cmd = rsl_msgb_alloc();
2023 if (!cb_cmd)
2024 return -1;
2025
2026 dh = (struct abis_rsl_dchan_hdr *) msgb_put(cb_cmd, sizeof*dh);
2027 init_dchan_hdr(dh, RSL_MT_SMS_BC_CMD);
2028 dh->chan_nr = RSL_CHAN_SDCCH4_ACCH; /* TODO: check the chan config */
2029
2030 msgb_tv_put(cb_cmd, RSL_IE_CB_CMD_TYPE, cb_command);
2031 msgb_tlv_put(cb_cmd, RSL_IE_SMSCB_MSG, len, data);
2032
2033 cb_cmd->trx = bts->c0;
2034
2035 return abis_rsl_sendmsg(cb_cmd);
2036}
Dieter Spaar16646022011-07-28 00:01:50 +02002037
2038int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
2039{
2040 struct abis_rsl_common_hdr *ch;
2041 struct msgb *msg = rsl_msgb_alloc();
2042
2043 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2044 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2045 ch->msg_type = 0x40; /* Nokia SI Begin */
2046
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002047 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002048
2049 return abis_rsl_sendmsg(msg);
2050}
2051
2052int rsl_nokia_si_end(struct gsm_bts_trx *trx)
2053{
2054 struct abis_rsl_common_hdr *ch;
2055 struct msgb *msg = rsl_msgb_alloc();
2056
2057 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2058 ch->msg_discr = ABIS_RSL_MDISC_TRX;
2059 ch->msg_type = 0x41; /* Nokia SI End */
2060
2061 msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
2062
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002063 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002064
2065 return abis_rsl_sendmsg(msg);
2066}
2067
2068int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
2069{
2070 struct abis_rsl_common_hdr *ch;
2071 struct msgb *msg = rsl_msgb_alloc();
2072
2073 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
2074 ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
2075 ch->msg_type = RSL_MT_BS_POWER_CONTROL;
2076
2077 msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
2078 msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
2079
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02002080 msg->dst = trx->rsl_link;
Dieter Spaar16646022011-07-28 00:01:50 +02002081
2082 return abis_rsl_sendmsg(msg);
2083}
Holger Hans Peter Freyther85825352011-12-27 22:24:17 +01002084
2085/**
2086 * Release all allocated SAPIs starting from @param start and
2087 * release them with the given release mode. Once the release
2088 * confirmation arrives it will be attempted to release the
2089 * the RF channel.
2090 */
2091int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
2092 enum rsl_rel_mode release_mode)
2093{
2094 int no_sapi = 1;
2095 int sapi;
2096
2097 for (sapi = start; sapi < ARRAY_SIZE(lchan->sapis); ++sapi) {
2098 uint8_t link_id;
2099 if (lchan->sapis[sapi] == LCHAN_SAPI_UNUSED)
2100 continue;
2101
2102 link_id = sapi;
2103 if (lchan->type == GSM_LCHAN_TCH_F || lchan->type == GSM_LCHAN_TCH_H)
2104 link_id |= 0x40;
2105 rsl_release_request(lchan, link_id, release_mode);
2106 no_sapi = 0;
2107 }
2108
2109 return no_sapi;
2110}