blob: 726ef23a63c2db4eb79c1031b35c1b327cde4fea [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>
33#include <openbsc/abis_rsl.h>
34#include <openbsc/chan_alloc.h>
35#include <openbsc/debug.h>
36#include <openbsc/tlv.h>
Holger Freyther392209c2009-02-10 00:06:19 +000037#include <openbsc/paging.h>
Harald Welte167df882009-02-17 14:35:45 +000038#include <openbsc/signal.h>
Harald Welte52b1f982008-12-23 20:25:15 +000039
Harald Welte8470bf22008-12-25 23:28:35 +000040#define RSL_ALLOC_SIZE 1024
41#define RSL_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000042
Holger Freyther3b72a892009-02-04 00:31:39 +000043#define MAX(a, b) (a) >= (b) ? (a) : (b)
44
Harald Welte75099262009-02-16 21:12:08 +000045static const struct tlv_definition rsl_att_tlvdef = {
46 .def = {
47 [RSL_IE_CHAN_NR] = { TLV_TYPE_TV },
48 [RSL_IE_LINK_IDENT] = { TLV_TYPE_TV },
49 [RSL_IE_ACT_TYPE] = { TLV_TYPE_TV },
50 [RSL_IE_BS_POWER] = { TLV_TYPE_TV },
51 [RSL_IE_CHAN_IDENT] = { TLV_TYPE_TLV },
52 [RSL_IE_CHAN_MODE] = { TLV_TYPE_TLV },
53 [RSL_IE_ENCR_INFO] = { TLV_TYPE_TLV },
54 [RSL_IE_FRAME_NUMBER] = { TLV_TYPE_FIXED, 2 },
55 [RSL_IE_HANDO_REF] = { TLV_TYPE_TV },
56 [RSL_IE_L1_INFO] = { TLV_TYPE_FIXED, 2 },
57 [RSL_IE_L3_INFO] = { TLV_TYPE_TL16V },
58 [RSL_IE_MS_IDENTITY] = { TLV_TYPE_TLV },
59 [RSL_IE_MS_POWER] = { TLV_TYPE_TV },
60 [RSL_IE_PAGING_GROUP] = { TLV_TYPE_TV },
61 [RSL_IE_PAGING_LOAD] = { TLV_TYPE_FIXED, 2 },
62 [RSL_IE_PYHS_CONTEXT] = { TLV_TYPE_TLV },
63 [RSL_IE_ACCESS_DELAY] = { TLV_TYPE_TV },
64 [RSL_IE_RACH_LOAD] = { TLV_TYPE_TLV },
65 [RSL_IE_REQ_REFERENCE] = { TLV_TYPE_FIXED, 3 },
66 [RSL_IE_RELEASE_MODE] = { TLV_TYPE_TV },
67 [RSL_IE_RESOURCE_INFO] = { TLV_TYPE_TLV },
68 [RSL_IE_RLM_CAUSE] = { TLV_TYPE_TLV },
69 [RSL_IE_STARTNG_TIME] = { TLV_TYPE_FIXED, 2 },
70 [RSL_IE_TIMING_ADVANCE] = { TLV_TYPE_TV },
71 [RSL_IE_UPLINK_MEAS] = { TLV_TYPE_TLV },
72 [RSL_IE_CAUSE] = { TLV_TYPE_TLV },
73 [RSL_IE_MEAS_RES_NR] = { TLV_TYPE_TV },
74 [RSL_IE_MSG_ID] = { TLV_TYPE_TV },
75 [RSL_IE_SYSINFO_TYPE] = { TLV_TYPE_TV },
76 [RSL_IE_MS_POWER_PARAM] = { TLV_TYPE_TLV },
77 [RSL_IE_BS_POWER_PARAM] = { TLV_TYPE_TLV },
78 [RSL_IE_PREPROC_PARAM] = { TLV_TYPE_TLV },
79 [RSL_IE_PREPROC_MEAS] = { TLV_TYPE_TLV },
80 [RSL_IE_IMM_ASS_INFO] = { TLV_TYPE_TLV },
81 [RSL_IE_SMSCB_INFO] = { TLV_TYPE_FIXED, 23 },
82 [RSL_IE_MS_TIMING_OFFSET] = { TLV_TYPE_TV },
83 [RSL_IE_ERR_MSG] = { TLV_TYPE_TLV },
84 [RSL_IE_FULL_BCCH_INFO] = { TLV_TYPE_TLV },
85 [RSL_IE_CHAN_NEEDED] = { TLV_TYPE_TV },
86 [RSL_IE_CB_CMD_TYPE] = { TLV_TYPE_TV },
87 [RSL_IE_SMSCB_MSG] = { TLV_TYPE_TLV },
88 [RSL_IE_FULL_IMM_ASS_INFO] = { TLV_TYPE_TLV },
89 [RSL_IE_SACCH_INFO] = { TLV_TYPE_TLV },
90 [RSL_IE_CBCH_LOAD_INFO] = { TLV_TYPE_TV },
91 [RSL_IE_SMSCB_CHAN_INDICATOR] = { TLV_TYPE_TV },
92 [RSL_IE_GROUP_CALL_REF] = { TLV_TYPE_TLV },
93 [RSL_IE_CHAN_DESC] = { TLV_TYPE_TLV },
94 [RSL_IE_NCH_DRX_INFO] = { TLV_TYPE_TLV },
95 [RSL_IE_CMD_INDICATOR] = { TLV_TYPE_TLV },
96 [RSL_IE_EMLPP_PRIO] = { TLV_TYPE_TV },
97 [RSL_IE_UIC] = { TLV_TYPE_TLV },
98 [RSL_IE_MAIN_CHAN_REF] = { TLV_TYPE_TV },
99 [RSL_IE_MR_CONFIG] = { TLV_TYPE_TLV },
100 [RSL_IE_MR_CONTROL] = { TLV_TYPE_TV },
101 [RSL_IE_SUP_CODEC_TYPES] = { TLV_TYPE_TLV },
102 [RSL_IE_CODEC_CONFIG] = { TLV_TYPE_TLV },
103 [RSL_IE_RTD] = { TLV_TYPE_TV },
104 [RSL_IE_TFO_STATUS] = { TLV_TYPE_TV },
105 [RSL_IE_LLP_APDU] = { TLV_TYPE_TLV },
Harald Welteab46d742009-07-12 09:56:39 +0200106 [RSL_IE_IPAC_PROXY_UDP] = { TLV_TYPE_FIXED, 2 },
107 [RSL_IE_IPAC_BSCMPL_TOUT] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000108 [RSL_IE_IPAC_REMOTE_IP] = { TLV_TYPE_FIXED, 4 },
109 [RSL_IE_IPAC_REMOTE_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200110 [RSL_IE_IPAC_RTP_PAYLOAD] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000111 [RSL_IE_IPAC_LOCAL_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welte86c162d2009-07-12 09:45:05 +0200112 [RSL_IE_IPAC_SPEECH_MODE] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200113 [RSL_IE_IPAC_LOCAL_IP] = { TLV_TYPE_FIXED, 4 },
Harald Welte86c162d2009-07-12 09:45:05 +0200114 [RSL_IE_IPAC_CONN_ID] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200115 [RSL_IE_IPAC_RTP_CSD_FMT] = { TLV_TYPE_TV },
116 [RSL_IE_IPAC_RTP_JIT_BUF] = { TLV_TYPE_FIXED, 2 },
117 [RSL_IE_IPAC_RTP_COMPR] = { TLV_TYPE_TV },
Harald Welte86c162d2009-07-12 09:45:05 +0200118 [RSL_IE_IPAC_RTP_PAYLOAD2] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200119 [RSL_IE_IPAC_RTP_MPLEX] = { TLV_TYPE_FIXED, 8 },
120 [RSL_IE_IPAC_RTP_MPLEX_ID] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000121 },
122};
Harald Weltea4d49e92009-05-23 06:39:58 +0000123#define rsl_tlv_parse(dec, buf, len) \
124 tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
Harald Welte75099262009-02-16 21:12:08 +0000125
Harald Welte52b1f982008-12-23 20:25:15 +0000126static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
127{
128 /* mask off the transparent bit ? */
129 msg_type &= 0xfe;
130
Harald Welte8470bf22008-12-25 23:28:35 +0000131 if ((msg_type & 0xf0) == 0x00)
Harald Welte52b1f982008-12-23 20:25:15 +0000132 return ABIS_RSL_MDISC_RLL;
Harald Welte8470bf22008-12-25 23:28:35 +0000133 if ((msg_type & 0xf0) == 0x10) {
Harald Welte52b1f982008-12-23 20:25:15 +0000134 if (msg_type >= 0x19 && msg_type <= 0x22)
135 return ABIS_RSL_MDISC_TRX;
136 else
137 return ABIS_RSL_MDISC_COM_CHAN;
138 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000139 if ((msg_type & 0xe0) == 0x20)
Harald Welte52b1f982008-12-23 20:25:15 +0000140 return ABIS_RSL_MDISC_DED_CHAN;
141
142 return ABIS_RSL_MDISC_LOC;
143}
144
145static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
146 u_int8_t msg_type)
147{
148 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
149 dh->c.msg_type = msg_type;
150 dh->ie_chan = RSL_IE_CHAN_NR;
151}
152
153static inline void init_llm_hdr(struct abis_rsl_rll_hdr *dh,
154 u_int8_t msg_type)
155{
156 /* dh->c.msg_discr = mdisc_by_msgtype(msg_type); */
157 dh->c.msg_discr = ABIS_RSL_MDISC_RLL;
158 dh->c.msg_type = msg_type;
159 dh->ie_chan = RSL_IE_CHAN_NR;
160 dh->ie_link_id = RSL_IE_LINK_IDENT;
161}
162
163
164/* encode channel number as per Section 9.3.1 */
165u_int8_t rsl_enc_chan_nr(u_int8_t type, u_int8_t subch, u_int8_t timeslot)
166{
167 u_int8_t ret;
168
169 ret = (timeslot & 0x07) | type;
170
171 switch (type) {
172 case RSL_CHAN_Lm_ACCHs:
173 subch &= 0x01;
174 break;
175 case RSL_CHAN_SDCCH4_ACCH:
176 subch &= 0x07;
177 break;
178 case RSL_CHAN_SDCCH8_ACCH:
179 subch &= 0x07;
180 break;
181 default:
182 /* no subchannels allowed */
183 subch = 0x00;
184 break;
185 }
186 ret |= (subch << 3);
187
188 return ret;
189}
190
Harald Welte8470bf22008-12-25 23:28:35 +0000191/* determine logical channel based on TRX and channel number IE */
192struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
193{
194 struct gsm_lchan *lchan;
195 u_int8_t ts_nr = chan_nr & 0x07;
196 u_int8_t cbits = chan_nr >> 3;
197 u_int8_t lch_idx;
198 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
199
200 if (cbits == 0x01) {
201 lch_idx = 0; /* TCH/F */
202 if (ts->pchan != GSM_PCHAN_TCH_F)
203 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
204 chan_nr, ts->pchan);
205 } else if ((cbits & 0x1e) == 0x02) {
206 lch_idx = cbits & 0x1; /* TCH/H */
207 if (ts->pchan != GSM_PCHAN_TCH_H)
208 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
209 chan_nr, ts->pchan);
210 } else if ((cbits & 0x1c) == 0x04) {
211 lch_idx = cbits & 0x3; /* SDCCH/4 */
212 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
213 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
214 chan_nr, ts->pchan);
215 } else if ((cbits & 0x18) == 0x08) {
216 lch_idx = cbits & 0x7; /* SDCCH/8 */
217 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
218 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
219 chan_nr, ts->pchan);
220 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
221 lch_idx = 0;
222 if (ts->pchan != GSM_PCHAN_CCCH &&
223 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
224 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
225 chan_nr, ts->pchan);
226 /* FIXME: we should not return first sdcch4 !!! */
227 } else {
228 fprintf(stderr, "unknown chan_nr=0x%02x\n", chan_nr);
229 return NULL;
230 }
231
232 lchan = &ts->lchan[lch_idx];
233
234 return lchan;
235}
236
237u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
238{
239 struct gsm_bts_trx_ts *ts = lchan->ts;
240 u_int8_t cbits, chan_nr;
241
242 switch (ts->pchan) {
243 case GSM_PCHAN_TCH_F:
244 cbits = 0x01;
245 break;
246 case GSM_PCHAN_TCH_H:
247 cbits = 0x02;
248 cbits += lchan->nr;
249 break;
250 case GSM_PCHAN_CCCH_SDCCH4:
251 cbits = 0x04;
252 cbits += lchan->nr;
253 break;
254 case GSM_PCHAN_SDCCH8_SACCH8C:
255 cbits = 0x08;
256 cbits += lchan->nr;
257 break;
258 default:
259 case GSM_PCHAN_CCCH:
260 cbits = 0x10;
261 break;
262 }
263
264 chan_nr = (cbits << 3) | (ts->nr & 0x7);
265
266 return chan_nr;
267}
268
Harald Welte52b1f982008-12-23 20:25:15 +0000269/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
270u_int64_t str_to_imsi(const char *imsi_str)
271{
272 u_int64_t ret;
273
274 ret = strtoull(imsi_str, NULL, 10);
275
276 return ret;
277}
278
279/* Table 5 Clause 7 TS 05.02 */
280unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res)
281{
282 if (!bs_ccch_sdcch_comb)
283 return 9 - bs_ag_blks_res;
284 else
285 return 3 - bs_ag_blks_res;
286}
287
288/* Chapter 6.5.2 of TS 05.02 */
289unsigned int get_ccch_group(u_int64_t imsi, unsigned int bs_cc_chans,
290 unsigned int n_pag_blocks)
291{
292 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) / n_pag_blocks;
293}
294
295/* Chapter 6.5.2 of TS 05.02 */
296unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
297 int n_pag_blocks)
298{
299 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) % n_pag_blocks;
300}
301
Harald Welte8470bf22008-12-25 23:28:35 +0000302static struct msgb *rsl_msgb_alloc(void)
303{
Harald Welte966636f2009-06-26 19:39:35 +0200304 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
305 "RSL");
Harald Welte8470bf22008-12-25 23:28:35 +0000306}
307
Harald Welte362322e2009-02-15 14:36:38 +0000308#define MACBLOCK_SIZE 23
309static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
310{
311 memcpy(out, in, len);
312
313 if (len < MACBLOCK_SIZE)
314 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
315}
316
Harald Welte8830e072009-07-28 17:58:09 +0200317static const char *rsl_err_vals[0xff] = {
318 [RSL_ERR_RADIO_IF_FAIL] = "Radio Interface Failure",
319 [RSL_ERR_RADIO_LINK_FAIL] = "Radio Link Failure",
320 [RSL_ERR_HANDOVER_ACC_FAIL] = "Handover Access Failure",
321 [RSL_ERR_TALKER_ACC_FAIL] = "Talker Access Failure",
322 [RSL_ERR_OM_INTERVENTION] = "O&M Intervention",
323 [RSL_ERR_NORMAL_UNSPEC] = "Normal event, unspecified",
Harald Welte2da86292009-08-04 02:31:05 +0200324 [RSL_ERR_T_MSRFPCI_EXP] = "Siemens: T_MSRFPCI Expired",
Harald Welte8830e072009-07-28 17:58:09 +0200325 [RSL_ERR_EQUIPMENT_FAIL] = "Equipment Failure",
326 [RSL_ERR_RR_UNAVAIL] = "Radio Resource not available",
327 [RSL_ERR_TERR_CH_FAIL] = "Terrestrial Channel Failure",
328 [RSL_ERR_CCCH_OVERLOAD] = "CCCH Overload",
329 [RSL_ERR_ACCH_OVERLOAD] = "ACCH Overload",
330 [RSL_ERR_PROCESSOR_OVERLOAD] = "Processor Overload",
331 [RSL_ERR_RES_UNAVAIL] = "Resource not available, unspecified",
332 [RSL_ERR_TRANSC_UNAVAIL] = "Transcoding not available",
333 [RSL_ERR_SERV_OPT_UNAVAIL] = "Service or Option not available",
334 [RSL_ERR_ENCR_UNIMPL] = "Encryption algorithm not implemented",
335 [RSL_ERR_SERV_OPT_UNIMPL] = "Service or Option not implemented",
336 [RSL_ERR_RCH_ALR_ACTV_ALLOC] = "Radio channel already activated",
337 [RSL_ERR_INVALID_MESSAGE] = "Invalid Message, unspecified",
338 [RSL_ERR_MSG_DISCR] = "Message Discriminator Error",
339 [RSL_ERR_MSG_TYPE] = "Message Type Error",
340 [RSL_ERR_MSG_SEQ] = "Message Sequence Error",
341 [RSL_ERR_IE_ERROR] = "General IE error",
342 [RSL_ERR_MAND_IE_ERROR] = "Mandatory IE error",
343 [RSL_ERR_OPT_IE_ERROR] = "Optional IE error",
344 [RSL_ERR_IE_NONEXIST] = "IE non-existent",
345 [RSL_ERR_IE_LENGTH] = "IE length error",
346 [RSL_ERR_IE_CONTENT] = "IE content error",
347 [RSL_ERR_PROTO] = "Protocol error, unspecified",
348 [RSL_ERR_INTERWORKING] = "Interworking error, unspecified",
349};
350
351static const char *rsl_err_name(u_int8_t err)
Harald Welte7f93cea2009-02-23 00:02:59 +0000352{
Harald Welte8830e072009-07-28 17:58:09 +0200353 if (rsl_err_vals[err])
354 return rsl_err_vals[err];
355 else
356 return "unknown";
357}
358
359static void print_rsl_cause(const u_int8_t *cause_v, u_int8_t cause_len)
360{
Harald Welte7f93cea2009-02-23 00:02:59 +0000361 int i;
362
Harald Welte8830e072009-07-28 17:58:09 +0200363 DEBUGPC(DRSL, "CAUSE=0x%02x(%s) ",
364 cause_v[0], rsl_err_name(cause_v[0]));
365 for (i = 1; i < cause_len-1; i++)
366 DEBUGPC(DRSL, "%02x ", cause_v[i]);
Harald Welte7f93cea2009-02-23 00:02:59 +0000367}
368
Harald Welte52b1f982008-12-23 20:25:15 +0000369/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Harald Weltee79769b2009-02-07 00:48:17 +0000370int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000371 const u_int8_t *data, int len)
372{
373 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000374 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000375
376 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
377 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
378 dh->chan_nr = RSL_CHAN_BCCH;
379
380 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
381 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
382
Harald Weltee79769b2009-02-07 00:48:17 +0000383 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000384
385 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000386}
387
Harald Weltee79769b2009-02-07 00:48:17 +0000388int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000389 const u_int8_t *data, int len)
390{
391 struct abis_rsl_common_hdr *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000392 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000393
394 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
395 ch->msg_discr = ABIS_RSL_MDISC_TRX;
396 ch->msg_type = RSL_MT_SACCH_FILL;
397
398 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
Harald Welte702d8702008-12-26 20:25:35 +0000399 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
Harald Welte52b1f982008-12-23 20:25:15 +0000400
Harald Weltee79769b2009-02-07 00:48:17 +0000401 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000402
403 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000404}
405
Harald Weltefcd24452009-06-20 18:15:19 +0200406int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
407{
408 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200409 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200410 u_int8_t chan_nr = lchan2chan_nr(lchan);
411
412 db = abs(db);
413 if (db > 30)
414 return -EINVAL;
415
Harald Welteeab33352009-06-27 03:09:08 +0200416 msg = rsl_msgb_alloc();
417
Harald Weltefcd24452009-06-20 18:15:19 +0200418 lchan->bs_power = db/2;
419 if (fpc)
420 lchan->bs_power |= 0x10;
421
422 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
423 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
424 dh->chan_nr = chan_nr;
425
426 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
427
428 msg->trx = lchan->ts->trx;
429
430 return abis_rsl_sendmsg(msg);
431}
432
433/* determine power control level for given dBm value, as indicated
434 * by the tables in chapter 4.1.1 of GSM TS 05.05 */
435static int ms_pwr_ctl_lvl(struct gsm_bts *bts, unsigned int dbm)
436{
437 switch (bts->band) {
438 case GSM_BAND_400:
439 case GSM_BAND_900:
440 case GSM_BAND_850:
441 if (dbm >= 39)
442 return 0;
443 else if (dbm < 5)
444 return 19;
445 else
446 return 2 + ((39 - dbm) / 2);
447 break;
448 case GSM_BAND_1800:
449 if (dbm >= 36)
450 return 29;
451 else if (dbm >= 34)
452 return 30;
453 else if (dbm >= 32)
454 return 31;
455 else
456 return (30 - dbm) / 2;
457 break;
458 case GSM_BAND_1900:
459 if (dbm >= 33)
460 return 30;
461 else if (dbm >= 32)
462 return 31;
463 else
464 return (30 - dbm) / 2;
465 break;
466 }
467 return -EINVAL;
468}
469
Harald Weltefe9af262009-06-20 18:44:35 +0200470static int ms_pwr_dbm(enum gsm_band band, u_int8_t lvl)
471{
472 lvl &= 0x1f;
473
474 switch (band) {
475 case GSM_BAND_400:
476 case GSM_BAND_900:
477 case GSM_BAND_850:
478 if (lvl < 2)
479 return 39;
480 else if (lvl < 20)
481 return 39 - ((lvl - 2) * 2) ;
482 else
483 return 5;
484 break;
485 case GSM_BAND_1800:
486 if (lvl < 16)
487 return 30 - (lvl * 2);
488 else if (lvl < 29)
489 return 0;
490 else
491 return 36 - ((lvl - 29) * 2);
492 break;
493 case GSM_BAND_1900:
494 if (lvl < 16)
495 return 30 - (lvl * 2);
496 else if (lvl < 30)
497 return -EINVAL;
498 else
499 return 33 - (lvl - 30);
500 break;
501 }
502 return -EINVAL;
503}
504
Harald Weltefcd24452009-06-20 18:15:19 +0200505int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
506{
507 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200508 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200509 u_int8_t chan_nr = lchan2chan_nr(lchan);
510 int ctl_lvl;
511
512 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts, dbm);
513 if (ctl_lvl < 0)
514 return ctl_lvl;
515
Harald Welteeab33352009-06-27 03:09:08 +0200516 msg = rsl_msgb_alloc();
517
Harald Weltefcd24452009-06-20 18:15:19 +0200518 lchan->ms_power = ctl_lvl;
519
520 if (fpc)
521 lchan->ms_power |= 0x20;
522
523 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
524 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
525 dh->chan_nr = chan_nr;
526
527 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
528
529 msg->trx = lchan->ts->trx;
530
531 return abis_rsl_sendmsg(msg);
532}
533
Harald Welte9943c5b2009-07-29 15:41:29 +0200534static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
535 struct gsm_lchan *lchan)
536{
537 memset(cm, 0, sizeof(cm));
538
539 /* FIXME: what to do with data calls ? */
540 cm->dtx_dtu = 0x00;
541
542 /* set TCH Speech/Data */
543 cm->spd_ind = lchan->rsl_cmode;
544
545 switch (lchan->type) {
546 case GSM_LCHAN_SDCCH:
547 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
548 break;
549 case GSM_LCHAN_TCH_F:
550 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
551 break;
552 case GSM_LCHAN_TCH_H:
553 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
554 break;
555 case GSM_LCHAN_NONE:
556 case GSM_LCHAN_UNKNOWN:
557 default:
558 return -EINVAL;
559 }
560
561 switch (lchan->tch_mode) {
562 case GSM48_CMODE_SIGN:
563 cm->chan_rate = 0;
564 break;
565 case GSM48_CMODE_SPEECH_V1:
566 cm->chan_rate = RSL_CMOD_SP_GSM1;
567 break;
568 case GSM48_CMODE_SPEECH_EFR:
569 cm->chan_rate = RSL_CMOD_SP_GSM2;
570 break;
571 case GSM48_CMODE_SPEECH_AMR:
572 cm->chan_rate = RSL_CMOD_SP_GSM3;
573 break;
574 case GSM48_CMODE_DATA_14k5:
575 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
576 break;
577 case GSM48_CMODE_DATA_12k0:
578 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
579 break;
580 case GSM48_CMODE_DATA_6k0:
581 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
582 break;
583 default:
584 return -EINVAL;
585 }
586
587 return 0;
588}
589
Harald Welte52b1f982008-12-23 20:25:15 +0000590/* Chapter 8.4.1 */
Harald Welteddab3c72009-02-28 13:19:15 +0000591#if 0
Harald Weltee79769b2009-02-07 00:48:17 +0000592int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
Harald Welte52b1f982008-12-23 20:25:15 +0000593 u_int8_t act_type,
594 struct rsl_ie_chan_mode *chan_mode,
595 struct rsl_ie_chan_ident *chan_ident,
596 u_int8_t bs_power, u_int8_t ms_power,
597 u_int8_t ta)
598{
599 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000600 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000601
602 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
603 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
604 dh->chan_nr = chan_nr;
605
606 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
607 /* For compatibility with Phase 1 */
608 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
609 (u_int8_t *) chan_mode);
610 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Harald Welte702d8702008-12-26 20:25:35 +0000611 (u_int8_t *) chan_ident);
Harald Welte702d8702008-12-26 20:25:35 +0000612#if 0
Harald Welte52b1f982008-12-23 20:25:15 +0000613 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
614 (u_int8_t *) &encr_info);
Harald Welte702d8702008-12-26 20:25:35 +0000615#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000616 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
Harald Welte52b1f982008-12-23 20:25:15 +0000617 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
618 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
619
Harald Weltee79769b2009-02-07 00:48:17 +0000620 msg->trx = trx;
621
Harald Welte8470bf22008-12-25 23:28:35 +0000622 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000623}
Harald Welteddab3c72009-02-28 13:19:15 +0000624#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000625
Harald Welte8f5e2392009-02-03 12:57:37 +0000626int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
Harald Welte9943c5b2009-07-29 15:41:29 +0200627 u_int8_t ta)
Harald Welte4b634542008-12-27 01:55:51 +0000628{
629 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200630 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200631 int rc;
Harald Welte4b634542008-12-27 01:55:51 +0000632
633 u_int8_t chan_nr = lchan2chan_nr(lchan);
634 u_int16_t arfcn = lchan->ts->trx->arfcn;
635 struct rsl_ie_chan_mode cm;
636 struct rsl_ie_chan_ident ci;
637
Harald Welte9943c5b2009-07-29 15:41:29 +0200638 rc = channel_mode_from_lchan(&cm, lchan);
639 if (rc < 0)
640 return rc;
Harald Welte4b634542008-12-27 01:55:51 +0000641
Harald Welte02b0e092009-02-28 13:11:07 +0000642 memset(&ci, 0, sizeof(ci));
Harald Welte4b634542008-12-27 01:55:51 +0000643 ci.chan_desc.iei = 0x64;
644 ci.chan_desc.chan_nr = chan_nr;
Harald Welte02b0e092009-02-28 13:11:07 +0000645 ci.chan_desc.oct3 = (lchan->ts->trx->bts->tsc << 5) | ((arfcn & 0x3ff) >> 8);
Harald Welte4b634542008-12-27 01:55:51 +0000646 ci.chan_desc.oct4 = arfcn & 0xff;
647
Harald Welteeab33352009-06-27 03:09:08 +0200648 msg = rsl_msgb_alloc();
Harald Welte4b634542008-12-27 01:55:51 +0000649 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
650 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
651 dh->chan_nr = chan_nr;
652
653 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
654 /* For compatibility with Phase 1 */
655 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
656 (u_int8_t *) &cm);
657 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
658 (u_int8_t *) &ci);
Harald Welte4b634542008-12-27 01:55:51 +0000659#if 0
660 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
661 (u_int8_t *) &encr_info);
Harald Welte4b634542008-12-27 01:55:51 +0000662#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000663 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
664 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
Harald Welte4b634542008-12-27 01:55:51 +0000665 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
666
Harald Weltee79769b2009-02-07 00:48:17 +0000667 msg->trx = lchan->ts->trx;
668
Harald Welte4b634542008-12-27 01:55:51 +0000669 return abis_rsl_sendmsg(msg);
670}
671
Harald Welte470abb72009-07-29 11:38:15 +0200672/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welteda783762009-02-18 03:29:53 +0000673int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
674{
675 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200676 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200677 int rc;
Harald Welteda783762009-02-18 03:29:53 +0000678
679 u_int8_t chan_nr = lchan2chan_nr(lchan);
680 struct rsl_ie_chan_mode cm;
681
Harald Welte9943c5b2009-07-29 15:41:29 +0200682 rc = channel_mode_from_lchan(&cm, lchan);
683 if (rc < 0)
684 return rc;
Harald Welteda783762009-02-18 03:29:53 +0000685
Harald Welteeab33352009-06-27 03:09:08 +0200686 msg = rsl_msgb_alloc();
Harald Welteda783762009-02-18 03:29:53 +0000687 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
688 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
689 dh->chan_nr = chan_nr;
690
691 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
692 (u_int8_t *) &cm);
693#if 0
694 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
695 (u_int8_t *) &encr_info);
696#endif
697
698 msg->trx = lchan->ts->trx;
699
700 return abis_rsl_sendmsg(msg);
701}
702
Harald Welteae0f2362009-07-19 18:36:49 +0200703/* Chapter 8.4.5 */
704int rsl_deact_sacch(struct gsm_lchan *lchan)
705{
706 struct abis_rsl_dchan_hdr *dh;
707 struct msgb *msg = rsl_msgb_alloc();
708
709 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
710 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
711 dh->chan_nr = lchan2chan_nr(lchan);
712
713 msg->lchan = lchan;
714 msg->trx = lchan->ts->trx;
715
716 DEBUGP(DRSL, "DEACTivate SACCH CMD channel=%s chan_nr=0x%02x\n",
717 gsm_ts_name(lchan->ts), dh->chan_nr);
718
719 return abis_rsl_sendmsg(msg);
720}
721
Holger Freyther36cbeff2008-12-30 19:15:20 +0000722/* Chapter 9.1.7 of 04.08 */
Harald Welte8470bf22008-12-25 23:28:35 +0000723int rsl_chan_release(struct gsm_lchan *lchan)
Harald Welte52b1f982008-12-23 20:25:15 +0000724{
725 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000726 struct msgb *msg = rsl_msgb_alloc();
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_RF_CHAN_REL);
Harald Welte8470bf22008-12-25 23:28:35 +0000730 dh->chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +0000731
Harald Welte8470bf22008-12-25 23:28:35 +0000732 msg->lchan = lchan;
733 msg->trx = lchan->ts->trx;
734
Harald Weltef325eb42009-02-19 17:07:39 +0000735 DEBUGP(DRSL, "Channel Release CMD channel=%s chan_nr=0x%02x\n",
736 gsm_ts_name(lchan->ts), dh->chan_nr);
Harald Welte2d5b6382008-12-27 19:46:06 +0000737
Harald Welte8470bf22008-12-25 23:28:35 +0000738 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000739}
740
741int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
742 u_int8_t *ms_ident, u_int8_t chan_needed)
743{
744 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000745 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000746
747 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
748 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
749 dh->chan_nr = RSL_CHAN_PCH_AGCH;
750
751 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
Harald Welte255539c2008-12-28 02:26:27 +0000752 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000753 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
754
Harald Welte8470bf22008-12-25 23:28:35 +0000755 msg->trx = bts->c0;
756
757 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000758}
759
Holger Freyther7448a532009-01-04 20:18:23 +0000760int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_need,
761 struct gsm_subscriber *subscr)
762{
Holger Freytherca362a62009-01-04 21:05:01 +0000763#if 0
Holger Freyther7448a532009-01-04 20:18:23 +0000764 u_int8_t mi[128];
765 unsigned int mi_len;
766 u_int8_t paging_group;
Holger Freytherca362a62009-01-04 21:05:01 +0000767#endif
Holger Freyther7448a532009-01-04 20:18:23 +0000768
769 return -1;
770}
771
Harald Welte52b1f982008-12-23 20:25:15 +0000772int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
773{
774 int i, len = strlen(str_in);
775
776 for (i = 0; i < len; i++) {
777 int num = str_in[i] - 0x30;
778 if (num < 0 || num > 9)
779 return -1;
780 if (i % 2 == 0)
781 bcd_out[i/2] = num;
782 else
783 bcd_out[i/2] |= (num << 4);
784 }
785
786 return 0;
787}
788
Harald Welte702d8702008-12-26 20:25:35 +0000789/* Chapter 8.5.6 */
Harald Welte52b1f982008-12-23 20:25:15 +0000790int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val)
791{
Harald Welte8470bf22008-12-25 23:28:35 +0000792 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000793 struct abis_rsl_dchan_hdr *dh;
Harald Welte362322e2009-02-15 14:36:38 +0000794 u_int8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000795
796 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
797 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
798 dh->chan_nr = RSL_CHAN_PCH_AGCH;
799
Harald Welte362322e2009-02-15 14:36:38 +0000800 switch (bts->type) {
801 case GSM_BTS_TYPE_BS11:
802 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
803 break;
804 default:
805 /* If phase 2, construct a FULL_IMM_ASS_INFO */
806 pad_macblock(buf, val, len);
807 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
808 break;
809 }
Harald Welte52b1f982008-12-23 20:25:15 +0000810
Harald Welte8470bf22008-12-25 23:28:35 +0000811 msg->trx = bts->c0;
812
813 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000814}
815
Harald Welte8470bf22008-12-25 23:28:35 +0000816/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000817/* Chapter 8.3.1 */
Harald Welte8470bf22008-12-25 23:28:35 +0000818int rsl_data_request(struct msgb *msg, u_int8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000819{
Harald Welte8470bf22008-12-25 23:28:35 +0000820 u_int8_t l3_len = msg->tail - (u_int8_t *)msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000821 struct abis_rsl_rll_hdr *rh;
822
Harald Welte8470bf22008-12-25 23:28:35 +0000823 if (msg->lchan == NULL) {
824 fprintf(stderr, "cannot send DATA REQUEST to unknown lchan\n");
825 return -EINVAL;
826 }
Harald Welte52b1f982008-12-23 20:25:15 +0000827
Harald Welte8470bf22008-12-25 23:28:35 +0000828 /* First push the L3 IE tag and length */
Harald Welte4b634542008-12-27 01:55:51 +0000829 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
Harald Welte8470bf22008-12-25 23:28:35 +0000830
831 /* Then push the RSL header */
Harald Welte52b1f982008-12-23 20:25:15 +0000832 rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh));
833 init_llm_hdr(rh, RSL_MT_DATA_REQ);
Harald Welte4a543e82009-02-28 13:17:55 +0000834 rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
Harald Welte8470bf22008-12-25 23:28:35 +0000835 rh->chan_nr = lchan2chan_nr(msg->lchan);
836 rh->link_id = link_id;
Harald Welte52b1f982008-12-23 20:25:15 +0000837
Harald Welte8470bf22008-12-25 23:28:35 +0000838 msg->trx = msg->lchan->ts->trx;
839
840 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000841}
842
Harald Welted2dc1de2009-08-08 13:15:07 +0200843/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
844 This is what higher layers should call. The BTS then responds with
845 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
846 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
847 lchan_free() */
848int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id)
849{
850 struct msgb *msg = rsl_msgb_alloc();
851 struct abis_rsl_rll_hdr *rh;
852
853 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
854 init_llm_hdr(rh, RSL_MT_REL_REQ);
855 //rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
856 rh->chan_nr = lchan2chan_nr(lchan);
857 rh->link_id = link_id;
858
859 msg->trx = lchan->ts->trx;
860
861 return abis_rsl_sendmsg(msg);
862}
863
Harald Welte702d8702008-12-26 20:25:35 +0000864/* Chapter 8.4.2: Channel Activate Acknowledge */
865static int rsl_rx_chan_act_ack(struct msgb *msg)
866{
867 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
868
869 /* BTS has confirmed channel activation, we now need
870 * to assign the activated channel to the MS */
Harald Welte4b634542008-12-27 01:55:51 +0000871 if (rslh->ie_chan != RSL_IE_CHAN_NR)
872 return -EINVAL;
873
Harald Welte4b634542008-12-27 01:55:51 +0000874 return 0;
875}
Harald Welte702d8702008-12-26 20:25:35 +0000876
Harald Welte4b634542008-12-27 01:55:51 +0000877/* Chapter 8.4.3: Channel Activate NACK */
878static int rsl_rx_chan_act_nack(struct msgb *msg)
879{
Harald Welte6dab0552009-05-01 17:21:37 +0000880 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
881 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +0000882
Harald Welte6dab0552009-05-01 17:21:37 +0000883 /* BTS has rejected channel activation ?!? */
884 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +0000885 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +0000886
887 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
888 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte8830e072009-07-28 17:58:09 +0200889 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
890 TLVP_LEN(&tp, RSL_IE_CAUSE));
891
Harald Welte4b634542008-12-27 01:55:51 +0000892 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000893}
894
Harald Welte7f93cea2009-02-23 00:02:59 +0000895/* Chapter 8.4.4: Connection Failure Indication */
896static int rsl_rx_conn_fail(struct msgb *msg)
897{
898 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
899 struct tlv_parsed tp;
900
901 DEBUGPC(DRSL, "CONNECTION FAIL: ");
Harald Welte7f93cea2009-02-23 00:02:59 +0000902
903 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
904
Harald Welte8830e072009-07-28 17:58:09 +0200905 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
906 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
907 TLVP_LEN(&tp, RSL_IE_CAUSE));
908
Harald Welte7f93cea2009-02-23 00:02:59 +0000909 if (msg->trx->bts->type == GSM_BTS_TYPE_BS11) {
910 /* FIXME: we have no idea what cause 0x18 is !!! */
911 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE) &&
912 TLVP_LEN(&tp, RSL_IE_CAUSE) >= 1 &&
913 *TLVP_VAL(&tp, RSL_IE_CAUSE) == 0x18) {
Harald Welte73be3aa2009-07-04 10:05:51 +0200914 DEBUGPC(DRSL, "Cause 0x18 IGNORING\n");
915 return 0;
Harald Welte7f93cea2009-02-23 00:02:59 +0000916 }
917 }
918
Holger Freytherf7b2a0e2009-06-02 02:55:17 +0000919 DEBUGPC(DRSL, "RELEASING.\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000920
921 /* FIXME: only free it after channel release ACK */
922 return rsl_chan_release(msg->lchan);
923}
924
Harald Welte440fed02009-05-01 18:43:47 +0000925static int rsl_rx_meas_res(struct msgb *msg)
926{
927 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
928 struct tlv_parsed tp;
929
Harald Welte10d0e672009-06-27 02:53:10 +0200930 DEBUGPC(DMEAS, "MEASUREMENT RESULT ");
Harald Welte440fed02009-05-01 18:43:47 +0000931 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
932
933 if (TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR))
Harald Welte10d0e672009-06-27 02:53:10 +0200934 DEBUGPC(DMEAS, "NR=%d ", *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR));
Harald Welte440fed02009-05-01 18:43:47 +0000935 if (TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS)) {
936 u_int8_t len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte75d34a82009-05-23 06:11:13 +0000937 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte440fed02009-05-01 18:43:47 +0000938 if (len >= 3) {
939 if (val[0] & 0x40)
Harald Welte10d0e672009-06-27 02:53:10 +0200940 DEBUGPC(DMEAS, "DTXd ");
941 DEBUGPC(DMEAS, "RXL-FULL-up=%d RXL-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000942 val[0] & 0x3f, val[1] & 0x3f);
Harald Welte10d0e672009-06-27 02:53:10 +0200943 DEBUGPC(DMEAS, "RXQ-FULL-up=%d RXQ-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000944 val[2]>>3 & 0x7, val[2] & 0x7);
945 }
946 }
947 if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
Harald Welte10d0e672009-06-27 02:53:10 +0200948 DEBUGPC(DMEAS, "BS_POWER=%d ", *TLVP_VAL(&tp, RSL_IE_BS_POWER));
Harald Welte440fed02009-05-01 18:43:47 +0000949 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welte10d0e672009-06-27 02:53:10 +0200950 DEBUGPC(DMEAS, "MS_TO=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000951 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET));
Harald Weltefe9af262009-06-20 18:44:35 +0200952 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Harald Welte86c162d2009-07-12 09:45:05 +0200953 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltefe9af262009-06-20 18:44:35 +0200954 u_int8_t pwr_lvl = val[0] >> 3;
Harald Welte10d0e672009-06-27 02:53:10 +0200955 DEBUGPC(DMEAS, "L1_MS_PWR=%ddBm ",
Harald Weltefe9af262009-06-20 18:44:35 +0200956 ms_pwr_dbm(msg->trx->bts->band, pwr_lvl));
Harald Welte10d0e672009-06-27 02:53:10 +0200957 DEBUGPC(DMEAS, "L1_FPC=%u ", val[0] & 0x04 ? 1 : 0);
958 DEBUGPC(DMEAS, "L1_TA=%u ", val[1]);
Harald Weltefe9af262009-06-20 18:44:35 +0200959 }
Harald Weltef7c43522009-06-09 20:24:21 +0000960 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Harald Welte10d0e672009-06-27 02:53:10 +0200961 DEBUGPC(DMEAS, "L3\n");
Harald Weltef7c43522009-06-09 20:24:21 +0000962 msg->l3h = TLVP_VAL(&tp, RSL_IE_L3_INFO);
963 return gsm0408_rcvmsg(msg);
964 } else
Harald Welte10d0e672009-06-27 02:53:10 +0200965 DEBUGPC(DMEAS, "\n");
Harald Welte60d68f12009-06-05 20:07:43 +0000966
Harald Welte75d34a82009-05-23 06:11:13 +0000967 return 0;
Harald Welte440fed02009-05-01 18:43:47 +0000968}
969
Harald Welte52b1f982008-12-23 20:25:15 +0000970static int abis_rsl_rx_dchan(struct msgb *msg)
971{
Harald Welte8470bf22008-12-25 23:28:35 +0000972 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
973 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +0000974 char *ts_name;
Harald Welte52b1f982008-12-23 20:25:15 +0000975
Harald Welte8470bf22008-12-25 23:28:35 +0000976 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +0000977 ts_name = gsm_ts_name(msg->lchan->ts);
978
Harald Welte10d0e672009-06-27 02:53:10 +0200979 if (rslh->c.msg_type != RSL_MT_MEAS_RES)
980 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ", ts_name, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +0000981
982 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +0000983 case RSL_MT_CHAN_ACTIV_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000984 DEBUGPC(DRSL, "CHANNEL ACTIVATE ACK\n");
Harald Welte4b634542008-12-27 01:55:51 +0000985 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000986 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000987 case RSL_MT_CHAN_ACTIV_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000988 DEBUGPC(DRSL, "CHANNEL ACTIVATE NACK\n");
Harald Welte4b634542008-12-27 01:55:51 +0000989 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000990 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000991 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +0000992 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +0000993 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000994 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +0000995 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +0000996 break;
997 case RSL_MT_RF_CHAN_REL_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +0000998 DEBUGPC(DRSL, "RF CHANNEL RELEASE ACK\n");
Harald Welte2d5b6382008-12-27 19:46:06 +0000999 lchan_free(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +00001000 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001001 case RSL_MT_MODE_MODIFY_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001002 DEBUGPC(DRSL, "CHANNEL MODE MODIFY ACK\n");
Harald Welteda783762009-02-18 03:29:53 +00001003 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001004 case RSL_MT_MODE_MODIFY_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001005 DEBUGPC(DRSL, "CHANNEL MODE MODIFY NACK\n");
Harald Welteda783762009-02-18 03:29:53 +00001006 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001007 case RSL_MT_PHY_CONTEXT_CONF:
1008 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +00001009 case RSL_MT_TALKER_DET:
1010 case RSL_MT_LISTENER_DET:
1011 case RSL_MT_REMOTE_CODEC_CONF_REP:
1012 case RSL_MT_MR_CODEC_MOD_ACK:
1013 case RSL_MT_MR_CODEC_MOD_NACK:
1014 case RSL_MT_MR_CODEC_MOD_PER:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001015 DEBUGPC(DRSL, "Unimplemented Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001016 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001017 break;
1018 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001019 DEBUGPC(DRSL, "unknown Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001020 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001021 return -EINVAL;
1022 }
Harald Weltef325eb42009-02-19 17:07:39 +00001023
Harald Welte8470bf22008-12-25 23:28:35 +00001024 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001025}
1026
Harald Welte702d8702008-12-26 20:25:35 +00001027static int rsl_rx_error_rep(struct msgb *msg)
1028{
1029 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +02001030 struct tlv_parsed tp;
Harald Welte702d8702008-12-26 20:25:35 +00001031
Harald Welte7f93cea2009-02-23 00:02:59 +00001032 DEBUGP(DRSL, "ERROR REPORT ");
Harald Welte8830e072009-07-28 17:58:09 +02001033
1034 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1035
1036 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
1037 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
1038 TLVP_LEN(&tp, RSL_IE_CAUSE));
1039
Holger Freyther79f4ae62009-06-02 03:25:04 +00001040 DEBUGPC(DRSL, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001041
1042 return 0;
1043}
1044
Harald Welte52b1f982008-12-23 20:25:15 +00001045static int abis_rsl_rx_trx(struct msgb *msg)
1046{
Harald Welte702d8702008-12-26 20:25:35 +00001047 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001048 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001049
1050 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001051 case RSL_MT_ERROR_REPORT:
1052 rc = rsl_rx_error_rep(msg);
1053 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001054 case RSL_MT_RF_RES_IND:
1055 /* interference on idle channels of TRX */
Harald Welte3cf7c3f2009-05-01 18:28:00 +00001056 //DEBUGP(DRSL, "TRX: RF Interference Indication\n");
Harald Welte8f5e2392009-02-03 12:57:37 +00001057 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001058 case RSL_MT_OVERLOAD:
1059 /* indicate CCCH / ACCH / processor overload */
Harald Weltef325eb42009-02-19 17:07:39 +00001060 DEBUGP(DRSL, "TRX: CCCH/ACCH/CPU Overload\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001061 break;
1062 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001063 DEBUGP(DRSL, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001064 rslh->msg_type);
1065 return -EINVAL;
1066 }
Harald Welte8470bf22008-12-25 23:28:35 +00001067 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001068}
1069
Harald Welte8470bf22008-12-25 23:28:35 +00001070/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001071static int rsl_rx_chan_rqd(struct msgb *msg)
1072{
Harald Welte702d8702008-12-26 20:25:35 +00001073 struct gsm_bts *bts = msg->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001074 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1075 struct gsm48_req_ref *rqd_ref;
Harald Welte52b1f982008-12-23 20:25:15 +00001076 struct gsm48_imm_ass ia;
Harald Welte8470bf22008-12-25 23:28:35 +00001077 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001078 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001079 struct gsm_lchan *lchan;
1080 u_int8_t rqd_ta;
Holger Freyther3186bf22008-12-29 06:23:49 +00001081 int ret;
Harald Welte8470bf22008-12-25 23:28:35 +00001082
Harald Welte52b1f982008-12-23 20:25:15 +00001083 u_int16_t arfcn;
1084 u_int8_t ts_number, subch;
1085
Harald Welte8470bf22008-12-25 23:28:35 +00001086 /* parse request reference to be used in immediate assign */
1087 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1088 return -EINVAL;
1089
1090 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1091
1092 /* parse access delay and use as TA */
1093 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1094 return -EINVAL;
1095 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1096
1097 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1098 * request reference RA */
1099 lctype = get_ctype_by_chreq(bts, rqd_ref->ra);
Harald Welte2cbe0922008-12-29 04:09:31 +00001100 chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra);
1101
Harald Welte8470bf22008-12-25 23:28:35 +00001102 /* check availability / allocate channel */
1103 lchan = lchan_alloc(bts, lctype);
1104 if (!lchan) {
1105 fprintf(stderr, "CHAN RQD: no resources\n");
1106 /* FIXME: send some kind of reject ?!? */
1107 return -ENOMEM;
1108 }
1109
1110 ts_number = lchan->ts->nr;
1111 arfcn = lchan->ts->trx->arfcn;
1112 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001113
Harald Weltef89abbd2009-08-04 02:31:55 +02001114 lchan->ms_power = ms_pwr_ctl_lvl(bts, 20 /* dBm == 100mW */);
1115 lchan->bs_power = 0x0f; /* 30dB reduction */
Harald Welte9943c5b2009-07-29 15:41:29 +02001116 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
1117 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
Harald Welte52b1f982008-12-23 20:25:15 +00001118
1119 /* create IMMEDIATE ASSIGN 04.08 messge */
1120 memset(&ia, 0, sizeof(ia));
1121 ia.l2_plen = 0x2d;
1122 ia.proto_discr = GSM48_PDISC_RR;
1123 ia.msg_type = GSM48_MT_RR_IMM_ASS;
Harald Welte2d5b6382008-12-27 19:46:06 +00001124 ia.page_mode = GSM48_PM_SAME;
Harald Welte4b634542008-12-27 01:55:51 +00001125 ia.chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +00001126 ia.chan_desc.h0.h = 0;
1127 ia.chan_desc.h0.arfcn_high = arfcn >> 8;
1128 ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
Harald Welte814c4b72009-07-21 20:55:56 +02001129 ia.chan_desc.h0.tsc = bts->tsc;
Harald Welte8470bf22008-12-25 23:28:35 +00001130 /* use request reference extracted from CHAN_RQD */
1131 memcpy(&ia.req_ref, rqd_ref, sizeof(ia.req_ref));
1132 ia.timing_advance = rqd_ta;
Harald Welte52b1f982008-12-23 20:25:15 +00001133 ia.mob_alloc_len = 0;
1134
Harald Welte8f5e2392009-02-03 12:57:37 +00001135 DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %s "
Holger Freyther79f4ae62009-06-02 03:25:04 +00001136 "chan_nr=0x%02x r=%s ra=0x%02x\n",
Harald Welteca64da92009-01-04 16:54:12 +00001137 arfcn, ts_number, subch, gsm_lchan_name(lchan->type),
Harald Welte4a543e82009-02-28 13:17:55 +00001138 ia.chan_desc.chan_nr, gsm_chreq_name(chreq_reason),
1139 rqd_ref->ra);
Harald Welte75a983f2008-12-27 21:34:06 +00001140
Harald Welte09e38af2009-02-16 22:52:23 +00001141 /* FIXME: Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
Holger Freyther3186bf22008-12-29 06:23:49 +00001142
Harald Welte52b1f982008-12-23 20:25:15 +00001143 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Freyther3186bf22008-12-29 06:23:49 +00001144 ret = rsl_imm_assign_cmd(bts, sizeof(ia), (u_int8_t *) &ia);
1145
Harald Welte817f3c82008-12-30 14:57:59 +00001146 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001147}
1148
Harald Welteea280442009-02-02 22:29:56 +00001149/* MS has requested a channel on the RACH */
1150static int rsl_rx_ccch_load(struct msgb *msg)
1151{
1152 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1153 u_int16_t pg_buf_space;
Holger Freyther8c563cf2009-02-03 20:08:51 +00001154 u_int16_t rach_slot_count = -1;
1155 u_int16_t rach_busy_count = -1;
1156 u_int16_t rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001157
1158 switch (rslh->data[0]) {
1159 case RSL_IE_PAGING_LOAD:
1160 pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
Holger Freyther392209c2009-02-10 00:06:19 +00001161 paging_update_buffer_space(msg->trx->bts, pg_buf_space);
Harald Welteea280442009-02-02 22:29:56 +00001162 break;
1163 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001164 if (msg->data_len >= 7) {
1165 rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1166 rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1167 rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1168 }
Harald Welteea280442009-02-02 22:29:56 +00001169 break;
1170 default:
1171 break;
1172 }
1173
1174 return 0;
1175}
1176
Harald Welte52b1f982008-12-23 20:25:15 +00001177static int abis_rsl_rx_cchan(struct msgb *msg)
1178{
Harald Welteea280442009-02-02 22:29:56 +00001179 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001180 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001181
Harald Welte8470bf22008-12-25 23:28:35 +00001182 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
1183
1184 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001185 case RSL_MT_CHAN_RQD:
1186 /* MS has requested a channel on the RACH */
1187 rc = rsl_rx_chan_rqd(msg);
1188 break;
Harald Welteea280442009-02-02 22:29:56 +00001189 case RSL_MT_CCCH_LOAD_IND:
1190 /* current load on the CCCH */
1191 rc = rsl_rx_ccch_load(msg);
1192 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001193 case RSL_MT_DELETE_IND:
1194 /* CCCH overloaded, IMM_ASSIGN was dropped */
1195 case RSL_MT_CBCH_LOAD_IND:
1196 /* current load on the CBCH */
Harald Welte8f5e2392009-02-03 12:57:37 +00001197 fprintf(stderr, "Unimplemented Abis RSL TRX message type "
1198 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001199 break;
1200 default:
1201 fprintf(stderr, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001202 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001203 return -EINVAL;
1204 }
Harald Welte8470bf22008-12-25 23:28:35 +00001205
1206 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001207}
1208
Harald Welte4b634542008-12-27 01:55:51 +00001209static int rsl_rx_rll_err_ind(struct msgb *msg)
1210{
1211 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1212 u_int8_t *rlm_cause = rllh->data;
1213
Harald Welte602f2b82009-08-04 02:50:21 +02001214 DEBUGPC(DRLL, "ERROR INDICATION cause=0x%02x\n", rlm_cause[1]);
Harald Welte4b634542008-12-27 01:55:51 +00001215
Harald Welte81543bc2009-07-04 09:40:05 +02001216 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED)
1217 return rsl_chan_release(msg->lchan);
1218
Harald Welte4b634542008-12-27 01:55:51 +00001219 return 0;
1220}
Harald Weltef325eb42009-02-19 17:07:39 +00001221
Harald Welte52b1f982008-12-23 20:25:15 +00001222/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
1223 0x02, 0x06,
1224 0x01, 0x20,
1225 0x02, 0x00,
1226 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1227
1228static int abis_rsl_rx_rll(struct msgb *msg)
1229{
1230 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001231 int rc = 0;
1232 char *ts_name;
Harald Welte8470bf22008-12-25 23:28:35 +00001233
1234 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001235 ts_name = gsm_ts_name(msg->lchan->ts);
1236 DEBUGP(DRLL, "channel=%s chan_nr=0x%02x ", ts_name, rllh->chan_nr);
Harald Welte52b1f982008-12-23 20:25:15 +00001237
1238 switch (rllh->c.msg_type) {
1239 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001240 DEBUGPC(DRLL, "DATA INDICATION\n");
Harald Welte4a543e82009-02-28 13:17:55 +00001241 if (msgb_l2len(msg) >
1242 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1243 rllh->data[0] == RSL_IE_L3_INFO) {
1244 msg->l3h = &rllh->data[3];
1245 return gsm0408_rcvmsg(msg);
1246 }
Harald Welte52b1f982008-12-23 20:25:15 +00001247 break;
1248 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001249 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte4a543e82009-02-28 13:17:55 +00001250 if (msgb_l2len(msg) >
1251 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1252 rllh->data[0] == RSL_IE_L3_INFO) {
1253 msg->l3h = &rllh->data[3];
1254 return gsm0408_rcvmsg(msg);
1255 }
Harald Welte52b1f982008-12-23 20:25:15 +00001256 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001257 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001258 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001259 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Harald Welted2dc1de2009-08-08 13:15:07 +02001260 /* we can now releae the channel on the BTS/Abis side */
1261 rsl_chan_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001262 break;
1263 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001264 /* BTS informs us of having received UA from MS,
1265 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001266 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Harald Welted2dc1de2009-08-08 13:15:07 +02001267 /* we can now releae the channel on the BTS/Abis side */
1268 rsl_chan_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001269 break;
1270 case RSL_MT_ERROR_IND:
1271 rc = rsl_rx_rll_err_ind(msg);
1272 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001273 case RSL_MT_UNIT_DATA_IND:
Harald Welte602f2b82009-08-04 02:50:21 +02001274 DEBUGPC(DRLL, "unimplemented Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001275 rllh->c.msg_type);
1276 break;
1277 default:
Harald Welte602f2b82009-08-04 02:50:21 +02001278 DEBUGPC(DRLL, "unknown Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001279 rllh->c.msg_type);
1280 }
Harald Welte8470bf22008-12-25 23:28:35 +00001281 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001282}
1283
Harald Weltef4e79f22009-07-28 18:11:56 +02001284static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
1285{
Harald Weltef4e79f22009-07-28 18:11:56 +02001286 switch (tch_mode) {
1287 case GSM48_CMODE_SPEECH_V1:
1288 return 0x00;
1289 case GSM48_CMODE_SPEECH_EFR:
1290 return 0x01;
1291 case GSM48_CMODE_SPEECH_AMR:
1292 return 0x02;
1293 /* FIXME: Type1 half-rate and type3 half-rate */
1294 }
Harald Welte58ca5b72009-07-29 12:12:18 +02001295 DEBUGPC(DRSL, "Cannot determine ip.access speech mode for "
1296 "tch_mode == 0x%02x\n", tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001297 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001298}
1299
Harald Welte75099262009-02-16 21:12:08 +00001300/* ip.access specific RSL extensions */
1301int rsl_ipacc_bind(struct gsm_lchan *lchan)
1302{
1303 struct msgb *msg = rsl_msgb_alloc();
1304 struct abis_rsl_dchan_hdr *dh;
Harald Welte58ca5b72009-07-29 12:12:18 +02001305 u_int8_t speech_mode;
Harald Welte75099262009-02-16 21:12:08 +00001306
1307 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1308 init_dchan_hdr(dh, RSL_MT_IPAC_BIND);
1309 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1310 dh->chan_nr = lchan2chan_nr(lchan);
1311
Harald Weltef4e79f22009-07-28 18:11:56 +02001312 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte58ca5b72009-07-29 12:12:18 +02001313 speech_mode = 0x10 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1314 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001315
Harald Welte58ca5b72009-07-29 12:12:18 +02001316 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND "
1317 "speech_mode=0x%02x\n", gsm_ts_name(lchan->ts),
1318 dh->chan_nr, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001319
Harald Welte75099262009-02-16 21:12:08 +00001320 msg->trx = lchan->ts->trx;
1321
1322 return abis_rsl_sendmsg(msg);
1323}
1324
Harald Welte20855542009-07-12 09:50:35 +02001325int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
1326 u_int16_t conn_id, u_int8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001327{
1328 struct msgb *msg = rsl_msgb_alloc();
1329 struct abis_rsl_dchan_hdr *dh;
1330 u_int8_t *att_f8, *att_ip, *att_port;
Harald Welte58ca5b72009-07-29 12:12:18 +02001331 u_int8_t speech_mode;
Harald Weltef4e79f22009-07-28 18:11:56 +02001332 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001333
1334 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1335 init_dchan_hdr(dh, RSL_MT_IPAC_CONNECT);
1336 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1337 dh->chan_nr = lchan2chan_nr(lchan);
1338
Harald Welte58ca5b72009-07-29 12:12:18 +02001339 /* 0x0- == both directions, 0x-1 == EFR codec */
1340 speech_mode = 0x00 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1341
Harald Weltef4e79f22009-07-28 18:11:56 +02001342 ia.s_addr = htonl(ip);
Harald Welte58ca5b72009-07-29 12:12:18 +02001343 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_CONNECT "
1344 "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d speech_mode=0x%02x\n",
Harald Weltef4e79f22009-07-28 18:11:56 +02001345 gsm_ts_name(lchan->ts), dh->chan_nr,
Harald Welte58ca5b72009-07-29 12:12:18 +02001346 inet_ntoa(ia), port, rtp_payload2, conn_id, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001347
Harald Welte20855542009-07-12 09:50:35 +02001348 att_f8 = msgb_put(msg, sizeof(conn_id)+1);
Harald Welte86c162d2009-07-12 09:45:05 +02001349 att_f8[0] = RSL_IE_IPAC_CONN_ID;
Harald Welte20855542009-07-12 09:50:35 +02001350 att_f8[1] = conn_id >> 8;
1351 att_f8[2] = conn_id & 0xff;
Harald Welte75099262009-02-16 21:12:08 +00001352
1353 att_ip = msgb_put(msg, sizeof(ip)+1);
1354 att_ip[0] = RSL_IE_IPAC_REMOTE_IP;
1355 att_ip[1] = ip >> 24;
1356 att_ip[2] = ip >> 16;
1357 att_ip[3] = ip >> 8;
1358 att_ip[4] = ip & 0xff;
Harald Welteda783762009-02-18 03:29:53 +00001359 //att_ip[4] = 11;
Harald Welte75099262009-02-16 21:12:08 +00001360
1361 att_port = msgb_put(msg, sizeof(port)+1);
1362 att_port[0] = RSL_IE_IPAC_REMOTE_PORT;
1363 att_port[1] = port >> 8;
1364 att_port[2] = port & 0xff;
1365
Harald Welte58ca5b72009-07-29 12:12:18 +02001366 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001367 if (rtp_payload2)
1368 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
1369
Harald Welte75099262009-02-16 21:12:08 +00001370 msg->trx = lchan->ts->trx;
1371
1372 return abis_rsl_sendmsg(msg);
1373}
1374
1375static int abis_rsl_rx_ipacc_bindack(struct msgb *msg)
1376{
1377 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1378 struct tlv_parsed tv;
1379 struct gsm_bts_trx_ts *ts = msg->lchan->ts;
Harald Welte167df882009-02-17 14:35:45 +00001380 struct in_addr ip;
Harald Welte75099262009-02-16 21:12:08 +00001381 u_int16_t port, attr_f8;
1382
1383 /* the BTS has acknowledged a local bind, it now tells us the IP
1384 * address and port number to which it has bound the given logical
1385 * channel */
1386
1387 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1388 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1389 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02001390 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltef325eb42009-02-19 17:07:39 +00001391 DEBUGPC(DRSL, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001392 return -EINVAL;
1393 }
Harald Welte167df882009-02-17 14:35:45 +00001394 ip.s_addr = *((u_int32_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte75099262009-02-16 21:12:08 +00001395 port = *((u_int16_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_PORT));
1396 attr_f8 = *((u_int16_t *) TLVP_VAL(&tv, 0xf8));
1397
Harald Weltef4e79f22009-07-28 18:11:56 +02001398 DEBUGPC(DRSL, "IP=%s PORT=%d CONN_ID=%d ",
1399 inet_ntoa(ip), ntohs(port), ntohs(attr_f8));
1400
1401 if (TLVP_PRESENT(&tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1402 ts->abis_ip.rtp_payload2 =
1403 *TLVP_VAL(&tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1404 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1405 ts->abis_ip.rtp_payload2);
1406 }
Harald Welte167df882009-02-17 14:35:45 +00001407
Harald Welte75099262009-02-16 21:12:08 +00001408 /* update our local information about this TS */
Harald Welte167df882009-02-17 14:35:45 +00001409 ts->abis_ip.bound_ip = ntohl(ip.s_addr);
1410 ts->abis_ip.bound_port = ntohs(port);
Harald Welte20855542009-07-12 09:50:35 +02001411 ts->abis_ip.conn_id = ntohs(attr_f8);
Harald Welte75099262009-02-16 21:12:08 +00001412
Harald Welte167df882009-02-17 14:35:45 +00001413 dispatch_signal(SS_ABISIP, S_ABISIP_BIND_ACK, msg->lchan);
1414
Harald Welte75099262009-02-16 21:12:08 +00001415 return 0;
1416}
1417
1418static int abis_rsl_rx_ipacc_disc_ind(struct msgb *msg)
1419{
1420 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1421 struct tlv_parsed tv;
1422
1423 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00001424
Harald Welte8830e072009-07-28 17:58:09 +02001425 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
1426 print_rsl_cause(TLVP_VAL(&tv, RSL_IE_CAUSE),
1427 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001428
Harald Welte888b1142009-07-28 18:02:05 +02001429 dispatch_signal(SS_ABISIP, S_ABISIP_DISC_IND, msg->lchan);
1430
Harald Welte75099262009-02-16 21:12:08 +00001431 return 0;
1432}
1433
1434static int abis_rsl_rx_ipacc(struct msgb *msg)
1435{
1436 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1437 int rc = 0;
1438
1439 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001440 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ",
1441 gsm_ts_name(msg->lchan->ts), rllh->chan_nr);
Harald Welte75099262009-02-16 21:12:08 +00001442
1443 switch (rllh->c.msg_type) {
1444 case RSL_MT_IPAC_BIND_ACK:
Harald Welte4a543e82009-02-28 13:17:55 +00001445 DEBUGPC(DRSL, "IPAC_BIND_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001446 rc = abis_rsl_rx_ipacc_bindack(msg);
1447 break;
1448 case RSL_MT_IPAC_BIND_NACK:
1449 /* somehow the BTS was unable to bind the lchan to its local
1450 * port?!? */
Harald Weltef325eb42009-02-19 17:07:39 +00001451 DEBUGPC(DRSL, "IPAC_BIND_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001452 break;
1453 case RSL_MT_IPAC_CONNECT_ACK:
1454 /* the BTS tells us that a connect operation was successful */
Harald Weltef325eb42009-02-19 17:07:39 +00001455 DEBUGPC(DRSL, "IPAC_CONNECT_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001456 break;
1457 case RSL_MT_IPAC_CONNECT_NACK:
1458 /* somehow the BTS was unable to connect the lchan to a remote
1459 * port */
Harald Weltef325eb42009-02-19 17:07:39 +00001460 DEBUGPC(DRSL, "IPAC_CONNECT_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001461 break;
1462 case RSL_MT_IPAC_DISCONNECT_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001463 DEBUGPC(DRSL, "IPAC_DISCONNECT_IND ");
Harald Welte75099262009-02-16 21:12:08 +00001464 rc = abis_rsl_rx_ipacc_disc_ind(msg);
1465 break;
1466 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001467 DEBUGPC(DRSL, "Unknown ip.access msg_type 0x%02x", rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001468 break;
1469 }
Harald Welte6dab0552009-05-01 17:21:37 +00001470 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001471
1472 return rc;
1473}
1474
1475
Harald Welte52b1f982008-12-23 20:25:15 +00001476/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001477int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001478{
1479 struct abis_rsl_common_hdr *rslh = msgb_l2(msg) ;
Harald Welte8f5e2392009-02-03 12:57:37 +00001480 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001481
1482 switch (rslh->msg_discr & 0xfe) {
1483 case ABIS_RSL_MDISC_RLL:
1484 rc = abis_rsl_rx_rll(msg);
1485 break;
1486 case ABIS_RSL_MDISC_DED_CHAN:
1487 rc = abis_rsl_rx_dchan(msg);
1488 break;
1489 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00001490 rc = abis_rsl_rx_cchan(msg);
1491 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001492 case ABIS_RSL_MDISC_TRX:
1493 rc = abis_rsl_rx_trx(msg);
1494 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001495 case ABIS_RSL_MDISC_LOC:
Harald Welte8f5e2392009-02-03 12:57:37 +00001496 fprintf(stderr, "unimplemented RSL msg disc 0x%02x\n",
1497 rslh->msg_discr);
1498 break;
Harald Welte75099262009-02-16 21:12:08 +00001499 case ABIS_RSL_MDISC_IPACCESS:
1500 rc = abis_rsl_rx_ipacc(msg);
1501 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001502 default:
1503 fprintf(stderr, "unknown RSL message discriminator 0x%02x\n",
1504 rslh->msg_discr);
1505 return -EINVAL;
1506 }
Harald Welte4f4a3902008-12-26 00:04:49 +00001507 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001508 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001509}
Holger Freyther3b72a892009-02-04 00:31:39 +00001510
1511
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001512/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
Holger Freyther3b72a892009-02-04 00:31:39 +00001513int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf)
1514{
1515 switch (ccch_conf) {
1516 case RSL_BCCH_CCCH_CONF_1_NC:
1517 return 1;
1518 case RSL_BCCH_CCCH_CONF_1_C:
1519 return 1;
1520 case RSL_BCCH_CCCH_CONF_2_NC:
1521 return 2;
1522 case RSL_BCCH_CCCH_CONF_3_NC:
1523 return 3;
1524 case RSL_BCCH_CCCH_CONF_4_NC:
1525 return 4;
1526 default:
1527 return -1;
1528 }
1529}
1530
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001531/* Section 3.3.2.3 TS 05.02 */
Holger Freyther3b72a892009-02-04 00:31:39 +00001532int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf)
1533{
1534 switch (ccch_conf) {
1535 case RSL_BCCH_CCCH_CONF_1_NC:
1536 return 0;
1537 case RSL_BCCH_CCCH_CONF_1_C:
1538 return 1;
1539 case RSL_BCCH_CCCH_CONF_2_NC:
1540 return 0;
1541 case RSL_BCCH_CCCH_CONF_3_NC:
1542 return 0;
1543 case RSL_BCCH_CCCH_CONF_4_NC:
1544 return 0;
1545 default:
1546 return -1;
1547 }
1548}
1549
1550/* From Table 10.5.33 of GSM 04.08 */
1551int rsl_number_of_paging_subchannels(struct gsm_bts *bts)
1552{
1553 if (bts->chan_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) {
1554 return MAX(1, (3 - bts->chan_desc.bs_ag_blks_res))
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001555 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001556 } else {
1557 return (9 - bts->chan_desc.bs_ag_blks_res)
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001558 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001559 }
1560}