blob: 33da2ecdbb32c151c6ce6262fa467ba55f5dfee9 [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 Welteab46d742009-07-12 09:56:39 +0200108 [RSL_IE_IPAC_PROXY_UDP] = { TLV_TYPE_FIXED, 2 },
109 [RSL_IE_IPAC_BSCMPL_TOUT] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000110 [RSL_IE_IPAC_REMOTE_IP] = { TLV_TYPE_FIXED, 4 },
111 [RSL_IE_IPAC_REMOTE_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200112 [RSL_IE_IPAC_RTP_PAYLOAD] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000113 [RSL_IE_IPAC_LOCAL_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welte86c162d2009-07-12 09:45:05 +0200114 [RSL_IE_IPAC_SPEECH_MODE] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200115 [RSL_IE_IPAC_LOCAL_IP] = { TLV_TYPE_FIXED, 4 },
Harald Welte86c162d2009-07-12 09:45:05 +0200116 [RSL_IE_IPAC_CONN_ID] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200117 [RSL_IE_IPAC_RTP_CSD_FMT] = { TLV_TYPE_TV },
118 [RSL_IE_IPAC_RTP_JIT_BUF] = { TLV_TYPE_FIXED, 2 },
119 [RSL_IE_IPAC_RTP_COMPR] = { TLV_TYPE_TV },
Harald Welte86c162d2009-07-12 09:45:05 +0200120 [RSL_IE_IPAC_RTP_PAYLOAD2] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200121 [RSL_IE_IPAC_RTP_MPLEX] = { TLV_TYPE_FIXED, 8 },
122 [RSL_IE_IPAC_RTP_MPLEX_ID] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000123 },
124};
Harald Weltea4d49e92009-05-23 06:39:58 +0000125#define rsl_tlv_parse(dec, buf, len) \
126 tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
Harald Welte75099262009-02-16 21:12:08 +0000127
Harald Welte52b1f982008-12-23 20:25:15 +0000128static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
129{
130 /* mask off the transparent bit ? */
131 msg_type &= 0xfe;
132
Harald Welte8470bf22008-12-25 23:28:35 +0000133 if ((msg_type & 0xf0) == 0x00)
Harald Welte52b1f982008-12-23 20:25:15 +0000134 return ABIS_RSL_MDISC_RLL;
Harald Welte8470bf22008-12-25 23:28:35 +0000135 if ((msg_type & 0xf0) == 0x10) {
Harald Welte52b1f982008-12-23 20:25:15 +0000136 if (msg_type >= 0x19 && msg_type <= 0x22)
137 return ABIS_RSL_MDISC_TRX;
138 else
139 return ABIS_RSL_MDISC_COM_CHAN;
140 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000141 if ((msg_type & 0xe0) == 0x20)
Harald Welte52b1f982008-12-23 20:25:15 +0000142 return ABIS_RSL_MDISC_DED_CHAN;
143
144 return ABIS_RSL_MDISC_LOC;
145}
146
147static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
148 u_int8_t msg_type)
149{
150 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
151 dh->c.msg_type = msg_type;
152 dh->ie_chan = RSL_IE_CHAN_NR;
153}
154
155static inline void init_llm_hdr(struct abis_rsl_rll_hdr *dh,
156 u_int8_t msg_type)
157{
158 /* dh->c.msg_discr = mdisc_by_msgtype(msg_type); */
159 dh->c.msg_discr = ABIS_RSL_MDISC_RLL;
160 dh->c.msg_type = msg_type;
161 dh->ie_chan = RSL_IE_CHAN_NR;
162 dh->ie_link_id = RSL_IE_LINK_IDENT;
163}
164
165
166/* encode channel number as per Section 9.3.1 */
167u_int8_t rsl_enc_chan_nr(u_int8_t type, u_int8_t subch, u_int8_t timeslot)
168{
169 u_int8_t ret;
170
171 ret = (timeslot & 0x07) | type;
172
173 switch (type) {
174 case RSL_CHAN_Lm_ACCHs:
175 subch &= 0x01;
176 break;
177 case RSL_CHAN_SDCCH4_ACCH:
178 subch &= 0x07;
179 break;
180 case RSL_CHAN_SDCCH8_ACCH:
181 subch &= 0x07;
182 break;
183 default:
184 /* no subchannels allowed */
185 subch = 0x00;
186 break;
187 }
188 ret |= (subch << 3);
189
190 return ret;
191}
192
Harald Welte8470bf22008-12-25 23:28:35 +0000193/* determine logical channel based on TRX and channel number IE */
194struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
195{
196 struct gsm_lchan *lchan;
197 u_int8_t ts_nr = chan_nr & 0x07;
198 u_int8_t cbits = chan_nr >> 3;
199 u_int8_t lch_idx;
200 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
201
202 if (cbits == 0x01) {
203 lch_idx = 0; /* TCH/F */
204 if (ts->pchan != GSM_PCHAN_TCH_F)
205 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
206 chan_nr, ts->pchan);
207 } else if ((cbits & 0x1e) == 0x02) {
208 lch_idx = cbits & 0x1; /* TCH/H */
209 if (ts->pchan != GSM_PCHAN_TCH_H)
210 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
211 chan_nr, ts->pchan);
212 } else if ((cbits & 0x1c) == 0x04) {
213 lch_idx = cbits & 0x3; /* SDCCH/4 */
214 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
215 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
216 chan_nr, ts->pchan);
217 } else if ((cbits & 0x18) == 0x08) {
218 lch_idx = cbits & 0x7; /* SDCCH/8 */
219 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
220 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
221 chan_nr, ts->pchan);
222 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
223 lch_idx = 0;
224 if (ts->pchan != GSM_PCHAN_CCCH &&
225 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
226 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
227 chan_nr, ts->pchan);
228 /* FIXME: we should not return first sdcch4 !!! */
229 } else {
230 fprintf(stderr, "unknown chan_nr=0x%02x\n", chan_nr);
231 return NULL;
232 }
233
234 lchan = &ts->lchan[lch_idx];
235
236 return lchan;
237}
238
239u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
240{
241 struct gsm_bts_trx_ts *ts = lchan->ts;
242 u_int8_t cbits, chan_nr;
243
244 switch (ts->pchan) {
245 case GSM_PCHAN_TCH_F:
246 cbits = 0x01;
247 break;
248 case GSM_PCHAN_TCH_H:
249 cbits = 0x02;
250 cbits += lchan->nr;
251 break;
252 case GSM_PCHAN_CCCH_SDCCH4:
253 cbits = 0x04;
254 cbits += lchan->nr;
255 break;
256 case GSM_PCHAN_SDCCH8_SACCH8C:
257 cbits = 0x08;
258 cbits += lchan->nr;
259 break;
260 default:
261 case GSM_PCHAN_CCCH:
262 cbits = 0x10;
263 break;
264 }
265
266 chan_nr = (cbits << 3) | (ts->nr & 0x7);
267
268 return chan_nr;
269}
270
Harald Welte52b1f982008-12-23 20:25:15 +0000271/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
272u_int64_t str_to_imsi(const char *imsi_str)
273{
274 u_int64_t ret;
275
276 ret = strtoull(imsi_str, NULL, 10);
277
278 return ret;
279}
280
281/* Table 5 Clause 7 TS 05.02 */
282unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res)
283{
284 if (!bs_ccch_sdcch_comb)
285 return 9 - bs_ag_blks_res;
286 else
287 return 3 - bs_ag_blks_res;
288}
289
290/* Chapter 6.5.2 of TS 05.02 */
291unsigned int get_ccch_group(u_int64_t imsi, unsigned int bs_cc_chans,
292 unsigned int n_pag_blocks)
293{
294 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) / n_pag_blocks;
295}
296
297/* Chapter 6.5.2 of TS 05.02 */
298unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
299 int n_pag_blocks)
300{
301 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) % n_pag_blocks;
302}
303
Harald Welte8470bf22008-12-25 23:28:35 +0000304static struct msgb *rsl_msgb_alloc(void)
305{
Harald Welte966636f2009-06-26 19:39:35 +0200306 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
307 "RSL");
Harald Welte8470bf22008-12-25 23:28:35 +0000308}
309
Harald Welte362322e2009-02-15 14:36:38 +0000310#define MACBLOCK_SIZE 23
311static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
312{
313 memcpy(out, in, len);
314
315 if (len < MACBLOCK_SIZE)
316 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
317}
318
Harald Welte8830e072009-07-28 17:58:09 +0200319static const char *rsl_err_vals[0xff] = {
320 [RSL_ERR_RADIO_IF_FAIL] = "Radio Interface Failure",
321 [RSL_ERR_RADIO_LINK_FAIL] = "Radio Link Failure",
322 [RSL_ERR_HANDOVER_ACC_FAIL] = "Handover Access Failure",
323 [RSL_ERR_TALKER_ACC_FAIL] = "Talker Access Failure",
324 [RSL_ERR_OM_INTERVENTION] = "O&M Intervention",
325 [RSL_ERR_NORMAL_UNSPEC] = "Normal event, unspecified",
Harald Welte2da86292009-08-04 02:31:05 +0200326 [RSL_ERR_T_MSRFPCI_EXP] = "Siemens: T_MSRFPCI Expired",
Harald Welte8830e072009-07-28 17:58:09 +0200327 [RSL_ERR_EQUIPMENT_FAIL] = "Equipment Failure",
328 [RSL_ERR_RR_UNAVAIL] = "Radio Resource not available",
329 [RSL_ERR_TERR_CH_FAIL] = "Terrestrial Channel Failure",
330 [RSL_ERR_CCCH_OVERLOAD] = "CCCH Overload",
331 [RSL_ERR_ACCH_OVERLOAD] = "ACCH Overload",
332 [RSL_ERR_PROCESSOR_OVERLOAD] = "Processor Overload",
333 [RSL_ERR_RES_UNAVAIL] = "Resource not available, unspecified",
334 [RSL_ERR_TRANSC_UNAVAIL] = "Transcoding not available",
335 [RSL_ERR_SERV_OPT_UNAVAIL] = "Service or Option not available",
336 [RSL_ERR_ENCR_UNIMPL] = "Encryption algorithm not implemented",
337 [RSL_ERR_SERV_OPT_UNIMPL] = "Service or Option not implemented",
338 [RSL_ERR_RCH_ALR_ACTV_ALLOC] = "Radio channel already activated",
339 [RSL_ERR_INVALID_MESSAGE] = "Invalid Message, unspecified",
340 [RSL_ERR_MSG_DISCR] = "Message Discriminator Error",
341 [RSL_ERR_MSG_TYPE] = "Message Type Error",
342 [RSL_ERR_MSG_SEQ] = "Message Sequence Error",
343 [RSL_ERR_IE_ERROR] = "General IE error",
344 [RSL_ERR_MAND_IE_ERROR] = "Mandatory IE error",
345 [RSL_ERR_OPT_IE_ERROR] = "Optional IE error",
346 [RSL_ERR_IE_NONEXIST] = "IE non-existent",
347 [RSL_ERR_IE_LENGTH] = "IE length error",
348 [RSL_ERR_IE_CONTENT] = "IE content error",
349 [RSL_ERR_PROTO] = "Protocol error, unspecified",
350 [RSL_ERR_INTERWORKING] = "Interworking error, unspecified",
351};
352
353static const char *rsl_err_name(u_int8_t err)
Harald Welte7f93cea2009-02-23 00:02:59 +0000354{
Harald Welte8830e072009-07-28 17:58:09 +0200355 if (rsl_err_vals[err])
356 return rsl_err_vals[err];
357 else
358 return "unknown";
359}
360
361static void print_rsl_cause(const u_int8_t *cause_v, u_int8_t cause_len)
362{
Harald Welte7f93cea2009-02-23 00:02:59 +0000363 int i;
364
Harald Welte8830e072009-07-28 17:58:09 +0200365 DEBUGPC(DRSL, "CAUSE=0x%02x(%s) ",
366 cause_v[0], rsl_err_name(cause_v[0]));
367 for (i = 1; i < cause_len-1; i++)
368 DEBUGPC(DRSL, "%02x ", cause_v[i]);
Harald Welte7f93cea2009-02-23 00:02:59 +0000369}
370
Harald Welte52b1f982008-12-23 20:25:15 +0000371/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Harald Weltee79769b2009-02-07 00:48:17 +0000372int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000373 const u_int8_t *data, int len)
374{
375 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000376 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000377
378 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
379 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
380 dh->chan_nr = RSL_CHAN_BCCH;
381
382 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
383 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
384
Harald Weltee79769b2009-02-07 00:48:17 +0000385 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000386
387 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000388}
389
Harald Weltee79769b2009-02-07 00:48:17 +0000390int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000391 const u_int8_t *data, int len)
392{
393 struct abis_rsl_common_hdr *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000394 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000395
396 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
397 ch->msg_discr = ABIS_RSL_MDISC_TRX;
398 ch->msg_type = RSL_MT_SACCH_FILL;
399
400 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
Harald Welte702d8702008-12-26 20:25:35 +0000401 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
Harald Welte52b1f982008-12-23 20:25:15 +0000402
Harald Weltee79769b2009-02-07 00:48:17 +0000403 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000404
405 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000406}
407
Harald Weltefcd24452009-06-20 18:15:19 +0200408int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
409{
410 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200411 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200412 u_int8_t chan_nr = lchan2chan_nr(lchan);
413
414 db = abs(db);
415 if (db > 30)
416 return -EINVAL;
417
Harald Welteeab33352009-06-27 03:09:08 +0200418 msg = rsl_msgb_alloc();
419
Harald Weltefcd24452009-06-20 18:15:19 +0200420 lchan->bs_power = db/2;
421 if (fpc)
422 lchan->bs_power |= 0x10;
423
424 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
425 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
426 dh->chan_nr = chan_nr;
427
428 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
429
430 msg->trx = lchan->ts->trx;
431
432 return abis_rsl_sendmsg(msg);
433}
434
Harald Weltefcd24452009-06-20 18:15:19 +0200435int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
436{
437 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200438 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200439 u_int8_t chan_nr = lchan2chan_nr(lchan);
440 int ctl_lvl;
441
Harald Welte66b6a8d2009-08-09 14:45:18 +0200442 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm);
Harald Weltefcd24452009-06-20 18:15:19 +0200443 if (ctl_lvl < 0)
444 return ctl_lvl;
445
Harald Welteeab33352009-06-27 03:09:08 +0200446 msg = rsl_msgb_alloc();
447
Harald Weltefcd24452009-06-20 18:15:19 +0200448 lchan->ms_power = ctl_lvl;
449
450 if (fpc)
451 lchan->ms_power |= 0x20;
452
453 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
454 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
455 dh->chan_nr = chan_nr;
456
457 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
458
459 msg->trx = lchan->ts->trx;
460
461 return abis_rsl_sendmsg(msg);
462}
463
Harald Welte9943c5b2009-07-29 15:41:29 +0200464static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
465 struct gsm_lchan *lchan)
466{
467 memset(cm, 0, sizeof(cm));
468
469 /* FIXME: what to do with data calls ? */
470 cm->dtx_dtu = 0x00;
471
472 /* set TCH Speech/Data */
473 cm->spd_ind = lchan->rsl_cmode;
474
475 switch (lchan->type) {
476 case GSM_LCHAN_SDCCH:
477 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
478 break;
479 case GSM_LCHAN_TCH_F:
480 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
481 break;
482 case GSM_LCHAN_TCH_H:
483 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
484 break;
485 case GSM_LCHAN_NONE:
486 case GSM_LCHAN_UNKNOWN:
487 default:
488 return -EINVAL;
489 }
490
491 switch (lchan->tch_mode) {
492 case GSM48_CMODE_SIGN:
493 cm->chan_rate = 0;
494 break;
495 case GSM48_CMODE_SPEECH_V1:
496 cm->chan_rate = RSL_CMOD_SP_GSM1;
497 break;
498 case GSM48_CMODE_SPEECH_EFR:
499 cm->chan_rate = RSL_CMOD_SP_GSM2;
500 break;
501 case GSM48_CMODE_SPEECH_AMR:
502 cm->chan_rate = RSL_CMOD_SP_GSM3;
503 break;
504 case GSM48_CMODE_DATA_14k5:
505 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
506 break;
507 case GSM48_CMODE_DATA_12k0:
508 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
509 break;
510 case GSM48_CMODE_DATA_6k0:
511 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
512 break;
513 default:
514 return -EINVAL;
515 }
516
517 return 0;
518}
519
Harald Welte52b1f982008-12-23 20:25:15 +0000520/* Chapter 8.4.1 */
Harald Welteddab3c72009-02-28 13:19:15 +0000521#if 0
Harald Weltee79769b2009-02-07 00:48:17 +0000522int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
Harald Welte52b1f982008-12-23 20:25:15 +0000523 u_int8_t act_type,
524 struct rsl_ie_chan_mode *chan_mode,
525 struct rsl_ie_chan_ident *chan_ident,
526 u_int8_t bs_power, u_int8_t ms_power,
527 u_int8_t ta)
528{
529 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000530 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000531
532 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
533 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
534 dh->chan_nr = chan_nr;
535
536 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
537 /* For compatibility with Phase 1 */
538 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
539 (u_int8_t *) chan_mode);
540 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Harald Welte702d8702008-12-26 20:25:35 +0000541 (u_int8_t *) chan_ident);
Harald Welte702d8702008-12-26 20:25:35 +0000542#if 0
Harald Welte52b1f982008-12-23 20:25:15 +0000543 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
544 (u_int8_t *) &encr_info);
Harald Welte702d8702008-12-26 20:25:35 +0000545#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000546 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
Harald Welte52b1f982008-12-23 20:25:15 +0000547 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
548 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
549
Harald Weltee79769b2009-02-07 00:48:17 +0000550 msg->trx = trx;
551
Harald Welte8470bf22008-12-25 23:28:35 +0000552 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000553}
Harald Welteddab3c72009-02-28 13:19:15 +0000554#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000555
Harald Welte8f5e2392009-02-03 12:57:37 +0000556int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
Harald Welte9943c5b2009-07-29 15:41:29 +0200557 u_int8_t ta)
Harald Welte4b634542008-12-27 01:55:51 +0000558{
559 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200560 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200561 int rc;
Harald Welte4b634542008-12-27 01:55:51 +0000562
563 u_int8_t chan_nr = lchan2chan_nr(lchan);
564 u_int16_t arfcn = lchan->ts->trx->arfcn;
565 struct rsl_ie_chan_mode cm;
566 struct rsl_ie_chan_ident ci;
567
Harald Welte9943c5b2009-07-29 15:41:29 +0200568 rc = channel_mode_from_lchan(&cm, lchan);
569 if (rc < 0)
570 return rc;
Harald Welte4b634542008-12-27 01:55:51 +0000571
Harald Welte02b0e092009-02-28 13:11:07 +0000572 memset(&ci, 0, sizeof(ci));
Harald Welte4b634542008-12-27 01:55:51 +0000573 ci.chan_desc.iei = 0x64;
574 ci.chan_desc.chan_nr = chan_nr;
Harald Welte02b0e092009-02-28 13:11:07 +0000575 ci.chan_desc.oct3 = (lchan->ts->trx->bts->tsc << 5) | ((arfcn & 0x3ff) >> 8);
Harald Welte4b634542008-12-27 01:55:51 +0000576 ci.chan_desc.oct4 = arfcn & 0xff;
577
Harald Welteeab33352009-06-27 03:09:08 +0200578 msg = rsl_msgb_alloc();
Harald Welte4b634542008-12-27 01:55:51 +0000579 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
580 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
581 dh->chan_nr = chan_nr;
582
583 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
584 /* For compatibility with Phase 1 */
585 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
586 (u_int8_t *) &cm);
587 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
588 (u_int8_t *) &ci);
Harald Welte4b634542008-12-27 01:55:51 +0000589#if 0
590 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
591 (u_int8_t *) &encr_info);
Harald Welte4b634542008-12-27 01:55:51 +0000592#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000593 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
594 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
Harald Welte4b634542008-12-27 01:55:51 +0000595 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
596
Harald Weltee79769b2009-02-07 00:48:17 +0000597 msg->trx = lchan->ts->trx;
598
Harald Welte4b634542008-12-27 01:55:51 +0000599 return abis_rsl_sendmsg(msg);
600}
601
Harald Welte470abb72009-07-29 11:38:15 +0200602/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welteda783762009-02-18 03:29:53 +0000603int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
604{
605 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200606 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200607 int rc;
Harald Welteda783762009-02-18 03:29:53 +0000608
609 u_int8_t chan_nr = lchan2chan_nr(lchan);
610 struct rsl_ie_chan_mode cm;
611
Harald Welte9943c5b2009-07-29 15:41:29 +0200612 rc = channel_mode_from_lchan(&cm, lchan);
613 if (rc < 0)
614 return rc;
Harald Welteda783762009-02-18 03:29:53 +0000615
Harald Welteeab33352009-06-27 03:09:08 +0200616 msg = rsl_msgb_alloc();
Harald Welteda783762009-02-18 03:29:53 +0000617 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
618 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
619 dh->chan_nr = chan_nr;
620
621 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
622 (u_int8_t *) &cm);
623#if 0
624 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
625 (u_int8_t *) &encr_info);
626#endif
627
628 msg->trx = lchan->ts->trx;
629
630 return abis_rsl_sendmsg(msg);
631}
632
Harald Welteae0f2362009-07-19 18:36:49 +0200633/* Chapter 8.4.5 */
634int rsl_deact_sacch(struct gsm_lchan *lchan)
635{
636 struct abis_rsl_dchan_hdr *dh;
637 struct msgb *msg = rsl_msgb_alloc();
638
639 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
640 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
641 dh->chan_nr = lchan2chan_nr(lchan);
642
643 msg->lchan = lchan;
644 msg->trx = lchan->ts->trx;
645
646 DEBUGP(DRSL, "DEACTivate SACCH CMD channel=%s chan_nr=0x%02x\n",
647 gsm_ts_name(lchan->ts), dh->chan_nr);
648
649 return abis_rsl_sendmsg(msg);
650}
651
Holger Freyther36cbeff2008-12-30 19:15:20 +0000652/* Chapter 9.1.7 of 04.08 */
Harald Welte8470bf22008-12-25 23:28:35 +0000653int rsl_chan_release(struct gsm_lchan *lchan)
Harald Welte52b1f982008-12-23 20:25:15 +0000654{
655 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000656 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000657
658 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
659 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Welte8470bf22008-12-25 23:28:35 +0000660 dh->chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +0000661
Harald Welte8470bf22008-12-25 23:28:35 +0000662 msg->lchan = lchan;
663 msg->trx = lchan->ts->trx;
664
Harald Weltef325eb42009-02-19 17:07:39 +0000665 DEBUGP(DRSL, "Channel Release CMD channel=%s chan_nr=0x%02x\n",
666 gsm_ts_name(lchan->ts), dh->chan_nr);
Harald Welte2d5b6382008-12-27 19:46:06 +0000667
Harald Welte8470bf22008-12-25 23:28:35 +0000668 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000669}
670
671int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
672 u_int8_t *ms_ident, u_int8_t chan_needed)
673{
674 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000675 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000676
677 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
678 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
679 dh->chan_nr = RSL_CHAN_PCH_AGCH;
680
681 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
Harald Welte255539c2008-12-28 02:26:27 +0000682 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000683 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
684
Harald Welte8470bf22008-12-25 23:28:35 +0000685 msg->trx = bts->c0;
686
687 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000688}
689
Holger Freyther7448a532009-01-04 20:18:23 +0000690int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_need,
691 struct gsm_subscriber *subscr)
692{
Holger Freytherca362a62009-01-04 21:05:01 +0000693#if 0
Holger Freyther7448a532009-01-04 20:18:23 +0000694 u_int8_t mi[128];
695 unsigned int mi_len;
696 u_int8_t paging_group;
Holger Freytherca362a62009-01-04 21:05:01 +0000697#endif
Holger Freyther7448a532009-01-04 20:18:23 +0000698
699 return -1;
700}
701
Harald Welte52b1f982008-12-23 20:25:15 +0000702int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
703{
704 int i, len = strlen(str_in);
705
706 for (i = 0; i < len; i++) {
707 int num = str_in[i] - 0x30;
708 if (num < 0 || num > 9)
709 return -1;
710 if (i % 2 == 0)
711 bcd_out[i/2] = num;
712 else
713 bcd_out[i/2] |= (num << 4);
714 }
715
716 return 0;
717}
718
Harald Welte702d8702008-12-26 20:25:35 +0000719/* Chapter 8.5.6 */
Harald Welte52b1f982008-12-23 20:25:15 +0000720int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val)
721{
Harald Welte8470bf22008-12-25 23:28:35 +0000722 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000723 struct abis_rsl_dchan_hdr *dh;
Harald Welte362322e2009-02-15 14:36:38 +0000724 u_int8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000725
726 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
727 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
728 dh->chan_nr = RSL_CHAN_PCH_AGCH;
729
Harald Welte362322e2009-02-15 14:36:38 +0000730 switch (bts->type) {
731 case GSM_BTS_TYPE_BS11:
732 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
733 break;
734 default:
735 /* If phase 2, construct a FULL_IMM_ASS_INFO */
736 pad_macblock(buf, val, len);
737 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
738 break;
739 }
Harald Welte52b1f982008-12-23 20:25:15 +0000740
Harald Welte8470bf22008-12-25 23:28:35 +0000741 msg->trx = bts->c0;
742
743 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000744}
745
Harald Welte8470bf22008-12-25 23:28:35 +0000746/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000747/* Chapter 8.3.1 */
Harald Welte8470bf22008-12-25 23:28:35 +0000748int rsl_data_request(struct msgb *msg, u_int8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000749{
Harald Welte8470bf22008-12-25 23:28:35 +0000750 u_int8_t l3_len = msg->tail - (u_int8_t *)msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000751 struct abis_rsl_rll_hdr *rh;
752
Harald Welte8470bf22008-12-25 23:28:35 +0000753 if (msg->lchan == NULL) {
754 fprintf(stderr, "cannot send DATA REQUEST to unknown lchan\n");
755 return -EINVAL;
756 }
Harald Welte52b1f982008-12-23 20:25:15 +0000757
Harald Welte8470bf22008-12-25 23:28:35 +0000758 /* First push the L3 IE tag and length */
Harald Welte4b634542008-12-27 01:55:51 +0000759 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
Harald Welte8470bf22008-12-25 23:28:35 +0000760
761 /* Then push the RSL header */
Harald Welte52b1f982008-12-23 20:25:15 +0000762 rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh));
763 init_llm_hdr(rh, RSL_MT_DATA_REQ);
Harald Welte4a543e82009-02-28 13:17:55 +0000764 rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
Harald Welte8470bf22008-12-25 23:28:35 +0000765 rh->chan_nr = lchan2chan_nr(msg->lchan);
766 rh->link_id = link_id;
Harald Welte52b1f982008-12-23 20:25:15 +0000767
Harald Welte8470bf22008-12-25 23:28:35 +0000768 msg->trx = msg->lchan->ts->trx;
769
770 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000771}
772
Harald Welteedcc5272009-08-09 13:47:35 +0200773/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
774/* Chapter 8.3.1 */
775int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id)
776{
777 struct msgb *msg = rsl_msgb_alloc();
778 struct abis_rsl_rll_hdr *rh;
779
780 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
Harald Welte1c409272009-08-09 14:13:58 +0200781 init_llm_hdr(rh, RSL_MT_EST_REQ);
Harald Welteedcc5272009-08-09 13:47:35 +0200782 //rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
783 rh->chan_nr = lchan2chan_nr(lchan);
784 rh->link_id = link_id;
785
786 msg->trx = lchan->ts->trx;
787
788 return abis_rsl_sendmsg(msg);
789}
790
Harald Welted2dc1de2009-08-08 13:15:07 +0200791/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
792 This is what higher layers should call. The BTS then responds with
793 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
794 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
795 lchan_free() */
796int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id)
797{
798 struct msgb *msg = rsl_msgb_alloc();
799 struct abis_rsl_rll_hdr *rh;
800
801 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
802 init_llm_hdr(rh, RSL_MT_REL_REQ);
803 //rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
804 rh->chan_nr = lchan2chan_nr(lchan);
805 rh->link_id = link_id;
Harald Welte6c3d2ed2009-08-10 00:19:36 +0200806 msgb_tv_put(msg, RSL_IE_RELEASE_MODE, 0); /* normal release */
Harald Welted2dc1de2009-08-08 13:15:07 +0200807
808 msg->trx = lchan->ts->trx;
809
810 return abis_rsl_sendmsg(msg);
811}
812
Harald Welte702d8702008-12-26 20:25:35 +0000813/* Chapter 8.4.2: Channel Activate Acknowledge */
814static int rsl_rx_chan_act_ack(struct msgb *msg)
815{
816 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
817
818 /* BTS has confirmed channel activation, we now need
819 * to assign the activated channel to the MS */
Harald Welte4b634542008-12-27 01:55:51 +0000820 if (rslh->ie_chan != RSL_IE_CHAN_NR)
821 return -EINVAL;
822
Harald Welte4b634542008-12-27 01:55:51 +0000823 return 0;
824}
Harald Welte702d8702008-12-26 20:25:35 +0000825
Harald Welte4b634542008-12-27 01:55:51 +0000826/* Chapter 8.4.3: Channel Activate NACK */
827static int rsl_rx_chan_act_nack(struct msgb *msg)
828{
Harald Welte6dab0552009-05-01 17:21:37 +0000829 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
830 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +0000831
Harald Welte6dab0552009-05-01 17:21:37 +0000832 /* BTS has rejected channel activation ?!? */
833 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +0000834 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +0000835
836 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
837 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte8830e072009-07-28 17:58:09 +0200838 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
839 TLVP_LEN(&tp, RSL_IE_CAUSE));
840
Harald Welte3073a9f2009-08-09 19:50:08 +0200841 lchan_free(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +0000842 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000843}
844
Harald Welte7f93cea2009-02-23 00:02:59 +0000845/* Chapter 8.4.4: Connection Failure Indication */
846static int rsl_rx_conn_fail(struct msgb *msg)
847{
848 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
849 struct tlv_parsed tp;
850
851 DEBUGPC(DRSL, "CONNECTION FAIL: ");
Harald Welte7f93cea2009-02-23 00:02:59 +0000852
853 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
854
Harald Welte8830e072009-07-28 17:58:09 +0200855 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
856 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
857 TLVP_LEN(&tp, RSL_IE_CAUSE));
858
Harald Welte7f93cea2009-02-23 00:02:59 +0000859 if (msg->trx->bts->type == GSM_BTS_TYPE_BS11) {
860 /* FIXME: we have no idea what cause 0x18 is !!! */
861 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE) &&
862 TLVP_LEN(&tp, RSL_IE_CAUSE) >= 1 &&
863 *TLVP_VAL(&tp, RSL_IE_CAUSE) == 0x18) {
Harald Welte73be3aa2009-07-04 10:05:51 +0200864 DEBUGPC(DRSL, "Cause 0x18 IGNORING\n");
865 return 0;
Harald Welte7f93cea2009-02-23 00:02:59 +0000866 }
867 }
868
Holger Freytherf7b2a0e2009-06-02 02:55:17 +0000869 DEBUGPC(DRSL, "RELEASING.\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000870
871 /* FIXME: only free it after channel release ACK */
872 return rsl_chan_release(msg->lchan);
873}
874
Harald Welte440fed02009-05-01 18:43:47 +0000875static int rsl_rx_meas_res(struct msgb *msg)
876{
877 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
878 struct tlv_parsed tp;
879
Harald Welte10d0e672009-06-27 02:53:10 +0200880 DEBUGPC(DMEAS, "MEASUREMENT RESULT ");
Harald Welte440fed02009-05-01 18:43:47 +0000881 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
882
883 if (TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR))
Harald Welte10d0e672009-06-27 02:53:10 +0200884 DEBUGPC(DMEAS, "NR=%d ", *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR));
Harald Welte440fed02009-05-01 18:43:47 +0000885 if (TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS)) {
886 u_int8_t len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte75d34a82009-05-23 06:11:13 +0000887 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte440fed02009-05-01 18:43:47 +0000888 if (len >= 3) {
889 if (val[0] & 0x40)
Harald Welte10d0e672009-06-27 02:53:10 +0200890 DEBUGPC(DMEAS, "DTXd ");
891 DEBUGPC(DMEAS, "RXL-FULL-up=%d RXL-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000892 val[0] & 0x3f, val[1] & 0x3f);
Harald Welte10d0e672009-06-27 02:53:10 +0200893 DEBUGPC(DMEAS, "RXQ-FULL-up=%d RXQ-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000894 val[2]>>3 & 0x7, val[2] & 0x7);
895 }
896 }
897 if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
Harald Welte10d0e672009-06-27 02:53:10 +0200898 DEBUGPC(DMEAS, "BS_POWER=%d ", *TLVP_VAL(&tp, RSL_IE_BS_POWER));
Harald Welte440fed02009-05-01 18:43:47 +0000899 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welte10d0e672009-06-27 02:53:10 +0200900 DEBUGPC(DMEAS, "MS_TO=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000901 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET));
Harald Weltefe9af262009-06-20 18:44:35 +0200902 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Harald Welte86c162d2009-07-12 09:45:05 +0200903 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltefe9af262009-06-20 18:44:35 +0200904 u_int8_t pwr_lvl = val[0] >> 3;
Harald Welte10d0e672009-06-27 02:53:10 +0200905 DEBUGPC(DMEAS, "L1_MS_PWR=%ddBm ",
Harald Weltefe9af262009-06-20 18:44:35 +0200906 ms_pwr_dbm(msg->trx->bts->band, pwr_lvl));
Harald Welte10d0e672009-06-27 02:53:10 +0200907 DEBUGPC(DMEAS, "L1_FPC=%u ", val[0] & 0x04 ? 1 : 0);
908 DEBUGPC(DMEAS, "L1_TA=%u ", val[1]);
Harald Weltefe9af262009-06-20 18:44:35 +0200909 }
Harald Weltef7c43522009-06-09 20:24:21 +0000910 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Harald Welte10d0e672009-06-27 02:53:10 +0200911 DEBUGPC(DMEAS, "L3\n");
Harald Weltef7c43522009-06-09 20:24:21 +0000912 msg->l3h = TLVP_VAL(&tp, RSL_IE_L3_INFO);
913 return gsm0408_rcvmsg(msg);
914 } else
Harald Welte10d0e672009-06-27 02:53:10 +0200915 DEBUGPC(DMEAS, "\n");
Harald Welte60d68f12009-06-05 20:07:43 +0000916
Harald Welte75d34a82009-05-23 06:11:13 +0000917 return 0;
Harald Welte440fed02009-05-01 18:43:47 +0000918}
919
Harald Welte52b1f982008-12-23 20:25:15 +0000920static int abis_rsl_rx_dchan(struct msgb *msg)
921{
Harald Welte8470bf22008-12-25 23:28:35 +0000922 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
923 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +0000924 char *ts_name;
Harald Welte52b1f982008-12-23 20:25:15 +0000925
Harald Welte8470bf22008-12-25 23:28:35 +0000926 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +0000927 ts_name = gsm_ts_name(msg->lchan->ts);
928
Harald Welte10d0e672009-06-27 02:53:10 +0200929 if (rslh->c.msg_type != RSL_MT_MEAS_RES)
930 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ", ts_name, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +0000931
932 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +0000933 case RSL_MT_CHAN_ACTIV_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000934 DEBUGPC(DRSL, "CHANNEL ACTIVATE ACK\n");
Harald Welte4b634542008-12-27 01:55:51 +0000935 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000936 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000937 case RSL_MT_CHAN_ACTIV_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000938 DEBUGPC(DRSL, "CHANNEL ACTIVATE NACK\n");
Harald Welte4b634542008-12-27 01:55:51 +0000939 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000940 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000941 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +0000942 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000943 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000944 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +0000945 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +0000946 break;
947 case RSL_MT_RF_CHAN_REL_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000948 DEBUGPC(DRSL, "RF CHANNEL RELEASE ACK\n");
Harald Welte2d5b6382008-12-27 19:46:06 +0000949 lchan_free(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +0000950 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000951 case RSL_MT_MODE_MODIFY_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000952 DEBUGPC(DRSL, "CHANNEL MODE MODIFY ACK\n");
Harald Welteda783762009-02-18 03:29:53 +0000953 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000954 case RSL_MT_MODE_MODIFY_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000955 DEBUGPC(DRSL, "CHANNEL MODE MODIFY NACK\n");
Harald Welteda783762009-02-18 03:29:53 +0000956 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000957 case RSL_MT_PHY_CONTEXT_CONF:
958 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +0000959 case RSL_MT_TALKER_DET:
960 case RSL_MT_LISTENER_DET:
961 case RSL_MT_REMOTE_CODEC_CONF_REP:
962 case RSL_MT_MR_CODEC_MOD_ACK:
963 case RSL_MT_MR_CODEC_MOD_NACK:
964 case RSL_MT_MR_CODEC_MOD_PER:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000965 DEBUGPC(DRSL, "Unimplemented Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000966 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +0000967 break;
968 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000969 DEBUGPC(DRSL, "unknown Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +0000970 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +0000971 return -EINVAL;
972 }
Harald Weltef325eb42009-02-19 17:07:39 +0000973
Harald Welte8470bf22008-12-25 23:28:35 +0000974 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000975}
976
Harald Welte702d8702008-12-26 20:25:35 +0000977static int rsl_rx_error_rep(struct msgb *msg)
978{
979 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +0200980 struct tlv_parsed tp;
Harald Welte702d8702008-12-26 20:25:35 +0000981
Harald Welte7f93cea2009-02-23 00:02:59 +0000982 DEBUGP(DRSL, "ERROR REPORT ");
Harald Welte8830e072009-07-28 17:58:09 +0200983
984 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
985
986 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
987 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
988 TLVP_LEN(&tp, RSL_IE_CAUSE));
989
Holger Freyther79f4ae62009-06-02 03:25:04 +0000990 DEBUGPC(DRSL, "\n");
Harald Welte702d8702008-12-26 20:25:35 +0000991
992 return 0;
993}
994
Harald Welte52b1f982008-12-23 20:25:15 +0000995static int abis_rsl_rx_trx(struct msgb *msg)
996{
Harald Welte702d8702008-12-26 20:25:35 +0000997 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000998 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000999
1000 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001001 case RSL_MT_ERROR_REPORT:
1002 rc = rsl_rx_error_rep(msg);
1003 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001004 case RSL_MT_RF_RES_IND:
1005 /* interference on idle channels of TRX */
Harald Welte3cf7c3f2009-05-01 18:28:00 +00001006 //DEBUGP(DRSL, "TRX: RF Interference Indication\n");
Harald Welte8f5e2392009-02-03 12:57:37 +00001007 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001008 case RSL_MT_OVERLOAD:
1009 /* indicate CCCH / ACCH / processor overload */
Harald Weltef325eb42009-02-19 17:07:39 +00001010 DEBUGP(DRSL, "TRX: CCCH/ACCH/CPU Overload\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001011 break;
1012 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001013 DEBUGP(DRSL, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001014 rslh->msg_type);
1015 return -EINVAL;
1016 }
Harald Welte8470bf22008-12-25 23:28:35 +00001017 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001018}
1019
Harald Welteb7e81162009-08-10 00:26:10 +02001020/* If T3101 expires, we never received a response to IMMEDIATE ASSIGN */
1021static void t3101_expired(void *data)
1022{
1023 struct gsm_lchan *lchan = data;
1024
1025 rsl_chan_release(lchan);
1026}
1027
Harald Welte8470bf22008-12-25 23:28:35 +00001028/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001029static int rsl_rx_chan_rqd(struct msgb *msg)
1030{
Harald Welte702d8702008-12-26 20:25:35 +00001031 struct gsm_bts *bts = msg->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001032 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1033 struct gsm48_req_ref *rqd_ref;
Harald Welte52b1f982008-12-23 20:25:15 +00001034 struct gsm48_imm_ass ia;
Harald Welte8470bf22008-12-25 23:28:35 +00001035 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001036 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001037 struct gsm_lchan *lchan;
1038 u_int8_t rqd_ta;
Holger Freyther3186bf22008-12-29 06:23:49 +00001039 int ret;
Harald Welte8470bf22008-12-25 23:28:35 +00001040
Harald Welte52b1f982008-12-23 20:25:15 +00001041 u_int16_t arfcn;
1042 u_int8_t ts_number, subch;
1043
Harald Welte8470bf22008-12-25 23:28:35 +00001044 /* parse request reference to be used in immediate assign */
1045 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1046 return -EINVAL;
1047
1048 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1049
1050 /* parse access delay and use as TA */
1051 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1052 return -EINVAL;
1053 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1054
1055 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1056 * request reference RA */
1057 lctype = get_ctype_by_chreq(bts, rqd_ref->ra);
Harald Welte2cbe0922008-12-29 04:09:31 +00001058 chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra);
1059
Harald Welte8470bf22008-12-25 23:28:35 +00001060 /* check availability / allocate channel */
1061 lchan = lchan_alloc(bts, lctype);
1062 if (!lchan) {
1063 fprintf(stderr, "CHAN RQD: no resources\n");
1064 /* FIXME: send some kind of reject ?!? */
1065 return -ENOMEM;
1066 }
1067
1068 ts_number = lchan->ts->nr;
1069 arfcn = lchan->ts->trx->arfcn;
1070 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001071
Harald Welte66b6a8d2009-08-09 14:45:18 +02001072 lchan->ms_power = ms_pwr_ctl_lvl(bts->band, 20 /* dBm == 100mW */);
Harald Welte0b2124b2009-08-10 00:45:40 +02001073 lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
Harald Welte9943c5b2009-07-29 15:41:29 +02001074 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
1075 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
Harald Welte52b1f982008-12-23 20:25:15 +00001076
1077 /* create IMMEDIATE ASSIGN 04.08 messge */
1078 memset(&ia, 0, sizeof(ia));
1079 ia.l2_plen = 0x2d;
1080 ia.proto_discr = GSM48_PDISC_RR;
1081 ia.msg_type = GSM48_MT_RR_IMM_ASS;
Harald Welte2d5b6382008-12-27 19:46:06 +00001082 ia.page_mode = GSM48_PM_SAME;
Harald Welte4b634542008-12-27 01:55:51 +00001083 ia.chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +00001084 ia.chan_desc.h0.h = 0;
1085 ia.chan_desc.h0.arfcn_high = arfcn >> 8;
1086 ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
Harald Welte814c4b72009-07-21 20:55:56 +02001087 ia.chan_desc.h0.tsc = bts->tsc;
Harald Welte8470bf22008-12-25 23:28:35 +00001088 /* use request reference extracted from CHAN_RQD */
1089 memcpy(&ia.req_ref, rqd_ref, sizeof(ia.req_ref));
1090 ia.timing_advance = rqd_ta;
Harald Welte52b1f982008-12-23 20:25:15 +00001091 ia.mob_alloc_len = 0;
1092
Harald Welte8f5e2392009-02-03 12:57:37 +00001093 DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %s "
Holger Freyther79f4ae62009-06-02 03:25:04 +00001094 "chan_nr=0x%02x r=%s ra=0x%02x\n",
Harald Welteca64da92009-01-04 16:54:12 +00001095 arfcn, ts_number, subch, gsm_lchan_name(lchan->type),
Harald Welte4a543e82009-02-28 13:17:55 +00001096 ia.chan_desc.chan_nr, gsm_chreq_name(chreq_reason),
1097 rqd_ref->ra);
Harald Welte75a983f2008-12-27 21:34:06 +00001098
Harald Welteb7e81162009-08-10 00:26:10 +02001099 /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
1100 lchan->T3101.cb = t3101_expired;
1101 lchan->T3101.data = lchan;
1102 bsc_schedule_timer(&lchan->T3101, 10, 0);
Holger Freyther3186bf22008-12-29 06:23:49 +00001103
Harald Welte52b1f982008-12-23 20:25:15 +00001104 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Freyther3186bf22008-12-29 06:23:49 +00001105 ret = rsl_imm_assign_cmd(bts, sizeof(ia), (u_int8_t *) &ia);
1106
Harald Welte817f3c82008-12-30 14:57:59 +00001107 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001108}
1109
Harald Welteea280442009-02-02 22:29:56 +00001110/* MS has requested a channel on the RACH */
1111static int rsl_rx_ccch_load(struct msgb *msg)
1112{
1113 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1114 u_int16_t pg_buf_space;
Holger Freyther8c563cf2009-02-03 20:08:51 +00001115 u_int16_t rach_slot_count = -1;
1116 u_int16_t rach_busy_count = -1;
1117 u_int16_t rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001118
1119 switch (rslh->data[0]) {
1120 case RSL_IE_PAGING_LOAD:
1121 pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
Holger Freyther392209c2009-02-10 00:06:19 +00001122 paging_update_buffer_space(msg->trx->bts, pg_buf_space);
Harald Welteea280442009-02-02 22:29:56 +00001123 break;
1124 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001125 if (msg->data_len >= 7) {
1126 rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1127 rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1128 rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1129 }
Harald Welteea280442009-02-02 22:29:56 +00001130 break;
1131 default:
1132 break;
1133 }
1134
1135 return 0;
1136}
1137
Harald Welte52b1f982008-12-23 20:25:15 +00001138static int abis_rsl_rx_cchan(struct msgb *msg)
1139{
Harald Welteea280442009-02-02 22:29:56 +00001140 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001141 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001142
Harald Welte8470bf22008-12-25 23:28:35 +00001143 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
1144
1145 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001146 case RSL_MT_CHAN_RQD:
1147 /* MS has requested a channel on the RACH */
1148 rc = rsl_rx_chan_rqd(msg);
1149 break;
Harald Welteea280442009-02-02 22:29:56 +00001150 case RSL_MT_CCCH_LOAD_IND:
1151 /* current load on the CCCH */
1152 rc = rsl_rx_ccch_load(msg);
1153 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001154 case RSL_MT_DELETE_IND:
1155 /* CCCH overloaded, IMM_ASSIGN was dropped */
1156 case RSL_MT_CBCH_LOAD_IND:
1157 /* current load on the CBCH */
Harald Welte8f5e2392009-02-03 12:57:37 +00001158 fprintf(stderr, "Unimplemented Abis RSL TRX message type "
1159 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001160 break;
1161 default:
1162 fprintf(stderr, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001163 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001164 return -EINVAL;
1165 }
Harald Welte8470bf22008-12-25 23:28:35 +00001166
1167 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001168}
1169
Harald Welte4b634542008-12-27 01:55:51 +00001170static int rsl_rx_rll_err_ind(struct msgb *msg)
1171{
1172 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1173 u_int8_t *rlm_cause = rllh->data;
1174
Harald Welte602f2b82009-08-04 02:50:21 +02001175 DEBUGPC(DRLL, "ERROR INDICATION cause=0x%02x\n", rlm_cause[1]);
Harald Welteedcc5272009-08-09 13:47:35 +02001176
1177 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte4b634542008-12-27 01:55:51 +00001178
Harald Welte81543bc2009-07-04 09:40:05 +02001179 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED)
1180 return rsl_chan_release(msg->lchan);
1181
Harald Welte4b634542008-12-27 01:55:51 +00001182 return 0;
1183}
Harald Weltef325eb42009-02-19 17:07:39 +00001184
Harald Welte52b1f982008-12-23 20:25:15 +00001185/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
1186 0x02, 0x06,
1187 0x01, 0x20,
1188 0x02, 0x00,
1189 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1190
1191static int abis_rsl_rx_rll(struct msgb *msg)
1192{
1193 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001194 int rc = 0;
1195 char *ts_name;
Harald Welte8470bf22008-12-25 23:28:35 +00001196
1197 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001198 ts_name = gsm_ts_name(msg->lchan->ts);
1199 DEBUGP(DRLL, "channel=%s chan_nr=0x%02x ", ts_name, rllh->chan_nr);
Harald Welte52b1f982008-12-23 20:25:15 +00001200
1201 switch (rllh->c.msg_type) {
1202 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001203 DEBUGPC(DRLL, "DATA INDICATION\n");
Harald Welte4a543e82009-02-28 13:17:55 +00001204 if (msgb_l2len(msg) >
1205 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1206 rllh->data[0] == RSL_IE_L3_INFO) {
1207 msg->l3h = &rllh->data[3];
1208 return gsm0408_rcvmsg(msg);
1209 }
Harald Welte52b1f982008-12-23 20:25:15 +00001210 break;
1211 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001212 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welteb7e81162009-08-10 00:26:10 +02001213 /* lchan is established, stop T3101 */
1214 bsc_del_timer(&msg->lchan->T3101);
Harald Welte4a543e82009-02-28 13:17:55 +00001215 if (msgb_l2len(msg) >
1216 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1217 rllh->data[0] == RSL_IE_L3_INFO) {
1218 msg->l3h = &rllh->data[3];
1219 return gsm0408_rcvmsg(msg);
1220 }
Harald Welte52b1f982008-12-23 20:25:15 +00001221 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001222 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001223 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Harald Welteedcc5272009-08-09 13:47:35 +02001224 rll_indication(msg->lchan, rllh->link_id,
1225 BSC_RLLR_IND_EST_CONF);
1226 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001227 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001228 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001229 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Harald Welteedcc5272009-08-09 13:47:35 +02001230 rll_indication(msg->lchan, rllh->link_id,
1231 BSC_RLLR_IND_REL_IND);
Harald Welted2dc1de2009-08-08 13:15:07 +02001232 /* we can now releae the channel on the BTS/Abis side */
1233 rsl_chan_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001234 break;
1235 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001236 /* BTS informs us of having received UA from MS,
1237 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001238 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Harald Welted2dc1de2009-08-08 13:15:07 +02001239 /* we can now releae the channel on the BTS/Abis side */
1240 rsl_chan_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001241 break;
1242 case RSL_MT_ERROR_IND:
1243 rc = rsl_rx_rll_err_ind(msg);
1244 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001245 case RSL_MT_UNIT_DATA_IND:
Harald Welte602f2b82009-08-04 02:50:21 +02001246 DEBUGPC(DRLL, "unimplemented Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001247 rllh->c.msg_type);
1248 break;
1249 default:
Harald Welte602f2b82009-08-04 02:50:21 +02001250 DEBUGPC(DRLL, "unknown Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001251 rllh->c.msg_type);
1252 }
Harald Welte8470bf22008-12-25 23:28:35 +00001253 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001254}
1255
Harald Weltef4e79f22009-07-28 18:11:56 +02001256static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
1257{
Harald Weltef4e79f22009-07-28 18:11:56 +02001258 switch (tch_mode) {
1259 case GSM48_CMODE_SPEECH_V1:
1260 return 0x00;
1261 case GSM48_CMODE_SPEECH_EFR:
1262 return 0x01;
1263 case GSM48_CMODE_SPEECH_AMR:
1264 return 0x02;
1265 /* FIXME: Type1 half-rate and type3 half-rate */
1266 }
Harald Welte58ca5b72009-07-29 12:12:18 +02001267 DEBUGPC(DRSL, "Cannot determine ip.access speech mode for "
1268 "tch_mode == 0x%02x\n", tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001269 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001270}
1271
Harald Welte75099262009-02-16 21:12:08 +00001272/* ip.access specific RSL extensions */
1273int rsl_ipacc_bind(struct gsm_lchan *lchan)
1274{
1275 struct msgb *msg = rsl_msgb_alloc();
1276 struct abis_rsl_dchan_hdr *dh;
Harald Welte58ca5b72009-07-29 12:12:18 +02001277 u_int8_t speech_mode;
Harald Welte75099262009-02-16 21:12:08 +00001278
1279 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1280 init_dchan_hdr(dh, RSL_MT_IPAC_BIND);
1281 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1282 dh->chan_nr = lchan2chan_nr(lchan);
1283
Harald Weltef4e79f22009-07-28 18:11:56 +02001284 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte58ca5b72009-07-29 12:12:18 +02001285 speech_mode = 0x10 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1286 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001287
Harald Welte58ca5b72009-07-29 12:12:18 +02001288 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND "
1289 "speech_mode=0x%02x\n", gsm_ts_name(lchan->ts),
1290 dh->chan_nr, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001291
Harald Welte75099262009-02-16 21:12:08 +00001292 msg->trx = lchan->ts->trx;
1293
1294 return abis_rsl_sendmsg(msg);
1295}
1296
Harald Welte20855542009-07-12 09:50:35 +02001297int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
1298 u_int16_t conn_id, u_int8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001299{
1300 struct msgb *msg = rsl_msgb_alloc();
1301 struct abis_rsl_dchan_hdr *dh;
1302 u_int8_t *att_f8, *att_ip, *att_port;
Harald Welte58ca5b72009-07-29 12:12:18 +02001303 u_int8_t speech_mode;
Harald Weltef4e79f22009-07-28 18:11:56 +02001304 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001305
1306 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1307 init_dchan_hdr(dh, RSL_MT_IPAC_CONNECT);
1308 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1309 dh->chan_nr = lchan2chan_nr(lchan);
1310
Harald Welte58ca5b72009-07-29 12:12:18 +02001311 /* 0x0- == both directions, 0x-1 == EFR codec */
1312 speech_mode = 0x00 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1313
Harald Weltef4e79f22009-07-28 18:11:56 +02001314 ia.s_addr = htonl(ip);
Harald Welte58ca5b72009-07-29 12:12:18 +02001315 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_CONNECT "
1316 "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d speech_mode=0x%02x\n",
Harald Weltef4e79f22009-07-28 18:11:56 +02001317 gsm_ts_name(lchan->ts), dh->chan_nr,
Harald Welte58ca5b72009-07-29 12:12:18 +02001318 inet_ntoa(ia), port, rtp_payload2, conn_id, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001319
Harald Welte20855542009-07-12 09:50:35 +02001320 att_f8 = msgb_put(msg, sizeof(conn_id)+1);
Harald Welte86c162d2009-07-12 09:45:05 +02001321 att_f8[0] = RSL_IE_IPAC_CONN_ID;
Harald Welte20855542009-07-12 09:50:35 +02001322 att_f8[1] = conn_id >> 8;
1323 att_f8[2] = conn_id & 0xff;
Harald Welte75099262009-02-16 21:12:08 +00001324
1325 att_ip = msgb_put(msg, sizeof(ip)+1);
1326 att_ip[0] = RSL_IE_IPAC_REMOTE_IP;
1327 att_ip[1] = ip >> 24;
1328 att_ip[2] = ip >> 16;
1329 att_ip[3] = ip >> 8;
1330 att_ip[4] = ip & 0xff;
Harald Welteda783762009-02-18 03:29:53 +00001331 //att_ip[4] = 11;
Harald Welte75099262009-02-16 21:12:08 +00001332
1333 att_port = msgb_put(msg, sizeof(port)+1);
1334 att_port[0] = RSL_IE_IPAC_REMOTE_PORT;
1335 att_port[1] = port >> 8;
1336 att_port[2] = port & 0xff;
1337
Harald Welte58ca5b72009-07-29 12:12:18 +02001338 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001339 if (rtp_payload2)
1340 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
1341
Harald Welte75099262009-02-16 21:12:08 +00001342 msg->trx = lchan->ts->trx;
1343
1344 return abis_rsl_sendmsg(msg);
1345}
1346
1347static int abis_rsl_rx_ipacc_bindack(struct msgb *msg)
1348{
1349 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1350 struct tlv_parsed tv;
1351 struct gsm_bts_trx_ts *ts = msg->lchan->ts;
Harald Welte167df882009-02-17 14:35:45 +00001352 struct in_addr ip;
Harald Welte75099262009-02-16 21:12:08 +00001353 u_int16_t port, attr_f8;
1354
1355 /* the BTS has acknowledged a local bind, it now tells us the IP
1356 * address and port number to which it has bound the given logical
1357 * channel */
1358
1359 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1360 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1361 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02001362 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltef325eb42009-02-19 17:07:39 +00001363 DEBUGPC(DRSL, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001364 return -EINVAL;
1365 }
Harald Welte167df882009-02-17 14:35:45 +00001366 ip.s_addr = *((u_int32_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte75099262009-02-16 21:12:08 +00001367 port = *((u_int16_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_PORT));
1368 attr_f8 = *((u_int16_t *) TLVP_VAL(&tv, 0xf8));
1369
Harald Weltef4e79f22009-07-28 18:11:56 +02001370 DEBUGPC(DRSL, "IP=%s PORT=%d CONN_ID=%d ",
1371 inet_ntoa(ip), ntohs(port), ntohs(attr_f8));
1372
1373 if (TLVP_PRESENT(&tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1374 ts->abis_ip.rtp_payload2 =
1375 *TLVP_VAL(&tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1376 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1377 ts->abis_ip.rtp_payload2);
1378 }
Harald Welte167df882009-02-17 14:35:45 +00001379
Harald Welte75099262009-02-16 21:12:08 +00001380 /* update our local information about this TS */
Harald Welte167df882009-02-17 14:35:45 +00001381 ts->abis_ip.bound_ip = ntohl(ip.s_addr);
1382 ts->abis_ip.bound_port = ntohs(port);
Harald Welte20855542009-07-12 09:50:35 +02001383 ts->abis_ip.conn_id = ntohs(attr_f8);
Harald Welte75099262009-02-16 21:12:08 +00001384
Harald Welte167df882009-02-17 14:35:45 +00001385 dispatch_signal(SS_ABISIP, S_ABISIP_BIND_ACK, msg->lchan);
1386
Harald Welte75099262009-02-16 21:12:08 +00001387 return 0;
1388}
1389
1390static int abis_rsl_rx_ipacc_disc_ind(struct msgb *msg)
1391{
1392 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1393 struct tlv_parsed tv;
1394
1395 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00001396
Harald Welte8830e072009-07-28 17:58:09 +02001397 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
1398 print_rsl_cause(TLVP_VAL(&tv, RSL_IE_CAUSE),
1399 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001400
Harald Welte888b1142009-07-28 18:02:05 +02001401 dispatch_signal(SS_ABISIP, S_ABISIP_DISC_IND, msg->lchan);
1402
Harald Welte75099262009-02-16 21:12:08 +00001403 return 0;
1404}
1405
1406static int abis_rsl_rx_ipacc(struct msgb *msg)
1407{
1408 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1409 int rc = 0;
1410
1411 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001412 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ",
1413 gsm_ts_name(msg->lchan->ts), rllh->chan_nr);
Harald Welte75099262009-02-16 21:12:08 +00001414
1415 switch (rllh->c.msg_type) {
1416 case RSL_MT_IPAC_BIND_ACK:
Harald Welte4a543e82009-02-28 13:17:55 +00001417 DEBUGPC(DRSL, "IPAC_BIND_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001418 rc = abis_rsl_rx_ipacc_bindack(msg);
1419 break;
1420 case RSL_MT_IPAC_BIND_NACK:
1421 /* somehow the BTS was unable to bind the lchan to its local
1422 * port?!? */
Harald Weltef325eb42009-02-19 17:07:39 +00001423 DEBUGPC(DRSL, "IPAC_BIND_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001424 break;
1425 case RSL_MT_IPAC_CONNECT_ACK:
1426 /* the BTS tells us that a connect operation was successful */
Harald Weltef325eb42009-02-19 17:07:39 +00001427 DEBUGPC(DRSL, "IPAC_CONNECT_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001428 break;
1429 case RSL_MT_IPAC_CONNECT_NACK:
1430 /* somehow the BTS was unable to connect the lchan to a remote
1431 * port */
Harald Weltef325eb42009-02-19 17:07:39 +00001432 DEBUGPC(DRSL, "IPAC_CONNECT_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001433 break;
1434 case RSL_MT_IPAC_DISCONNECT_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001435 DEBUGPC(DRSL, "IPAC_DISCONNECT_IND ");
Harald Welte75099262009-02-16 21:12:08 +00001436 rc = abis_rsl_rx_ipacc_disc_ind(msg);
1437 break;
1438 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001439 DEBUGPC(DRSL, "Unknown ip.access msg_type 0x%02x", rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001440 break;
1441 }
Harald Welte6dab0552009-05-01 17:21:37 +00001442 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001443
1444 return rc;
1445}
1446
1447
Harald Welte52b1f982008-12-23 20:25:15 +00001448/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001449int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001450{
1451 struct abis_rsl_common_hdr *rslh = msgb_l2(msg) ;
Harald Welte8f5e2392009-02-03 12:57:37 +00001452 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001453
1454 switch (rslh->msg_discr & 0xfe) {
1455 case ABIS_RSL_MDISC_RLL:
1456 rc = abis_rsl_rx_rll(msg);
1457 break;
1458 case ABIS_RSL_MDISC_DED_CHAN:
1459 rc = abis_rsl_rx_dchan(msg);
1460 break;
1461 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00001462 rc = abis_rsl_rx_cchan(msg);
1463 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001464 case ABIS_RSL_MDISC_TRX:
1465 rc = abis_rsl_rx_trx(msg);
1466 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001467 case ABIS_RSL_MDISC_LOC:
Harald Welte8f5e2392009-02-03 12:57:37 +00001468 fprintf(stderr, "unimplemented RSL msg disc 0x%02x\n",
1469 rslh->msg_discr);
1470 break;
Harald Welte75099262009-02-16 21:12:08 +00001471 case ABIS_RSL_MDISC_IPACCESS:
1472 rc = abis_rsl_rx_ipacc(msg);
1473 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001474 default:
1475 fprintf(stderr, "unknown RSL message discriminator 0x%02x\n",
1476 rslh->msg_discr);
1477 return -EINVAL;
1478 }
Harald Welte4f4a3902008-12-26 00:04:49 +00001479 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001480 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001481}
Holger Freyther3b72a892009-02-04 00:31:39 +00001482
1483
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001484/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
Holger Freyther3b72a892009-02-04 00:31:39 +00001485int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf)
1486{
1487 switch (ccch_conf) {
1488 case RSL_BCCH_CCCH_CONF_1_NC:
1489 return 1;
1490 case RSL_BCCH_CCCH_CONF_1_C:
1491 return 1;
1492 case RSL_BCCH_CCCH_CONF_2_NC:
1493 return 2;
1494 case RSL_BCCH_CCCH_CONF_3_NC:
1495 return 3;
1496 case RSL_BCCH_CCCH_CONF_4_NC:
1497 return 4;
1498 default:
1499 return -1;
1500 }
1501}
1502
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001503/* Section 3.3.2.3 TS 05.02 */
Holger Freyther3b72a892009-02-04 00:31:39 +00001504int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf)
1505{
1506 switch (ccch_conf) {
1507 case RSL_BCCH_CCCH_CONF_1_NC:
1508 return 0;
1509 case RSL_BCCH_CCCH_CONF_1_C:
1510 return 1;
1511 case RSL_BCCH_CCCH_CONF_2_NC:
1512 return 0;
1513 case RSL_BCCH_CCCH_CONF_3_NC:
1514 return 0;
1515 case RSL_BCCH_CCCH_CONF_4_NC:
1516 return 0;
1517 default:
1518 return -1;
1519 }
1520}
1521
1522/* From Table 10.5.33 of GSM 04.08 */
1523int rsl_number_of_paging_subchannels(struct gsm_bts *bts)
1524{
1525 if (bts->chan_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) {
1526 return MAX(1, (3 - bts->chan_desc.bs_ag_blks_res))
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001527 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001528 } else {
1529 return (9 - bts->chan_desc.bs_ag_blks_res)
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001530 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001531 }
1532}