blob: 2f334360b41c6147feee9050a1c91960ad057d0a [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* GSM Radio Signalling Link messages on the A-bis interface
2 * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
3
Harald Welte8f5e2392009-02-03 12:57:37 +00004/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
Harald Welte8470bf22008-12-25 23:28:35 +00005 *
Harald Welte52b1f982008-12-23 20:25:15 +00006 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <stdio.h>
Harald Welte8470bf22008-12-25 23:28:35 +000025#include <stdlib.h>
Harald Welte52b1f982008-12-23 20:25:15 +000026#include <errno.h>
27#include <sys/types.h>
Harald Welte75099262009-02-16 21:12:08 +000028#include <netinet/in.h>
Harald Welte167df882009-02-17 14:35:45 +000029#include <arpa/inet.h>
Harald Welte52b1f982008-12-23 20:25:15 +000030
Harald Welte8470bf22008-12-25 23:28:35 +000031#include <openbsc/gsm_data.h>
32#include <openbsc/gsm_04_08.h>
Harald Welte66b6a8d2009-08-09 14:45:18 +020033#include <openbsc/gsm_utils.h>
Harald Welte8470bf22008-12-25 23:28:35 +000034#include <openbsc/abis_rsl.h>
35#include <openbsc/chan_alloc.h>
Harald Welteedcc5272009-08-09 13:47:35 +020036#include <openbsc/bsc_rll.h>
Harald Welte8470bf22008-12-25 23:28:35 +000037#include <openbsc/debug.h>
38#include <openbsc/tlv.h>
Holger Freyther392209c2009-02-10 00:06:19 +000039#include <openbsc/paging.h>
Harald Welte167df882009-02-17 14:35:45 +000040#include <openbsc/signal.h>
Harald Welte52b1f982008-12-23 20:25:15 +000041
Harald Welte8470bf22008-12-25 23:28:35 +000042#define RSL_ALLOC_SIZE 1024
43#define RSL_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000044
Holger Freyther3b72a892009-02-04 00:31:39 +000045#define MAX(a, b) (a) >= (b) ? (a) : (b)
46
Harald Welte75099262009-02-16 21:12:08 +000047static const struct tlv_definition rsl_att_tlvdef = {
48 .def = {
49 [RSL_IE_CHAN_NR] = { TLV_TYPE_TV },
50 [RSL_IE_LINK_IDENT] = { TLV_TYPE_TV },
51 [RSL_IE_ACT_TYPE] = { TLV_TYPE_TV },
52 [RSL_IE_BS_POWER] = { TLV_TYPE_TV },
53 [RSL_IE_CHAN_IDENT] = { TLV_TYPE_TLV },
54 [RSL_IE_CHAN_MODE] = { TLV_TYPE_TLV },
55 [RSL_IE_ENCR_INFO] = { TLV_TYPE_TLV },
56 [RSL_IE_FRAME_NUMBER] = { TLV_TYPE_FIXED, 2 },
57 [RSL_IE_HANDO_REF] = { TLV_TYPE_TV },
58 [RSL_IE_L1_INFO] = { TLV_TYPE_FIXED, 2 },
59 [RSL_IE_L3_INFO] = { TLV_TYPE_TL16V },
60 [RSL_IE_MS_IDENTITY] = { TLV_TYPE_TLV },
61 [RSL_IE_MS_POWER] = { TLV_TYPE_TV },
62 [RSL_IE_PAGING_GROUP] = { TLV_TYPE_TV },
63 [RSL_IE_PAGING_LOAD] = { TLV_TYPE_FIXED, 2 },
64 [RSL_IE_PYHS_CONTEXT] = { TLV_TYPE_TLV },
65 [RSL_IE_ACCESS_DELAY] = { TLV_TYPE_TV },
66 [RSL_IE_RACH_LOAD] = { TLV_TYPE_TLV },
67 [RSL_IE_REQ_REFERENCE] = { TLV_TYPE_FIXED, 3 },
68 [RSL_IE_RELEASE_MODE] = { TLV_TYPE_TV },
69 [RSL_IE_RESOURCE_INFO] = { TLV_TYPE_TLV },
70 [RSL_IE_RLM_CAUSE] = { TLV_TYPE_TLV },
71 [RSL_IE_STARTNG_TIME] = { TLV_TYPE_FIXED, 2 },
72 [RSL_IE_TIMING_ADVANCE] = { TLV_TYPE_TV },
73 [RSL_IE_UPLINK_MEAS] = { TLV_TYPE_TLV },
74 [RSL_IE_CAUSE] = { TLV_TYPE_TLV },
75 [RSL_IE_MEAS_RES_NR] = { TLV_TYPE_TV },
76 [RSL_IE_MSG_ID] = { TLV_TYPE_TV },
77 [RSL_IE_SYSINFO_TYPE] = { TLV_TYPE_TV },
78 [RSL_IE_MS_POWER_PARAM] = { TLV_TYPE_TLV },
79 [RSL_IE_BS_POWER_PARAM] = { TLV_TYPE_TLV },
80 [RSL_IE_PREPROC_PARAM] = { TLV_TYPE_TLV },
81 [RSL_IE_PREPROC_MEAS] = { TLV_TYPE_TLV },
82 [RSL_IE_IMM_ASS_INFO] = { TLV_TYPE_TLV },
83 [RSL_IE_SMSCB_INFO] = { TLV_TYPE_FIXED, 23 },
84 [RSL_IE_MS_TIMING_OFFSET] = { TLV_TYPE_TV },
85 [RSL_IE_ERR_MSG] = { TLV_TYPE_TLV },
86 [RSL_IE_FULL_BCCH_INFO] = { TLV_TYPE_TLV },
87 [RSL_IE_CHAN_NEEDED] = { TLV_TYPE_TV },
88 [RSL_IE_CB_CMD_TYPE] = { TLV_TYPE_TV },
89 [RSL_IE_SMSCB_MSG] = { TLV_TYPE_TLV },
90 [RSL_IE_FULL_IMM_ASS_INFO] = { TLV_TYPE_TLV },
91 [RSL_IE_SACCH_INFO] = { TLV_TYPE_TLV },
92 [RSL_IE_CBCH_LOAD_INFO] = { TLV_TYPE_TV },
93 [RSL_IE_SMSCB_CHAN_INDICATOR] = { TLV_TYPE_TV },
94 [RSL_IE_GROUP_CALL_REF] = { TLV_TYPE_TLV },
95 [RSL_IE_CHAN_DESC] = { TLV_TYPE_TLV },
96 [RSL_IE_NCH_DRX_INFO] = { TLV_TYPE_TLV },
97 [RSL_IE_CMD_INDICATOR] = { TLV_TYPE_TLV },
98 [RSL_IE_EMLPP_PRIO] = { TLV_TYPE_TV },
99 [RSL_IE_UIC] = { TLV_TYPE_TLV },
100 [RSL_IE_MAIN_CHAN_REF] = { TLV_TYPE_TV },
101 [RSL_IE_MR_CONFIG] = { TLV_TYPE_TLV },
102 [RSL_IE_MR_CONTROL] = { TLV_TYPE_TV },
103 [RSL_IE_SUP_CODEC_TYPES] = { TLV_TYPE_TLV },
104 [RSL_IE_CODEC_CONFIG] = { TLV_TYPE_TLV },
105 [RSL_IE_RTD] = { TLV_TYPE_TV },
106 [RSL_IE_TFO_STATUS] = { TLV_TYPE_TV },
107 [RSL_IE_LLP_APDU] = { TLV_TYPE_TLV },
Harald Welte67fa91b2009-08-10 09:51:40 +0200108 [RSL_IE_SIEMENS_MRPCI] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200109 [RSL_IE_IPAC_PROXY_UDP] = { TLV_TYPE_FIXED, 2 },
110 [RSL_IE_IPAC_BSCMPL_TOUT] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000111 [RSL_IE_IPAC_REMOTE_IP] = { TLV_TYPE_FIXED, 4 },
112 [RSL_IE_IPAC_REMOTE_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200113 [RSL_IE_IPAC_RTP_PAYLOAD] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000114 [RSL_IE_IPAC_LOCAL_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welte86c162d2009-07-12 09:45:05 +0200115 [RSL_IE_IPAC_SPEECH_MODE] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200116 [RSL_IE_IPAC_LOCAL_IP] = { TLV_TYPE_FIXED, 4 },
Harald Welte86c162d2009-07-12 09:45:05 +0200117 [RSL_IE_IPAC_CONN_ID] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200118 [RSL_IE_IPAC_RTP_CSD_FMT] = { TLV_TYPE_TV },
119 [RSL_IE_IPAC_RTP_JIT_BUF] = { TLV_TYPE_FIXED, 2 },
120 [RSL_IE_IPAC_RTP_COMPR] = { TLV_TYPE_TV },
Harald Welte86c162d2009-07-12 09:45:05 +0200121 [RSL_IE_IPAC_RTP_PAYLOAD2] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200122 [RSL_IE_IPAC_RTP_MPLEX] = { TLV_TYPE_FIXED, 8 },
123 [RSL_IE_IPAC_RTP_MPLEX_ID] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000124 },
125};
Harald Weltea4d49e92009-05-23 06:39:58 +0000126#define rsl_tlv_parse(dec, buf, len) \
127 tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
Harald Welte75099262009-02-16 21:12:08 +0000128
Harald Welte52b1f982008-12-23 20:25:15 +0000129static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
130{
131 /* mask off the transparent bit ? */
132 msg_type &= 0xfe;
133
Harald Welte8470bf22008-12-25 23:28:35 +0000134 if ((msg_type & 0xf0) == 0x00)
Harald Welte52b1f982008-12-23 20:25:15 +0000135 return ABIS_RSL_MDISC_RLL;
Harald Welte8470bf22008-12-25 23:28:35 +0000136 if ((msg_type & 0xf0) == 0x10) {
Harald Welte52b1f982008-12-23 20:25:15 +0000137 if (msg_type >= 0x19 && msg_type <= 0x22)
138 return ABIS_RSL_MDISC_TRX;
139 else
140 return ABIS_RSL_MDISC_COM_CHAN;
141 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000142 if ((msg_type & 0xe0) == 0x20)
Harald Welte52b1f982008-12-23 20:25:15 +0000143 return ABIS_RSL_MDISC_DED_CHAN;
144
145 return ABIS_RSL_MDISC_LOC;
146}
147
148static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
149 u_int8_t msg_type)
150{
151 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
152 dh->c.msg_type = msg_type;
153 dh->ie_chan = RSL_IE_CHAN_NR;
154}
155
156static inline void init_llm_hdr(struct abis_rsl_rll_hdr *dh,
157 u_int8_t msg_type)
158{
159 /* dh->c.msg_discr = mdisc_by_msgtype(msg_type); */
160 dh->c.msg_discr = ABIS_RSL_MDISC_RLL;
161 dh->c.msg_type = msg_type;
162 dh->ie_chan = RSL_IE_CHAN_NR;
163 dh->ie_link_id = RSL_IE_LINK_IDENT;
164}
165
166
167/* encode channel number as per Section 9.3.1 */
168u_int8_t rsl_enc_chan_nr(u_int8_t type, u_int8_t subch, u_int8_t timeslot)
169{
170 u_int8_t ret;
171
172 ret = (timeslot & 0x07) | type;
173
174 switch (type) {
175 case RSL_CHAN_Lm_ACCHs:
176 subch &= 0x01;
177 break;
178 case RSL_CHAN_SDCCH4_ACCH:
179 subch &= 0x07;
180 break;
181 case RSL_CHAN_SDCCH8_ACCH:
182 subch &= 0x07;
183 break;
184 default:
185 /* no subchannels allowed */
186 subch = 0x00;
187 break;
188 }
189 ret |= (subch << 3);
190
191 return ret;
192}
193
Harald Welte8470bf22008-12-25 23:28:35 +0000194/* determine logical channel based on TRX and channel number IE */
195struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
196{
197 struct gsm_lchan *lchan;
198 u_int8_t ts_nr = chan_nr & 0x07;
199 u_int8_t cbits = chan_nr >> 3;
200 u_int8_t lch_idx;
201 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
202
203 if (cbits == 0x01) {
204 lch_idx = 0; /* TCH/F */
205 if (ts->pchan != GSM_PCHAN_TCH_F)
206 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
207 chan_nr, ts->pchan);
208 } else if ((cbits & 0x1e) == 0x02) {
209 lch_idx = cbits & 0x1; /* TCH/H */
210 if (ts->pchan != GSM_PCHAN_TCH_H)
211 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
212 chan_nr, ts->pchan);
213 } else if ((cbits & 0x1c) == 0x04) {
214 lch_idx = cbits & 0x3; /* SDCCH/4 */
215 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
216 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
217 chan_nr, ts->pchan);
218 } else if ((cbits & 0x18) == 0x08) {
219 lch_idx = cbits & 0x7; /* SDCCH/8 */
220 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
221 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
222 chan_nr, ts->pchan);
223 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
224 lch_idx = 0;
225 if (ts->pchan != GSM_PCHAN_CCCH &&
226 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
227 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
228 chan_nr, ts->pchan);
229 /* FIXME: we should not return first sdcch4 !!! */
230 } else {
231 fprintf(stderr, "unknown chan_nr=0x%02x\n", chan_nr);
232 return NULL;
233 }
234
235 lchan = &ts->lchan[lch_idx];
236
237 return lchan;
238}
239
240u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
241{
242 struct gsm_bts_trx_ts *ts = lchan->ts;
243 u_int8_t cbits, chan_nr;
244
245 switch (ts->pchan) {
246 case GSM_PCHAN_TCH_F:
247 cbits = 0x01;
248 break;
249 case GSM_PCHAN_TCH_H:
250 cbits = 0x02;
251 cbits += lchan->nr;
252 break;
253 case GSM_PCHAN_CCCH_SDCCH4:
254 cbits = 0x04;
255 cbits += lchan->nr;
256 break;
257 case GSM_PCHAN_SDCCH8_SACCH8C:
258 cbits = 0x08;
259 cbits += lchan->nr;
260 break;
261 default:
262 case GSM_PCHAN_CCCH:
263 cbits = 0x10;
264 break;
265 }
266
267 chan_nr = (cbits << 3) | (ts->nr & 0x7);
268
269 return chan_nr;
270}
271
Harald Welte52b1f982008-12-23 20:25:15 +0000272/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
273u_int64_t str_to_imsi(const char *imsi_str)
274{
275 u_int64_t ret;
276
277 ret = strtoull(imsi_str, NULL, 10);
278
279 return ret;
280}
281
282/* Table 5 Clause 7 TS 05.02 */
283unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res)
284{
285 if (!bs_ccch_sdcch_comb)
286 return 9 - bs_ag_blks_res;
287 else
288 return 3 - bs_ag_blks_res;
289}
290
291/* Chapter 6.5.2 of TS 05.02 */
292unsigned int get_ccch_group(u_int64_t imsi, unsigned int bs_cc_chans,
293 unsigned int n_pag_blocks)
294{
295 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) / n_pag_blocks;
296}
297
298/* Chapter 6.5.2 of TS 05.02 */
299unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
300 int n_pag_blocks)
301{
302 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) % n_pag_blocks;
303}
304
Harald Welte8470bf22008-12-25 23:28:35 +0000305static struct msgb *rsl_msgb_alloc(void)
306{
Harald Welte966636f2009-06-26 19:39:35 +0200307 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
308 "RSL");
Harald Welte8470bf22008-12-25 23:28:35 +0000309}
310
Harald Welte362322e2009-02-15 14:36:38 +0000311#define MACBLOCK_SIZE 23
312static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
313{
314 memcpy(out, in, len);
315
316 if (len < MACBLOCK_SIZE)
317 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
318}
319
Harald Welte8830e072009-07-28 17:58:09 +0200320static const char *rsl_err_vals[0xff] = {
321 [RSL_ERR_RADIO_IF_FAIL] = "Radio Interface Failure",
322 [RSL_ERR_RADIO_LINK_FAIL] = "Radio Link Failure",
323 [RSL_ERR_HANDOVER_ACC_FAIL] = "Handover Access Failure",
324 [RSL_ERR_TALKER_ACC_FAIL] = "Talker Access Failure",
325 [RSL_ERR_OM_INTERVENTION] = "O&M Intervention",
326 [RSL_ERR_NORMAL_UNSPEC] = "Normal event, unspecified",
Harald Welte2da86292009-08-04 02:31:05 +0200327 [RSL_ERR_T_MSRFPCI_EXP] = "Siemens: T_MSRFPCI Expired",
Harald Welte8830e072009-07-28 17:58:09 +0200328 [RSL_ERR_EQUIPMENT_FAIL] = "Equipment Failure",
329 [RSL_ERR_RR_UNAVAIL] = "Radio Resource not available",
330 [RSL_ERR_TERR_CH_FAIL] = "Terrestrial Channel Failure",
331 [RSL_ERR_CCCH_OVERLOAD] = "CCCH Overload",
332 [RSL_ERR_ACCH_OVERLOAD] = "ACCH Overload",
333 [RSL_ERR_PROCESSOR_OVERLOAD] = "Processor Overload",
334 [RSL_ERR_RES_UNAVAIL] = "Resource not available, unspecified",
335 [RSL_ERR_TRANSC_UNAVAIL] = "Transcoding not available",
336 [RSL_ERR_SERV_OPT_UNAVAIL] = "Service or Option not available",
337 [RSL_ERR_ENCR_UNIMPL] = "Encryption algorithm not implemented",
338 [RSL_ERR_SERV_OPT_UNIMPL] = "Service or Option not implemented",
339 [RSL_ERR_RCH_ALR_ACTV_ALLOC] = "Radio channel already activated",
340 [RSL_ERR_INVALID_MESSAGE] = "Invalid Message, unspecified",
341 [RSL_ERR_MSG_DISCR] = "Message Discriminator Error",
342 [RSL_ERR_MSG_TYPE] = "Message Type Error",
343 [RSL_ERR_MSG_SEQ] = "Message Sequence Error",
344 [RSL_ERR_IE_ERROR] = "General IE error",
345 [RSL_ERR_MAND_IE_ERROR] = "Mandatory IE error",
346 [RSL_ERR_OPT_IE_ERROR] = "Optional IE error",
347 [RSL_ERR_IE_NONEXIST] = "IE non-existent",
348 [RSL_ERR_IE_LENGTH] = "IE length error",
349 [RSL_ERR_IE_CONTENT] = "IE content error",
350 [RSL_ERR_PROTO] = "Protocol error, unspecified",
351 [RSL_ERR_INTERWORKING] = "Interworking error, unspecified",
352};
353
354static const char *rsl_err_name(u_int8_t err)
Harald Welte7f93cea2009-02-23 00:02:59 +0000355{
Harald Welte8830e072009-07-28 17:58:09 +0200356 if (rsl_err_vals[err])
357 return rsl_err_vals[err];
358 else
359 return "unknown";
360}
361
362static void print_rsl_cause(const u_int8_t *cause_v, u_int8_t cause_len)
363{
Harald Welte7f93cea2009-02-23 00:02:59 +0000364 int i;
365
Harald Welte8830e072009-07-28 17:58:09 +0200366 DEBUGPC(DRSL, "CAUSE=0x%02x(%s) ",
367 cause_v[0], rsl_err_name(cause_v[0]));
368 for (i = 1; i < cause_len-1; i++)
369 DEBUGPC(DRSL, "%02x ", cause_v[i]);
Harald Welte7f93cea2009-02-23 00:02:59 +0000370}
371
Harald Welte52b1f982008-12-23 20:25:15 +0000372/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Harald Weltee79769b2009-02-07 00:48:17 +0000373int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000374 const u_int8_t *data, int len)
375{
376 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000377 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000378
379 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
380 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
381 dh->chan_nr = RSL_CHAN_BCCH;
382
383 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
384 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
385
Harald Weltee79769b2009-02-07 00:48:17 +0000386 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000387
388 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000389}
390
Harald Weltee79769b2009-02-07 00:48:17 +0000391int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000392 const u_int8_t *data, int len)
393{
394 struct abis_rsl_common_hdr *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000395 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000396
397 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
398 ch->msg_discr = ABIS_RSL_MDISC_TRX;
399 ch->msg_type = RSL_MT_SACCH_FILL;
400
401 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
Harald Welte702d8702008-12-26 20:25:35 +0000402 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
Harald Welte52b1f982008-12-23 20:25:15 +0000403
Harald Weltee79769b2009-02-07 00:48:17 +0000404 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000405
406 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000407}
408
Harald Weltefcd24452009-06-20 18:15:19 +0200409int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
410{
411 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200412 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200413 u_int8_t chan_nr = lchan2chan_nr(lchan);
414
415 db = abs(db);
416 if (db > 30)
417 return -EINVAL;
418
Harald Welteeab33352009-06-27 03:09:08 +0200419 msg = rsl_msgb_alloc();
420
Harald Weltefcd24452009-06-20 18:15:19 +0200421 lchan->bs_power = db/2;
422 if (fpc)
423 lchan->bs_power |= 0x10;
424
425 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
426 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
427 dh->chan_nr = chan_nr;
428
429 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
430
431 msg->trx = lchan->ts->trx;
432
433 return abis_rsl_sendmsg(msg);
434}
435
Harald Weltefcd24452009-06-20 18:15:19 +0200436int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
437{
438 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200439 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200440 u_int8_t chan_nr = lchan2chan_nr(lchan);
441 int ctl_lvl;
442
Harald Welte66b6a8d2009-08-09 14:45:18 +0200443 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Weltefcd24452009-06-20 18:15:19 +0200444 if (ctl_lvl < 0)
445 return ctl_lvl;
446
Harald Welteeab33352009-06-27 03:09:08 +0200447 msg = rsl_msgb_alloc();
448
Harald Weltefcd24452009-06-20 18:15:19 +0200449 lchan->ms_power = ctl_lvl;
450
451 if (fpc)
452 lchan->ms_power |= 0x20;
453
454 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
455 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
456 dh->chan_nr = chan_nr;
457
458 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
459
460 msg->trx = lchan->ts->trx;
461
462 return abis_rsl_sendmsg(msg);
463}
464
Harald Welte9943c5b2009-07-29 15:41:29 +0200465static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
466 struct gsm_lchan *lchan)
467{
468 memset(cm, 0, sizeof(cm));
469
470 /* FIXME: what to do with data calls ? */
471 cm->dtx_dtu = 0x00;
472
473 /* set TCH Speech/Data */
474 cm->spd_ind = lchan->rsl_cmode;
475
476 switch (lchan->type) {
477 case GSM_LCHAN_SDCCH:
478 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
479 break;
480 case GSM_LCHAN_TCH_F:
481 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
482 break;
483 case GSM_LCHAN_TCH_H:
484 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
485 break;
486 case GSM_LCHAN_NONE:
487 case GSM_LCHAN_UNKNOWN:
488 default:
489 return -EINVAL;
490 }
491
492 switch (lchan->tch_mode) {
493 case GSM48_CMODE_SIGN:
494 cm->chan_rate = 0;
495 break;
496 case GSM48_CMODE_SPEECH_V1:
497 cm->chan_rate = RSL_CMOD_SP_GSM1;
498 break;
499 case GSM48_CMODE_SPEECH_EFR:
500 cm->chan_rate = RSL_CMOD_SP_GSM2;
501 break;
502 case GSM48_CMODE_SPEECH_AMR:
503 cm->chan_rate = RSL_CMOD_SP_GSM3;
504 break;
505 case GSM48_CMODE_DATA_14k5:
506 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
507 break;
508 case GSM48_CMODE_DATA_12k0:
509 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
510 break;
511 case GSM48_CMODE_DATA_6k0:
512 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
513 break;
514 default:
515 return -EINVAL;
516 }
517
518 return 0;
519}
520
Harald Welte52b1f982008-12-23 20:25:15 +0000521/* Chapter 8.4.1 */
Harald Welteddab3c72009-02-28 13:19:15 +0000522#if 0
Harald Weltee79769b2009-02-07 00:48:17 +0000523int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
Harald Welte52b1f982008-12-23 20:25:15 +0000524 u_int8_t act_type,
525 struct rsl_ie_chan_mode *chan_mode,
526 struct rsl_ie_chan_ident *chan_ident,
527 u_int8_t bs_power, u_int8_t ms_power,
528 u_int8_t ta)
529{
530 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000531 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000532
533 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
534 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
535 dh->chan_nr = chan_nr;
536
537 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
538 /* For compatibility with Phase 1 */
539 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
540 (u_int8_t *) chan_mode);
541 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Harald Welte702d8702008-12-26 20:25:35 +0000542 (u_int8_t *) chan_ident);
Harald Welte702d8702008-12-26 20:25:35 +0000543#if 0
Harald Welte52b1f982008-12-23 20:25:15 +0000544 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
545 (u_int8_t *) &encr_info);
Harald Welte702d8702008-12-26 20:25:35 +0000546#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000547 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
Harald Welte52b1f982008-12-23 20:25:15 +0000548 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
549 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
550
Harald Weltee79769b2009-02-07 00:48:17 +0000551 msg->trx = trx;
552
Harald Welte8470bf22008-12-25 23:28:35 +0000553 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000554}
Harald Welteddab3c72009-02-28 13:19:15 +0000555#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000556
Harald Welte8f5e2392009-02-03 12:57:37 +0000557int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
Harald Welte9943c5b2009-07-29 15:41:29 +0200558 u_int8_t ta)
Harald Welte4b634542008-12-27 01:55:51 +0000559{
560 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200561 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200562 int rc;
Harald Welte4b634542008-12-27 01:55:51 +0000563
564 u_int8_t chan_nr = lchan2chan_nr(lchan);
565 u_int16_t arfcn = lchan->ts->trx->arfcn;
566 struct rsl_ie_chan_mode cm;
567 struct rsl_ie_chan_ident ci;
568
Harald Welte9943c5b2009-07-29 15:41:29 +0200569 rc = channel_mode_from_lchan(&cm, lchan);
570 if (rc < 0)
571 return rc;
Harald Welte4b634542008-12-27 01:55:51 +0000572
Harald Welte02b0e092009-02-28 13:11:07 +0000573 memset(&ci, 0, sizeof(ci));
Harald Welte4b634542008-12-27 01:55:51 +0000574 ci.chan_desc.iei = 0x64;
575 ci.chan_desc.chan_nr = chan_nr;
Harald Welte02b0e092009-02-28 13:11:07 +0000576 ci.chan_desc.oct3 = (lchan->ts->trx->bts->tsc << 5) | ((arfcn & 0x3ff) >> 8);
Harald Welte4b634542008-12-27 01:55:51 +0000577 ci.chan_desc.oct4 = arfcn & 0xff;
578
Harald Welteeab33352009-06-27 03:09:08 +0200579 msg = rsl_msgb_alloc();
Harald Welte4b634542008-12-27 01:55:51 +0000580 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
581 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
582 dh->chan_nr = chan_nr;
583
584 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
585 /* For compatibility with Phase 1 */
586 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
587 (u_int8_t *) &cm);
588 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
589 (u_int8_t *) &ci);
Harald Welte4b634542008-12-27 01:55:51 +0000590#if 0
591 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
592 (u_int8_t *) &encr_info);
Harald Welte4b634542008-12-27 01:55:51 +0000593#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000594 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
595 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
Harald Welte4b634542008-12-27 01:55:51 +0000596 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
597
Harald Weltee79769b2009-02-07 00:48:17 +0000598 msg->trx = lchan->ts->trx;
599
Harald Welte4b634542008-12-27 01:55:51 +0000600 return abis_rsl_sendmsg(msg);
601}
602
Harald Welte470abb72009-07-29 11:38:15 +0200603/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welteda783762009-02-18 03:29:53 +0000604int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
605{
606 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200607 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200608 int rc;
Harald Welteda783762009-02-18 03:29:53 +0000609
610 u_int8_t chan_nr = lchan2chan_nr(lchan);
611 struct rsl_ie_chan_mode cm;
612
Harald Welte9943c5b2009-07-29 15:41:29 +0200613 rc = channel_mode_from_lchan(&cm, lchan);
614 if (rc < 0)
615 return rc;
Harald Welteda783762009-02-18 03:29:53 +0000616
Harald Welteeab33352009-06-27 03:09:08 +0200617 msg = rsl_msgb_alloc();
Harald Welteda783762009-02-18 03:29:53 +0000618 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
619 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
620 dh->chan_nr = chan_nr;
621
622 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
623 (u_int8_t *) &cm);
624#if 0
625 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
626 (u_int8_t *) &encr_info);
627#endif
628
629 msg->trx = lchan->ts->trx;
630
631 return abis_rsl_sendmsg(msg);
632}
633
Harald Welte115d1032009-08-10 11:43:22 +0200634/* Chapter 8.4.5 / 4.6: Deactivate the SACCH after 04.08 RR CHAN RELEASE */
Harald Welteae0f2362009-07-19 18:36:49 +0200635int rsl_deact_sacch(struct gsm_lchan *lchan)
636{
637 struct abis_rsl_dchan_hdr *dh;
638 struct msgb *msg = rsl_msgb_alloc();
639
640 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
641 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
642 dh->chan_nr = lchan2chan_nr(lchan);
643
644 msg->lchan = lchan;
645 msg->trx = lchan->ts->trx;
646
647 DEBUGP(DRSL, "DEACTivate SACCH CMD channel=%s chan_nr=0x%02x\n",
648 gsm_ts_name(lchan->ts), dh->chan_nr);
649
650 return abis_rsl_sendmsg(msg);
651}
652
Harald Welte115d1032009-08-10 11:43:22 +0200653/* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */
654int rsl_rf_chan_release(struct gsm_lchan *lchan)
Harald Welte52b1f982008-12-23 20:25:15 +0000655{
656 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000657 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000658
659 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
660 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Welte8470bf22008-12-25 23:28:35 +0000661 dh->chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +0000662
Harald Welte8470bf22008-12-25 23:28:35 +0000663 msg->lchan = lchan;
664 msg->trx = lchan->ts->trx;
665
Harald Welte115d1032009-08-10 11:43:22 +0200666 DEBUGP(DRSL, "RF Channel Release CMD channel=%s chan_nr=0x%02x\n",
Harald Weltef325eb42009-02-19 17:07:39 +0000667 gsm_ts_name(lchan->ts), dh->chan_nr);
Harald Welte2d5b6382008-12-27 19:46:06 +0000668
Harald Welte115d1032009-08-10 11:43:22 +0200669 /* BTS will respond by RF CHAN REL ACK */
Harald Welte8470bf22008-12-25 23:28:35 +0000670 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000671}
672
673int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
674 u_int8_t *ms_ident, u_int8_t chan_needed)
675{
676 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000677 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000678
679 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
680 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
681 dh->chan_nr = RSL_CHAN_PCH_AGCH;
682
683 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
Harald Welte255539c2008-12-28 02:26:27 +0000684 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000685 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
686
Harald Welte8470bf22008-12-25 23:28:35 +0000687 msg->trx = bts->c0;
688
689 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000690}
691
Holger Freyther7448a532009-01-04 20:18:23 +0000692int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_need,
693 struct gsm_subscriber *subscr)
694{
Holger Freytherca362a62009-01-04 21:05:01 +0000695#if 0
Holger Freyther7448a532009-01-04 20:18:23 +0000696 u_int8_t mi[128];
697 unsigned int mi_len;
698 u_int8_t paging_group;
Holger Freytherca362a62009-01-04 21:05:01 +0000699#endif
Holger Freyther7448a532009-01-04 20:18:23 +0000700
701 return -1;
702}
703
Harald Welte52b1f982008-12-23 20:25:15 +0000704int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
705{
706 int i, len = strlen(str_in);
707
708 for (i = 0; i < len; i++) {
709 int num = str_in[i] - 0x30;
710 if (num < 0 || num > 9)
711 return -1;
712 if (i % 2 == 0)
713 bcd_out[i/2] = num;
714 else
715 bcd_out[i/2] |= (num << 4);
716 }
717
718 return 0;
719}
720
Harald Welte702d8702008-12-26 20:25:35 +0000721/* Chapter 8.5.6 */
Harald Welte52b1f982008-12-23 20:25:15 +0000722int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val)
723{
Harald Welte8470bf22008-12-25 23:28:35 +0000724 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000725 struct abis_rsl_dchan_hdr *dh;
Harald Welte362322e2009-02-15 14:36:38 +0000726 u_int8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000727
728 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
729 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
730 dh->chan_nr = RSL_CHAN_PCH_AGCH;
731
Harald Welte362322e2009-02-15 14:36:38 +0000732 switch (bts->type) {
733 case GSM_BTS_TYPE_BS11:
734 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
735 break;
736 default:
737 /* If phase 2, construct a FULL_IMM_ASS_INFO */
738 pad_macblock(buf, val, len);
739 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
740 break;
741 }
Harald Welte52b1f982008-12-23 20:25:15 +0000742
Harald Welte8470bf22008-12-25 23:28:35 +0000743 msg->trx = bts->c0;
744
745 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000746}
747
Harald Welte67fa91b2009-08-10 09:51:40 +0200748/* Send Siemens specific MS RF Power Capability Indication */
Harald Welte31c48932009-08-10 10:07:33 +0200749int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
Harald Welte67fa91b2009-08-10 09:51:40 +0200750{
751 struct msgb *msg = rsl_msgb_alloc();
752 struct abis_rsl_dchan_hdr *dh;
753
754 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
755 init_dchan_hdr(dh, RSL_MT_SIEMENS_MRPCI);
756 dh->chan_nr = lchan2chan_nr(lchan);
Harald Welte31c48932009-08-10 10:07:33 +0200757 msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(u_int8_t *)mrpci);
Harald Welte67fa91b2009-08-10 09:51:40 +0200758
759 return abis_rsl_sendmsg(msg);
760}
761
762
Harald Welte8470bf22008-12-25 23:28:35 +0000763/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000764/* Chapter 8.3.1 */
Harald Welte8470bf22008-12-25 23:28:35 +0000765int rsl_data_request(struct msgb *msg, u_int8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000766{
Harald Welte8470bf22008-12-25 23:28:35 +0000767 u_int8_t l3_len = msg->tail - (u_int8_t *)msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000768 struct abis_rsl_rll_hdr *rh;
769
Harald Welte8470bf22008-12-25 23:28:35 +0000770 if (msg->lchan == NULL) {
771 fprintf(stderr, "cannot send DATA REQUEST to unknown lchan\n");
772 return -EINVAL;
773 }
Harald Welte52b1f982008-12-23 20:25:15 +0000774
Harald Welte8470bf22008-12-25 23:28:35 +0000775 /* First push the L3 IE tag and length */
Harald Welte4b634542008-12-27 01:55:51 +0000776 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
Harald Welte8470bf22008-12-25 23:28:35 +0000777
778 /* Then push the RSL header */
Harald Welte52b1f982008-12-23 20:25:15 +0000779 rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh));
780 init_llm_hdr(rh, RSL_MT_DATA_REQ);
Harald Welte4a543e82009-02-28 13:17:55 +0000781 rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
Harald Welte8470bf22008-12-25 23:28:35 +0000782 rh->chan_nr = lchan2chan_nr(msg->lchan);
783 rh->link_id = link_id;
Harald Welte52b1f982008-12-23 20:25:15 +0000784
Harald Welte8470bf22008-12-25 23:28:35 +0000785 msg->trx = msg->lchan->ts->trx;
786
787 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000788}
789
Harald Welteedcc5272009-08-09 13:47:35 +0200790/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
791/* Chapter 8.3.1 */
792int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id)
793{
794 struct msgb *msg = rsl_msgb_alloc();
795 struct abis_rsl_rll_hdr *rh;
796
797 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
Harald Welte1c409272009-08-09 14:13:58 +0200798 init_llm_hdr(rh, RSL_MT_EST_REQ);
Harald Welteedcc5272009-08-09 13:47:35 +0200799 //rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
800 rh->chan_nr = lchan2chan_nr(lchan);
801 rh->link_id = link_id;
802
803 msg->trx = lchan->ts->trx;
804
805 return abis_rsl_sendmsg(msg);
806}
807
Harald Welted2dc1de2009-08-08 13:15:07 +0200808/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
809 This is what higher layers should call. The BTS then responds with
810 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
811 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
812 lchan_free() */
813int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id)
814{
815 struct msgb *msg = rsl_msgb_alloc();
816 struct abis_rsl_rll_hdr *rh;
817
818 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
819 init_llm_hdr(rh, RSL_MT_REL_REQ);
820 //rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
821 rh->chan_nr = lchan2chan_nr(lchan);
822 rh->link_id = link_id;
Harald Welte6c3d2ed2009-08-10 00:19:36 +0200823 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, 0); /* normal release */
Harald Welted2dc1de2009-08-08 13:15:07 +0200824
825 msg->trx = lchan->ts->trx;
826
827 return abis_rsl_sendmsg(msg);
828}
829
Harald Welte702d8702008-12-26 20:25:35 +0000830/* Chapter 8.4.2: Channel Activate Acknowledge */
831static int rsl_rx_chan_act_ack(struct msgb *msg)
832{
833 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
834
835 /* BTS has confirmed channel activation, we now need
836 * to assign the activated channel to the MS */
Harald Welte4b634542008-12-27 01:55:51 +0000837 if (rslh->ie_chan != RSL_IE_CHAN_NR)
838 return -EINVAL;
839
Harald Welte4b634542008-12-27 01:55:51 +0000840 return 0;
841}
Harald Welte702d8702008-12-26 20:25:35 +0000842
Harald Welte4b634542008-12-27 01:55:51 +0000843/* Chapter 8.4.3: Channel Activate NACK */
844static int rsl_rx_chan_act_nack(struct msgb *msg)
845{
Harald Welte6dab0552009-05-01 17:21:37 +0000846 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
847 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +0000848
Harald Welte6dab0552009-05-01 17:21:37 +0000849 /* BTS has rejected channel activation ?!? */
850 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +0000851 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +0000852
853 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
854 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte8830e072009-07-28 17:58:09 +0200855 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
856 TLVP_LEN(&tp, RSL_IE_CAUSE));
857
Harald Welte3073a9f2009-08-09 19:50:08 +0200858 lchan_free(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000859 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000860}
861
Harald Welte7f93cea2009-02-23 00:02:59 +0000862/* Chapter 8.4.4: Connection Failure Indication */
863static int rsl_rx_conn_fail(struct msgb *msg)
864{
865 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
866 struct tlv_parsed tp;
867
868 DEBUGPC(DRSL, "CONNECTION FAIL: ");
Harald Welte7f93cea2009-02-23 00:02:59 +0000869
870 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
871
Harald Welte8830e072009-07-28 17:58:09 +0200872 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
873 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
874 TLVP_LEN(&tp, RSL_IE_CAUSE));
875
Harald Welte7f93cea2009-02-23 00:02:59 +0000876 if (msg->trx->bts->type == GSM_BTS_TYPE_BS11) {
877 /* FIXME: we have no idea what cause 0x18 is !!! */
878 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE) &&
879 TLVP_LEN(&tp, RSL_IE_CAUSE) >= 1 &&
880 *TLVP_VAL(&tp, RSL_IE_CAUSE) == 0x18) {
Harald Welte73be3aa2009-07-04 10:05:51 +0200881 DEBUGPC(DRSL, "Cause 0x18 IGNORING\n");
882 return 0;
Harald Welte7f93cea2009-02-23 00:02:59 +0000883 }
884 }
885
Holger Freytherf7b2a0e2009-06-02 02:55:17 +0000886 DEBUGPC(DRSL, "RELEASING.\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000887
888 /* FIXME: only free it after channel release ACK */
Harald Welte115d1032009-08-10 11:43:22 +0200889 return rsl_rf_chan_release(msg->lchan);
Harald Welte7f93cea2009-02-23 00:02:59 +0000890}
891
Harald Welte440fed02009-05-01 18:43:47 +0000892static int rsl_rx_meas_res(struct msgb *msg)
893{
894 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
895 struct tlv_parsed tp;
896
Harald Welte10d0e672009-06-27 02:53:10 +0200897 DEBUGPC(DMEAS, "MEASUREMENT RESULT ");
Harald Welte440fed02009-05-01 18:43:47 +0000898 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
899
900 if (TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR))
Harald Welte10d0e672009-06-27 02:53:10 +0200901 DEBUGPC(DMEAS, "NR=%d ", *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR));
Harald Welte440fed02009-05-01 18:43:47 +0000902 if (TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS)) {
903 u_int8_t len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte75d34a82009-05-23 06:11:13 +0000904 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte440fed02009-05-01 18:43:47 +0000905 if (len >= 3) {
906 if (val[0] & 0x40)
Harald Welte10d0e672009-06-27 02:53:10 +0200907 DEBUGPC(DMEAS, "DTXd ");
908 DEBUGPC(DMEAS, "RXL-FULL-up=%d RXL-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000909 val[0] & 0x3f, val[1] & 0x3f);
Harald Welte10d0e672009-06-27 02:53:10 +0200910 DEBUGPC(DMEAS, "RXQ-FULL-up=%d RXQ-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000911 val[2]>>3 & 0x7, val[2] & 0x7);
912 }
913 }
914 if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
Harald Welte10d0e672009-06-27 02:53:10 +0200915 DEBUGPC(DMEAS, "BS_POWER=%d ", *TLVP_VAL(&tp, RSL_IE_BS_POWER));
Harald Welte440fed02009-05-01 18:43:47 +0000916 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welte10d0e672009-06-27 02:53:10 +0200917 DEBUGPC(DMEAS, "MS_TO=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000918 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET));
Harald Weltefe9af262009-06-20 18:44:35 +0200919 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Harald Welte86c162d2009-07-12 09:45:05 +0200920 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltefe9af262009-06-20 18:44:35 +0200921 u_int8_t pwr_lvl = val[0] >> 3;
Harald Welte10d0e672009-06-27 02:53:10 +0200922 DEBUGPC(DMEAS, "L1_MS_PWR=%ddBm ",
Harald Weltefe9af262009-06-20 18:44:35 +0200923 ms_pwr_dbm(msg->trx->bts->band, pwr_lvl));
Harald Welte10d0e672009-06-27 02:53:10 +0200924 DEBUGPC(DMEAS, "L1_FPC=%u ", val[0] & 0x04 ? 1 : 0);
925 DEBUGPC(DMEAS, "L1_TA=%u ", val[1]);
Harald Weltefe9af262009-06-20 18:44:35 +0200926 }
Harald Weltef7c43522009-06-09 20:24:21 +0000927 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Harald Welte10d0e672009-06-27 02:53:10 +0200928 DEBUGPC(DMEAS, "L3\n");
Harald Weltef7c43522009-06-09 20:24:21 +0000929 msg->l3h = TLVP_VAL(&tp, RSL_IE_L3_INFO);
930 return gsm0408_rcvmsg(msg);
931 } else
Harald Welte10d0e672009-06-27 02:53:10 +0200932 DEBUGPC(DMEAS, "\n");
Harald Welte60d68f12009-06-05 20:07:43 +0000933
Harald Welte75d34a82009-05-23 06:11:13 +0000934 return 0;
Harald Welte440fed02009-05-01 18:43:47 +0000935}
936
Harald Welte52b1f982008-12-23 20:25:15 +0000937static int abis_rsl_rx_dchan(struct msgb *msg)
938{
Harald Welte8470bf22008-12-25 23:28:35 +0000939 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
940 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +0000941 char *ts_name;
Harald Welte52b1f982008-12-23 20:25:15 +0000942
Harald Welte8470bf22008-12-25 23:28:35 +0000943 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +0000944 ts_name = gsm_ts_name(msg->lchan->ts);
945
Harald Welte10d0e672009-06-27 02:53:10 +0200946 if (rslh->c.msg_type != RSL_MT_MEAS_RES)
947 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ", ts_name, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +0000948
949 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +0000950 case RSL_MT_CHAN_ACTIV_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000951 DEBUGPC(DRSL, "CHANNEL ACTIVATE ACK\n");
Harald Welte4b634542008-12-27 01:55:51 +0000952 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000953 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000954 case RSL_MT_CHAN_ACTIV_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000955 DEBUGPC(DRSL, "CHANNEL ACTIVATE NACK\n");
Harald Welte4b634542008-12-27 01:55:51 +0000956 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000957 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000958 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +0000959 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000960 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000961 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +0000962 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +0000963 break;
964 case RSL_MT_RF_CHAN_REL_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000965 DEBUGPC(DRSL, "RF CHANNEL RELEASE ACK\n");
Harald Welte2d5b6382008-12-27 19:46:06 +0000966 lchan_free(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +0000967 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000968 case RSL_MT_MODE_MODIFY_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000969 DEBUGPC(DRSL, "CHANNEL MODE MODIFY ACK\n");
Harald Welteda783762009-02-18 03:29:53 +0000970 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000971 case RSL_MT_MODE_MODIFY_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000972 DEBUGPC(DRSL, "CHANNEL MODE MODIFY NACK\n");
Harald Welteda783762009-02-18 03:29:53 +0000973 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000974 case RSL_MT_PHY_CONTEXT_CONF:
975 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +0000976 case RSL_MT_TALKER_DET:
977 case RSL_MT_LISTENER_DET:
978 case RSL_MT_REMOTE_CODEC_CONF_REP:
979 case RSL_MT_MR_CODEC_MOD_ACK:
980 case RSL_MT_MR_CODEC_MOD_NACK:
981 case RSL_MT_MR_CODEC_MOD_PER:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000982 DEBUGPC(DRSL, "Unimplemented Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000983 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +0000984 break;
985 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000986 DEBUGPC(DRSL, "unknown Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000987 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +0000988 return -EINVAL;
989 }
Harald Weltef325eb42009-02-19 17:07:39 +0000990
Harald Welte8470bf22008-12-25 23:28:35 +0000991 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000992}
993
Harald Welte702d8702008-12-26 20:25:35 +0000994static int rsl_rx_error_rep(struct msgb *msg)
995{
996 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +0200997 struct tlv_parsed tp;
Harald Welte702d8702008-12-26 20:25:35 +0000998
Harald Welte7f93cea2009-02-23 00:02:59 +0000999 DEBUGP(DRSL, "ERROR REPORT ");
Harald Welte8830e072009-07-28 17:58:09 +02001000
1001 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1002
1003 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
1004 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
1005 TLVP_LEN(&tp, RSL_IE_CAUSE));
1006
Holger Freyther79f4ae62009-06-02 03:25:04 +00001007 DEBUGPC(DRSL, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001008
1009 return 0;
1010}
1011
Harald Welte52b1f982008-12-23 20:25:15 +00001012static int abis_rsl_rx_trx(struct msgb *msg)
1013{
Harald Welte702d8702008-12-26 20:25:35 +00001014 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001015 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001016
1017 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001018 case RSL_MT_ERROR_REPORT:
1019 rc = rsl_rx_error_rep(msg);
1020 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001021 case RSL_MT_RF_RES_IND:
1022 /* interference on idle channels of TRX */
Harald Welte3cf7c3f2009-05-01 18:28:00 +00001023 //DEBUGP(DRSL, "TRX: RF Interference Indication\n");
Harald Welte8f5e2392009-02-03 12:57:37 +00001024 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001025 case RSL_MT_OVERLOAD:
1026 /* indicate CCCH / ACCH / processor overload */
Harald Weltef325eb42009-02-19 17:07:39 +00001027 DEBUGP(DRSL, "TRX: CCCH/ACCH/CPU Overload\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001028 break;
1029 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001030 DEBUGP(DRSL, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001031 rslh->msg_type);
1032 return -EINVAL;
1033 }
Harald Welte8470bf22008-12-25 23:28:35 +00001034 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001035}
1036
Harald Welteb7e81162009-08-10 00:26:10 +02001037/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1038static void t3101_expired(void *data)
1039{
1040 struct gsm_lchan *lchan = data;
1041
Harald Welte115d1032009-08-10 11:43:22 +02001042 rsl_rf_chan_release(lchan);
Harald Welteb7e81162009-08-10 00:26:10 +02001043}
1044
Harald Welte8470bf22008-12-25 23:28:35 +00001045/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001046static int rsl_rx_chan_rqd(struct msgb *msg)
1047{
Harald Welte702d8702008-12-26 20:25:35 +00001048 struct gsm_bts *bts = msg->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001049 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1050 struct gsm48_req_ref *rqd_ref;
Harald Welte52b1f982008-12-23 20:25:15 +00001051 struct gsm48_imm_ass ia;
Harald Welte8470bf22008-12-25 23:28:35 +00001052 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001053 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001054 struct gsm_lchan *lchan;
1055 u_int8_t rqd_ta;
Holger Freyther3186bf22008-12-29 06:23:49 +00001056 int ret;
Harald Welte8470bf22008-12-25 23:28:35 +00001057
Harald Welte52b1f982008-12-23 20:25:15 +00001058 u_int16_t arfcn;
1059 u_int8_t ts_number, subch;
1060
Harald Welte8470bf22008-12-25 23:28:35 +00001061 /* parse request reference to be used in immediate assign */
1062 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1063 return -EINVAL;
1064
1065 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1066
1067 /* parse access delay and use as TA */
1068 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1069 return -EINVAL;
1070 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1071
1072 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1073 * request reference RA */
1074 lctype = get_ctype_by_chreq(bts, rqd_ref->ra);
Harald Welte2cbe0922008-12-29 04:09:31 +00001075 chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra);
1076
Harald Welte8470bf22008-12-25 23:28:35 +00001077 /* check availability / allocate channel */
1078 lchan = lchan_alloc(bts, lctype);
1079 if (!lchan) {
1080 fprintf(stderr, "CHAN RQD: no resources\n");
1081 /* FIXME: send some kind of reject ?!? */
1082 return -ENOMEM;
1083 }
1084
1085 ts_number = lchan->ts->nr;
1086 arfcn = lchan->ts->trx->arfcn;
1087 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001088
Harald Welte66b6a8d2009-08-09 14:45:18 +02001089 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, 20 /* dBm == 100mW */);
Harald Welte0b2124b2009-08-10 00:45:40 +02001090 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte9943c5b2009-07-29 15:41:29 +02001091 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
1092 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
Harald Welte52b1f982008-12-23 20:25:15 +00001093
1094 /* create IMMEDIATE ASSIGN 04.08 messge */
1095 memset(&ia, 0, sizeof(ia));
1096 ia.l2_plen = 0x2d;
1097 ia.proto_discr = GSM48_PDISC_RR;
1098 ia.msg_type = GSM48_MT_RR_IMM_ASS;
Harald Welte2d5b6382008-12-27 19:46:06 +00001099 ia.page_mode = GSM48_PM_SAME;
Harald Welte4b634542008-12-27 01:55:51 +00001100 ia.chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +00001101 ia.chan_desc.h0.h = 0;
1102 ia.chan_desc.h0.arfcn_high = arfcn >> 8;
1103 ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
Harald Welte814c4b72009-07-21 20:55:56 +02001104 ia.chan_desc.h0.tsc = bts->tsc;
Harald Welte8470bf22008-12-25 23:28:35 +00001105 /* use request reference extracted from CHAN_RQD */
1106 memcpy(&ia.req_ref, rqd_ref, sizeof(ia.req_ref));
1107 ia.timing_advance = rqd_ta;
Harald Welte52b1f982008-12-23 20:25:15 +00001108 ia.mob_alloc_len = 0;
1109
Harald Welte8f5e2392009-02-03 12:57:37 +00001110 DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %s "
Holger Freyther79f4ae62009-06-02 03:25:04 +00001111 "chan_nr=0x%02x r=%s ra=0x%02x\n",
Harald Welteca64da92009-01-04 16:54:12 +00001112 arfcn, ts_number, subch, gsm_lchan_name(lchan->type),
Harald Welte4a543e82009-02-28 13:17:55 +00001113 ia.chan_desc.chan_nr, gsm_chreq_name(chreq_reason),
1114 rqd_ref->ra);
Harald Welte75a983f2008-12-27 21:34:06 +00001115
Harald Welteb7e81162009-08-10 00:26:10 +02001116 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1117 lchan->T3101.cb = t3101_expired;
1118 lchan->T3101.data = lchan;
1119 bsc_schedule_timer(&lchan->T3101, 10, 0);
Holger Freyther3186bf22008-12-29 06:23:49 +00001120
Harald Welte52b1f982008-12-23 20:25:15 +00001121 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Freyther3186bf22008-12-29 06:23:49 +00001122 ret = rsl_imm_assign_cmd(bts, sizeof(ia), (u_int8_t *) &ia);
1123
Harald Welte817f3c82008-12-30 14:57:59 +00001124 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001125}
1126
Harald Welteea280442009-02-02 22:29:56 +00001127/* MS has requested a channel on the RACH */
1128static int rsl_rx_ccch_load(struct msgb *msg)
1129{
1130 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1131 u_int16_t pg_buf_space;
Holger Freyther8c563cf2009-02-03 20:08:51 +00001132 u_int16_t rach_slot_count = -1;
1133 u_int16_t rach_busy_count = -1;
1134 u_int16_t rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001135
1136 switch (rslh->data[0]) {
1137 case RSL_IE_PAGING_LOAD:
1138 pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
Holger Freyther392209c2009-02-10 00:06:19 +00001139 paging_update_buffer_space(msg->trx->bts, pg_buf_space);
Harald Welteea280442009-02-02 22:29:56 +00001140 break;
1141 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001142 if (msg->data_len >= 7) {
1143 rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1144 rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1145 rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1146 }
Harald Welteea280442009-02-02 22:29:56 +00001147 break;
1148 default:
1149 break;
1150 }
1151
1152 return 0;
1153}
1154
Harald Welte52b1f982008-12-23 20:25:15 +00001155static int abis_rsl_rx_cchan(struct msgb *msg)
1156{
Harald Welteea280442009-02-02 22:29:56 +00001157 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001158 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001159
Harald Welte8470bf22008-12-25 23:28:35 +00001160 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
1161
1162 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001163 case RSL_MT_CHAN_RQD:
1164 /* MS has requested a channel on the RACH */
1165 rc = rsl_rx_chan_rqd(msg);
1166 break;
Harald Welteea280442009-02-02 22:29:56 +00001167 case RSL_MT_CCCH_LOAD_IND:
1168 /* current load on the CCCH */
1169 rc = rsl_rx_ccch_load(msg);
1170 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001171 case RSL_MT_DELETE_IND:
1172 /* CCCH overloaded, IMM_ASSIGN was dropped */
1173 case RSL_MT_CBCH_LOAD_IND:
1174 /* current load on the CBCH */
Harald Welte8f5e2392009-02-03 12:57:37 +00001175 fprintf(stderr, "Unimplemented Abis RSL TRX message type "
1176 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001177 break;
1178 default:
1179 fprintf(stderr, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001180 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001181 return -EINVAL;
1182 }
Harald Welte8470bf22008-12-25 23:28:35 +00001183
1184 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001185}
1186
Harald Welte4b634542008-12-27 01:55:51 +00001187static int rsl_rx_rll_err_ind(struct msgb *msg)
1188{
1189 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1190 u_int8_t *rlm_cause = rllh->data;
1191
Harald Welte602f2b82009-08-04 02:50:21 +02001192 DEBUGPC(DRLL, "ERROR INDICATION cause=0x%02x\n", rlm_cause[1]);
Harald Welteedcc5272009-08-09 13:47:35 +02001193
1194 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte4b634542008-12-27 01:55:51 +00001195
Harald Welte81543bc2009-07-04 09:40:05 +02001196 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED)
Harald Welte115d1032009-08-10 11:43:22 +02001197 return rsl_rf_chan_release(msg->lchan);
Harald Welte81543bc2009-07-04 09:40:05 +02001198
Harald Welte4b634542008-12-27 01:55:51 +00001199 return 0;
1200}
Harald Weltef325eb42009-02-19 17:07:39 +00001201
Harald Welte52b1f982008-12-23 20:25:15 +00001202/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
1203 0x02, 0x06,
1204 0x01, 0x20,
1205 0x02, 0x00,
1206 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1207
1208static int abis_rsl_rx_rll(struct msgb *msg)
1209{
1210 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001211 int rc = 0;
1212 char *ts_name;
Harald Welte8470bf22008-12-25 23:28:35 +00001213
1214 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001215 ts_name = gsm_ts_name(msg->lchan->ts);
1216 DEBUGP(DRLL, "channel=%s chan_nr=0x%02x ", ts_name, rllh->chan_nr);
Harald Welte52b1f982008-12-23 20:25:15 +00001217
1218 switch (rllh->c.msg_type) {
1219 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001220 DEBUGPC(DRLL, "DATA INDICATION\n");
Harald Welte4a543e82009-02-28 13:17:55 +00001221 if (msgb_l2len(msg) >
1222 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1223 rllh->data[0] == RSL_IE_L3_INFO) {
1224 msg->l3h = &rllh->data[3];
1225 return gsm0408_rcvmsg(msg);
1226 }
Harald Welte52b1f982008-12-23 20:25:15 +00001227 break;
1228 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001229 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welteb7e81162009-08-10 00:26:10 +02001230 /* lchan is established, stop T3101 */
1231 bsc_del_timer(&msg->lchan->T3101);
Harald Welte4a543e82009-02-28 13:17:55 +00001232 if (msgb_l2len(msg) >
1233 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1234 rllh->data[0] == RSL_IE_L3_INFO) {
1235 msg->l3h = &rllh->data[3];
1236 return gsm0408_rcvmsg(msg);
1237 }
Harald Welte52b1f982008-12-23 20:25:15 +00001238 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001239 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001240 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Harald Welteedcc5272009-08-09 13:47:35 +02001241 rll_indication(msg->lchan, rllh->link_id,
1242 BSC_RLLR_IND_EST_CONF);
1243 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001244 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001245 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001246 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Harald Welteedcc5272009-08-09 13:47:35 +02001247 rll_indication(msg->lchan, rllh->link_id,
1248 BSC_RLLR_IND_REL_IND);
Harald Welted2dc1de2009-08-08 13:15:07 +02001249 /* we can now releae the channel on the BTS/Abis side */
Harald Welte115d1032009-08-10 11:43:22 +02001250 /* FIXME: officially we need to start T3111 and wait for
1251 * some grace period */
1252 rsl_rf_chan_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001253 break;
1254 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001255 /* BTS informs us of having received UA from MS,
1256 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001257 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Harald Welted2dc1de2009-08-08 13:15:07 +02001258 /* we can now releae the channel on the BTS/Abis side */
Harald Welte115d1032009-08-10 11:43:22 +02001259 /* FIXME: officially we need to start T3111 and wait for
1260 * some grace period */
1261 rsl_rf_chan_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001262 break;
1263 case RSL_MT_ERROR_IND:
1264 rc = rsl_rx_rll_err_ind(msg);
1265 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001266 case RSL_MT_UNIT_DATA_IND:
Harald Welte602f2b82009-08-04 02:50:21 +02001267 DEBUGPC(DRLL, "unimplemented Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001268 rllh->c.msg_type);
1269 break;
1270 default:
Harald Welte602f2b82009-08-04 02:50:21 +02001271 DEBUGPC(DRLL, "unknown Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001272 rllh->c.msg_type);
1273 }
Harald Welte8470bf22008-12-25 23:28:35 +00001274 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001275}
1276
Harald Weltef4e79f22009-07-28 18:11:56 +02001277static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
1278{
Harald Weltef4e79f22009-07-28 18:11:56 +02001279 switch (tch_mode) {
1280 case GSM48_CMODE_SPEECH_V1:
1281 return 0x00;
1282 case GSM48_CMODE_SPEECH_EFR:
1283 return 0x01;
1284 case GSM48_CMODE_SPEECH_AMR:
1285 return 0x02;
1286 /* FIXME: Type1 half-rate and type3 half-rate */
1287 }
Harald Welte58ca5b72009-07-29 12:12:18 +02001288 DEBUGPC(DRSL, "Cannot determine ip.access speech mode for "
1289 "tch_mode == 0x%02x\n", tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001290 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001291}
1292
Harald Welte75099262009-02-16 21:12:08 +00001293/* ip.access specific RSL extensions */
1294int rsl_ipacc_bind(struct gsm_lchan *lchan)
1295{
1296 struct msgb *msg = rsl_msgb_alloc();
1297 struct abis_rsl_dchan_hdr *dh;
Harald Welte58ca5b72009-07-29 12:12:18 +02001298 u_int8_t speech_mode;
Harald Welte75099262009-02-16 21:12:08 +00001299
1300 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1301 init_dchan_hdr(dh, RSL_MT_IPAC_BIND);
1302 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1303 dh->chan_nr = lchan2chan_nr(lchan);
1304
Harald Weltef4e79f22009-07-28 18:11:56 +02001305 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte58ca5b72009-07-29 12:12:18 +02001306 speech_mode = 0x10 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1307 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001308
Harald Welte58ca5b72009-07-29 12:12:18 +02001309 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND "
1310 "speech_mode=0x%02x\n", gsm_ts_name(lchan->ts),
1311 dh->chan_nr, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001312
Harald Welte75099262009-02-16 21:12:08 +00001313 msg->trx = lchan->ts->trx;
1314
1315 return abis_rsl_sendmsg(msg);
1316}
1317
Harald Welte20855542009-07-12 09:50:35 +02001318int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
1319 u_int16_t conn_id, u_int8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001320{
1321 struct msgb *msg = rsl_msgb_alloc();
1322 struct abis_rsl_dchan_hdr *dh;
1323 u_int8_t *att_f8, *att_ip, *att_port;
Harald Welte58ca5b72009-07-29 12:12:18 +02001324 u_int8_t speech_mode;
Harald Weltef4e79f22009-07-28 18:11:56 +02001325 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001326
1327 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1328 init_dchan_hdr(dh, RSL_MT_IPAC_CONNECT);
1329 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1330 dh->chan_nr = lchan2chan_nr(lchan);
1331
Harald Welte58ca5b72009-07-29 12:12:18 +02001332 /* 0x0- == both directions, 0x-1 == EFR codec */
1333 speech_mode = 0x00 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1334
Harald Weltef4e79f22009-07-28 18:11:56 +02001335 ia.s_addr = htonl(ip);
Harald Welte58ca5b72009-07-29 12:12:18 +02001336 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_CONNECT "
1337 "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d speech_mode=0x%02x\n",
Harald Weltef4e79f22009-07-28 18:11:56 +02001338 gsm_ts_name(lchan->ts), dh->chan_nr,
Harald Welte58ca5b72009-07-29 12:12:18 +02001339 inet_ntoa(ia), port, rtp_payload2, conn_id, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001340
Harald Welte20855542009-07-12 09:50:35 +02001341 att_f8 = msgb_put(msg, sizeof(conn_id)+1);
Harald Welte86c162d2009-07-12 09:45:05 +02001342 att_f8[0] = RSL_IE_IPAC_CONN_ID;
Harald Welte20855542009-07-12 09:50:35 +02001343 att_f8[1] = conn_id >> 8;
1344 att_f8[2] = conn_id & 0xff;
Harald Welte75099262009-02-16 21:12:08 +00001345
1346 att_ip = msgb_put(msg, sizeof(ip)+1);
1347 att_ip[0] = RSL_IE_IPAC_REMOTE_IP;
1348 att_ip[1] = ip >> 24;
1349 att_ip[2] = ip >> 16;
1350 att_ip[3] = ip >> 8;
1351 att_ip[4] = ip & 0xff;
Harald Welteda783762009-02-18 03:29:53 +00001352 //att_ip[4] = 11;
Harald Welte75099262009-02-16 21:12:08 +00001353
1354 att_port = msgb_put(msg, sizeof(port)+1);
1355 att_port[0] = RSL_IE_IPAC_REMOTE_PORT;
1356 att_port[1] = port >> 8;
1357 att_port[2] = port & 0xff;
1358
Harald Welte58ca5b72009-07-29 12:12:18 +02001359 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001360 if (rtp_payload2)
1361 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
1362
Harald Welte75099262009-02-16 21:12:08 +00001363 msg->trx = lchan->ts->trx;
1364
1365 return abis_rsl_sendmsg(msg);
1366}
1367
1368static int abis_rsl_rx_ipacc_bindack(struct msgb *msg)
1369{
1370 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1371 struct tlv_parsed tv;
1372 struct gsm_bts_trx_ts *ts = msg->lchan->ts;
Harald Welte167df882009-02-17 14:35:45 +00001373 struct in_addr ip;
Harald Welte75099262009-02-16 21:12:08 +00001374 u_int16_t port, attr_f8;
1375
1376 /* the BTS has acknowledged a local bind, it now tells us the IP
1377 * address and port number to which it has bound the given logical
1378 * channel */
1379
1380 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1381 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1382 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02001383 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltef325eb42009-02-19 17:07:39 +00001384 DEBUGPC(DRSL, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001385 return -EINVAL;
1386 }
Harald Welte167df882009-02-17 14:35:45 +00001387 ip.s_addr = *((u_int32_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte75099262009-02-16 21:12:08 +00001388 port = *((u_int16_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_PORT));
1389 attr_f8 = *((u_int16_t *) TLVP_VAL(&tv, 0xf8));
1390
Harald Weltef4e79f22009-07-28 18:11:56 +02001391 DEBUGPC(DRSL, "IP=%s PORT=%d CONN_ID=%d ",
1392 inet_ntoa(ip), ntohs(port), ntohs(attr_f8));
1393
1394 if (TLVP_PRESENT(&tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1395 ts->abis_ip.rtp_payload2 =
1396 *TLVP_VAL(&tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1397 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1398 ts->abis_ip.rtp_payload2);
1399 }
Harald Welte167df882009-02-17 14:35:45 +00001400
Harald Welte75099262009-02-16 21:12:08 +00001401 /* update our local information about this TS */
Harald Welte167df882009-02-17 14:35:45 +00001402 ts->abis_ip.bound_ip = ntohl(ip.s_addr);
1403 ts->abis_ip.bound_port = ntohs(port);
Harald Welte20855542009-07-12 09:50:35 +02001404 ts->abis_ip.conn_id = ntohs(attr_f8);
Harald Welte75099262009-02-16 21:12:08 +00001405
Harald Welte167df882009-02-17 14:35:45 +00001406 dispatch_signal(SS_ABISIP, S_ABISIP_BIND_ACK, msg->lchan);
1407
Harald Welte75099262009-02-16 21:12:08 +00001408 return 0;
1409}
1410
1411static int abis_rsl_rx_ipacc_disc_ind(struct msgb *msg)
1412{
1413 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1414 struct tlv_parsed tv;
1415
1416 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00001417
Harald Welte8830e072009-07-28 17:58:09 +02001418 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
1419 print_rsl_cause(TLVP_VAL(&tv, RSL_IE_CAUSE),
1420 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001421
Harald Welte888b1142009-07-28 18:02:05 +02001422 dispatch_signal(SS_ABISIP, S_ABISIP_DISC_IND, msg->lchan);
1423
Harald Welte75099262009-02-16 21:12:08 +00001424 return 0;
1425}
1426
1427static int abis_rsl_rx_ipacc(struct msgb *msg)
1428{
1429 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1430 int rc = 0;
1431
1432 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001433 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ",
1434 gsm_ts_name(msg->lchan->ts), rllh->chan_nr);
Harald Welte75099262009-02-16 21:12:08 +00001435
1436 switch (rllh->c.msg_type) {
1437 case RSL_MT_IPAC_BIND_ACK:
Harald Welte4a543e82009-02-28 13:17:55 +00001438 DEBUGPC(DRSL, "IPAC_BIND_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001439 rc = abis_rsl_rx_ipacc_bindack(msg);
1440 break;
1441 case RSL_MT_IPAC_BIND_NACK:
1442 /* somehow the BTS was unable to bind the lchan to its local
1443 * port?!? */
Harald Weltef325eb42009-02-19 17:07:39 +00001444 DEBUGPC(DRSL, "IPAC_BIND_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001445 break;
1446 case RSL_MT_IPAC_CONNECT_ACK:
1447 /* the BTS tells us that a connect operation was successful */
Harald Weltef325eb42009-02-19 17:07:39 +00001448 DEBUGPC(DRSL, "IPAC_CONNECT_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001449 break;
1450 case RSL_MT_IPAC_CONNECT_NACK:
1451 /* somehow the BTS was unable to connect the lchan to a remote
1452 * port */
Harald Weltef325eb42009-02-19 17:07:39 +00001453 DEBUGPC(DRSL, "IPAC_CONNECT_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001454 break;
1455 case RSL_MT_IPAC_DISCONNECT_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001456 DEBUGPC(DRSL, "IPAC_DISCONNECT_IND ");
Harald Welte75099262009-02-16 21:12:08 +00001457 rc = abis_rsl_rx_ipacc_disc_ind(msg);
1458 break;
1459 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001460 DEBUGPC(DRSL, "Unknown ip.access msg_type 0x%02x", rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001461 break;
1462 }
Harald Welte6dab0552009-05-01 17:21:37 +00001463 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001464
1465 return rc;
1466}
1467
1468
Harald Welte52b1f982008-12-23 20:25:15 +00001469/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001470int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001471{
1472 struct abis_rsl_common_hdr *rslh = msgb_l2(msg) ;
Harald Welte8f5e2392009-02-03 12:57:37 +00001473 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001474
1475 switch (rslh->msg_discr & 0xfe) {
1476 case ABIS_RSL_MDISC_RLL:
1477 rc = abis_rsl_rx_rll(msg);
1478 break;
1479 case ABIS_RSL_MDISC_DED_CHAN:
1480 rc = abis_rsl_rx_dchan(msg);
1481 break;
1482 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00001483 rc = abis_rsl_rx_cchan(msg);
1484 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001485 case ABIS_RSL_MDISC_TRX:
1486 rc = abis_rsl_rx_trx(msg);
1487 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001488 case ABIS_RSL_MDISC_LOC:
Harald Welte8f5e2392009-02-03 12:57:37 +00001489 fprintf(stderr, "unimplemented RSL msg disc 0x%02x\n",
1490 rslh->msg_discr);
1491 break;
Harald Welte75099262009-02-16 21:12:08 +00001492 case ABIS_RSL_MDISC_IPACCESS:
1493 rc = abis_rsl_rx_ipacc(msg);
1494 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001495 default:
1496 fprintf(stderr, "unknown RSL message discriminator 0x%02x\n",
1497 rslh->msg_discr);
1498 return -EINVAL;
1499 }
Harald Welte4f4a3902008-12-26 00:04:49 +00001500 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001501 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001502}
Holger Freyther3b72a892009-02-04 00:31:39 +00001503
1504
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001505/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
Holger Freyther3b72a892009-02-04 00:31:39 +00001506int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf)
1507{
1508 switch (ccch_conf) {
1509 case RSL_BCCH_CCCH_CONF_1_NC:
1510 return 1;
1511 case RSL_BCCH_CCCH_CONF_1_C:
1512 return 1;
1513 case RSL_BCCH_CCCH_CONF_2_NC:
1514 return 2;
1515 case RSL_BCCH_CCCH_CONF_3_NC:
1516 return 3;
1517 case RSL_BCCH_CCCH_CONF_4_NC:
1518 return 4;
1519 default:
1520 return -1;
1521 }
1522}
1523
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001524/* Section 3.3.2.3 TS 05.02 */
Holger Freyther3b72a892009-02-04 00:31:39 +00001525int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf)
1526{
1527 switch (ccch_conf) {
1528 case RSL_BCCH_CCCH_CONF_1_NC:
1529 return 0;
1530 case RSL_BCCH_CCCH_CONF_1_C:
1531 return 1;
1532 case RSL_BCCH_CCCH_CONF_2_NC:
1533 return 0;
1534 case RSL_BCCH_CCCH_CONF_3_NC:
1535 return 0;
1536 case RSL_BCCH_CCCH_CONF_4_NC:
1537 return 0;
1538 default:
1539 return -1;
1540 }
1541}
1542
1543/* From Table 10.5.33 of GSM 04.08 */
1544int rsl_number_of_paging_subchannels(struct gsm_bts *bts)
1545{
1546 if (bts->chan_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) {
1547 return MAX(1, (3 - bts->chan_desc.bs_ag_blks_res))
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001548 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001549 } else {
1550 return (9 - bts->chan_desc.bs_ag_blks_res)
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001551 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001552 }
1553}