blob: f5a0f6dcb26026da96e4e4f2c7612ba058129253 [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>
Harald Welteedcc5272009-08-09 13:47:35 +020035#include <openbsc/bsc_rll.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/debug.h>
37#include <openbsc/tlv.h>
Holger Freyther392209c2009-02-10 00:06:19 +000038#include <openbsc/paging.h>
Harald Welte167df882009-02-17 14:35:45 +000039#include <openbsc/signal.h>
Harald Welte52b1f982008-12-23 20:25:15 +000040
Harald Welte8470bf22008-12-25 23:28:35 +000041#define RSL_ALLOC_SIZE 1024
42#define RSL_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000043
Holger Freyther3b72a892009-02-04 00:31:39 +000044#define MAX(a, b) (a) >= (b) ? (a) : (b)
45
Harald Welte75099262009-02-16 21:12:08 +000046static const struct tlv_definition rsl_att_tlvdef = {
47 .def = {
48 [RSL_IE_CHAN_NR] = { TLV_TYPE_TV },
49 [RSL_IE_LINK_IDENT] = { TLV_TYPE_TV },
50 [RSL_IE_ACT_TYPE] = { TLV_TYPE_TV },
51 [RSL_IE_BS_POWER] = { TLV_TYPE_TV },
52 [RSL_IE_CHAN_IDENT] = { TLV_TYPE_TLV },
53 [RSL_IE_CHAN_MODE] = { TLV_TYPE_TLV },
54 [RSL_IE_ENCR_INFO] = { TLV_TYPE_TLV },
55 [RSL_IE_FRAME_NUMBER] = { TLV_TYPE_FIXED, 2 },
56 [RSL_IE_HANDO_REF] = { TLV_TYPE_TV },
57 [RSL_IE_L1_INFO] = { TLV_TYPE_FIXED, 2 },
58 [RSL_IE_L3_INFO] = { TLV_TYPE_TL16V },
59 [RSL_IE_MS_IDENTITY] = { TLV_TYPE_TLV },
60 [RSL_IE_MS_POWER] = { TLV_TYPE_TV },
61 [RSL_IE_PAGING_GROUP] = { TLV_TYPE_TV },
62 [RSL_IE_PAGING_LOAD] = { TLV_TYPE_FIXED, 2 },
63 [RSL_IE_PYHS_CONTEXT] = { TLV_TYPE_TLV },
64 [RSL_IE_ACCESS_DELAY] = { TLV_TYPE_TV },
65 [RSL_IE_RACH_LOAD] = { TLV_TYPE_TLV },
66 [RSL_IE_REQ_REFERENCE] = { TLV_TYPE_FIXED, 3 },
67 [RSL_IE_RELEASE_MODE] = { TLV_TYPE_TV },
68 [RSL_IE_RESOURCE_INFO] = { TLV_TYPE_TLV },
69 [RSL_IE_RLM_CAUSE] = { TLV_TYPE_TLV },
70 [RSL_IE_STARTNG_TIME] = { TLV_TYPE_FIXED, 2 },
71 [RSL_IE_TIMING_ADVANCE] = { TLV_TYPE_TV },
72 [RSL_IE_UPLINK_MEAS] = { TLV_TYPE_TLV },
73 [RSL_IE_CAUSE] = { TLV_TYPE_TLV },
74 [RSL_IE_MEAS_RES_NR] = { TLV_TYPE_TV },
75 [RSL_IE_MSG_ID] = { TLV_TYPE_TV },
76 [RSL_IE_SYSINFO_TYPE] = { TLV_TYPE_TV },
77 [RSL_IE_MS_POWER_PARAM] = { TLV_TYPE_TLV },
78 [RSL_IE_BS_POWER_PARAM] = { TLV_TYPE_TLV },
79 [RSL_IE_PREPROC_PARAM] = { TLV_TYPE_TLV },
80 [RSL_IE_PREPROC_MEAS] = { TLV_TYPE_TLV },
81 [RSL_IE_IMM_ASS_INFO] = { TLV_TYPE_TLV },
82 [RSL_IE_SMSCB_INFO] = { TLV_TYPE_FIXED, 23 },
83 [RSL_IE_MS_TIMING_OFFSET] = { TLV_TYPE_TV },
84 [RSL_IE_ERR_MSG] = { TLV_TYPE_TLV },
85 [RSL_IE_FULL_BCCH_INFO] = { TLV_TYPE_TLV },
86 [RSL_IE_CHAN_NEEDED] = { TLV_TYPE_TV },
87 [RSL_IE_CB_CMD_TYPE] = { TLV_TYPE_TV },
88 [RSL_IE_SMSCB_MSG] = { TLV_TYPE_TLV },
89 [RSL_IE_FULL_IMM_ASS_INFO] = { TLV_TYPE_TLV },
90 [RSL_IE_SACCH_INFO] = { TLV_TYPE_TLV },
91 [RSL_IE_CBCH_LOAD_INFO] = { TLV_TYPE_TV },
92 [RSL_IE_SMSCB_CHAN_INDICATOR] = { TLV_TYPE_TV },
93 [RSL_IE_GROUP_CALL_REF] = { TLV_TYPE_TLV },
94 [RSL_IE_CHAN_DESC] = { TLV_TYPE_TLV },
95 [RSL_IE_NCH_DRX_INFO] = { TLV_TYPE_TLV },
96 [RSL_IE_CMD_INDICATOR] = { TLV_TYPE_TLV },
97 [RSL_IE_EMLPP_PRIO] = { TLV_TYPE_TV },
98 [RSL_IE_UIC] = { TLV_TYPE_TLV },
99 [RSL_IE_MAIN_CHAN_REF] = { TLV_TYPE_TV },
100 [RSL_IE_MR_CONFIG] = { TLV_TYPE_TLV },
101 [RSL_IE_MR_CONTROL] = { TLV_TYPE_TV },
102 [RSL_IE_SUP_CODEC_TYPES] = { TLV_TYPE_TLV },
103 [RSL_IE_CODEC_CONFIG] = { TLV_TYPE_TLV },
104 [RSL_IE_RTD] = { TLV_TYPE_TV },
105 [RSL_IE_TFO_STATUS] = { TLV_TYPE_TV },
106 [RSL_IE_LLP_APDU] = { TLV_TYPE_TLV },
Harald Welteab46d742009-07-12 09:56:39 +0200107 [RSL_IE_IPAC_PROXY_UDP] = { TLV_TYPE_FIXED, 2 },
108 [RSL_IE_IPAC_BSCMPL_TOUT] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000109 [RSL_IE_IPAC_REMOTE_IP] = { TLV_TYPE_FIXED, 4 },
110 [RSL_IE_IPAC_REMOTE_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200111 [RSL_IE_IPAC_RTP_PAYLOAD] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000112 [RSL_IE_IPAC_LOCAL_PORT] = { TLV_TYPE_FIXED, 2 },
Harald Welte86c162d2009-07-12 09:45:05 +0200113 [RSL_IE_IPAC_SPEECH_MODE] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200114 [RSL_IE_IPAC_LOCAL_IP] = { TLV_TYPE_FIXED, 4 },
Harald Welte86c162d2009-07-12 09:45:05 +0200115 [RSL_IE_IPAC_CONN_ID] = { TLV_TYPE_FIXED, 2 },
Harald Welteab46d742009-07-12 09:56:39 +0200116 [RSL_IE_IPAC_RTP_CSD_FMT] = { TLV_TYPE_TV },
117 [RSL_IE_IPAC_RTP_JIT_BUF] = { TLV_TYPE_FIXED, 2 },
118 [RSL_IE_IPAC_RTP_COMPR] = { TLV_TYPE_TV },
Harald Welte86c162d2009-07-12 09:45:05 +0200119 [RSL_IE_IPAC_RTP_PAYLOAD2] = { TLV_TYPE_TV },
Harald Welteab46d742009-07-12 09:56:39 +0200120 [RSL_IE_IPAC_RTP_MPLEX] = { TLV_TYPE_FIXED, 8 },
121 [RSL_IE_IPAC_RTP_MPLEX_ID] = { TLV_TYPE_TV },
Harald Welte75099262009-02-16 21:12:08 +0000122 },
123};
Harald Weltea4d49e92009-05-23 06:39:58 +0000124#define rsl_tlv_parse(dec, buf, len) \
125 tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0)
Harald Welte75099262009-02-16 21:12:08 +0000126
Harald Welte52b1f982008-12-23 20:25:15 +0000127static u_int8_t mdisc_by_msgtype(u_int8_t msg_type)
128{
129 /* mask off the transparent bit ? */
130 msg_type &= 0xfe;
131
Harald Welte8470bf22008-12-25 23:28:35 +0000132 if ((msg_type & 0xf0) == 0x00)
Harald Welte52b1f982008-12-23 20:25:15 +0000133 return ABIS_RSL_MDISC_RLL;
Harald Welte8470bf22008-12-25 23:28:35 +0000134 if ((msg_type & 0xf0) == 0x10) {
Harald Welte52b1f982008-12-23 20:25:15 +0000135 if (msg_type >= 0x19 && msg_type <= 0x22)
136 return ABIS_RSL_MDISC_TRX;
137 else
138 return ABIS_RSL_MDISC_COM_CHAN;
139 }
Harald Welte2d5b6382008-12-27 19:46:06 +0000140 if ((msg_type & 0xe0) == 0x20)
Harald Welte52b1f982008-12-23 20:25:15 +0000141 return ABIS_RSL_MDISC_DED_CHAN;
142
143 return ABIS_RSL_MDISC_LOC;
144}
145
146static inline void init_dchan_hdr(struct abis_rsl_dchan_hdr *dh,
147 u_int8_t msg_type)
148{
149 dh->c.msg_discr = mdisc_by_msgtype(msg_type);
150 dh->c.msg_type = msg_type;
151 dh->ie_chan = RSL_IE_CHAN_NR;
152}
153
154static inline void init_llm_hdr(struct abis_rsl_rll_hdr *dh,
155 u_int8_t msg_type)
156{
157 /* dh->c.msg_discr = mdisc_by_msgtype(msg_type); */
158 dh->c.msg_discr = ABIS_RSL_MDISC_RLL;
159 dh->c.msg_type = msg_type;
160 dh->ie_chan = RSL_IE_CHAN_NR;
161 dh->ie_link_id = RSL_IE_LINK_IDENT;
162}
163
164
165/* encode channel number as per Section 9.3.1 */
166u_int8_t rsl_enc_chan_nr(u_int8_t type, u_int8_t subch, u_int8_t timeslot)
167{
168 u_int8_t ret;
169
170 ret = (timeslot & 0x07) | type;
171
172 switch (type) {
173 case RSL_CHAN_Lm_ACCHs:
174 subch &= 0x01;
175 break;
176 case RSL_CHAN_SDCCH4_ACCH:
177 subch &= 0x07;
178 break;
179 case RSL_CHAN_SDCCH8_ACCH:
180 subch &= 0x07;
181 break;
182 default:
183 /* no subchannels allowed */
184 subch = 0x00;
185 break;
186 }
187 ret |= (subch << 3);
188
189 return ret;
190}
191
Harald Welte8470bf22008-12-25 23:28:35 +0000192/* determine logical channel based on TRX and channel number IE */
193struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
194{
195 struct gsm_lchan *lchan;
196 u_int8_t ts_nr = chan_nr & 0x07;
197 u_int8_t cbits = chan_nr >> 3;
198 u_int8_t lch_idx;
199 struct gsm_bts_trx_ts *ts = &trx->ts[ts_nr];
200
201 if (cbits == 0x01) {
202 lch_idx = 0; /* TCH/F */
203 if (ts->pchan != GSM_PCHAN_TCH_F)
204 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
205 chan_nr, ts->pchan);
206 } else if ((cbits & 0x1e) == 0x02) {
207 lch_idx = cbits & 0x1; /* TCH/H */
208 if (ts->pchan != GSM_PCHAN_TCH_H)
209 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
210 chan_nr, ts->pchan);
211 } else if ((cbits & 0x1c) == 0x04) {
212 lch_idx = cbits & 0x3; /* SDCCH/4 */
213 if (ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
214 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
215 chan_nr, ts->pchan);
216 } else if ((cbits & 0x18) == 0x08) {
217 lch_idx = cbits & 0x7; /* SDCCH/8 */
218 if (ts->pchan != GSM_PCHAN_SDCCH8_SACCH8C)
219 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
220 chan_nr, ts->pchan);
221 } else if (cbits == 0x10 || cbits == 0x11 || cbits == 0x12) {
222 lch_idx = 0;
223 if (ts->pchan != GSM_PCHAN_CCCH &&
224 ts->pchan != GSM_PCHAN_CCCH_SDCCH4)
225 fprintf(stderr, "chan_nr=0x%02x but pchan=%u\n",
226 chan_nr, ts->pchan);
227 /* FIXME: we should not return first sdcch4 !!! */
228 } else {
229 fprintf(stderr, "unknown chan_nr=0x%02x\n", chan_nr);
230 return NULL;
231 }
232
233 lchan = &ts->lchan[lch_idx];
234
235 return lchan;
236}
237
238u_int8_t lchan2chan_nr(struct gsm_lchan *lchan)
239{
240 struct gsm_bts_trx_ts *ts = lchan->ts;
241 u_int8_t cbits, chan_nr;
242
243 switch (ts->pchan) {
244 case GSM_PCHAN_TCH_F:
245 cbits = 0x01;
246 break;
247 case GSM_PCHAN_TCH_H:
248 cbits = 0x02;
249 cbits += lchan->nr;
250 break;
251 case GSM_PCHAN_CCCH_SDCCH4:
252 cbits = 0x04;
253 cbits += lchan->nr;
254 break;
255 case GSM_PCHAN_SDCCH8_SACCH8C:
256 cbits = 0x08;
257 cbits += lchan->nr;
258 break;
259 default:
260 case GSM_PCHAN_CCCH:
261 cbits = 0x10;
262 break;
263 }
264
265 chan_nr = (cbits << 3) | (ts->nr & 0x7);
266
267 return chan_nr;
268}
269
Harald Welte52b1f982008-12-23 20:25:15 +0000270/* As per TS 03.03 Section 2.2, the IMSI has 'not more than 15 digits' */
271u_int64_t str_to_imsi(const char *imsi_str)
272{
273 u_int64_t ret;
274
275 ret = strtoull(imsi_str, NULL, 10);
276
277 return ret;
278}
279
280/* Table 5 Clause 7 TS 05.02 */
281unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res)
282{
283 if (!bs_ccch_sdcch_comb)
284 return 9 - bs_ag_blks_res;
285 else
286 return 3 - bs_ag_blks_res;
287}
288
289/* Chapter 6.5.2 of TS 05.02 */
290unsigned int get_ccch_group(u_int64_t imsi, unsigned int bs_cc_chans,
291 unsigned int n_pag_blocks)
292{
293 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) / n_pag_blocks;
294}
295
296/* Chapter 6.5.2 of TS 05.02 */
297unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
298 int n_pag_blocks)
299{
300 return (imsi % 1000) % (bs_cc_chans * n_pag_blocks) % n_pag_blocks;
301}
302
Harald Welte8470bf22008-12-25 23:28:35 +0000303static struct msgb *rsl_msgb_alloc(void)
304{
Harald Welte966636f2009-06-26 19:39:35 +0200305 return msgb_alloc_headroom(RSL_ALLOC_SIZE, RSL_ALLOC_HEADROOM,
306 "RSL");
Harald Welte8470bf22008-12-25 23:28:35 +0000307}
308
Harald Welte362322e2009-02-15 14:36:38 +0000309#define MACBLOCK_SIZE 23
310static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
311{
312 memcpy(out, in, len);
313
314 if (len < MACBLOCK_SIZE)
315 memset(out+len, 0x2b, MACBLOCK_SIZE-len);
316}
317
Harald Welte8830e072009-07-28 17:58:09 +0200318static const char *rsl_err_vals[0xff] = {
319 [RSL_ERR_RADIO_IF_FAIL] = "Radio Interface Failure",
320 [RSL_ERR_RADIO_LINK_FAIL] = "Radio Link Failure",
321 [RSL_ERR_HANDOVER_ACC_FAIL] = "Handover Access Failure",
322 [RSL_ERR_TALKER_ACC_FAIL] = "Talker Access Failure",
323 [RSL_ERR_OM_INTERVENTION] = "O&M Intervention",
324 [RSL_ERR_NORMAL_UNSPEC] = "Normal event, unspecified",
Harald Welte2da86292009-08-04 02:31:05 +0200325 [RSL_ERR_T_MSRFPCI_EXP] = "Siemens: T_MSRFPCI Expired",
Harald Welte8830e072009-07-28 17:58:09 +0200326 [RSL_ERR_EQUIPMENT_FAIL] = "Equipment Failure",
327 [RSL_ERR_RR_UNAVAIL] = "Radio Resource not available",
328 [RSL_ERR_TERR_CH_FAIL] = "Terrestrial Channel Failure",
329 [RSL_ERR_CCCH_OVERLOAD] = "CCCH Overload",
330 [RSL_ERR_ACCH_OVERLOAD] = "ACCH Overload",
331 [RSL_ERR_PROCESSOR_OVERLOAD] = "Processor Overload",
332 [RSL_ERR_RES_UNAVAIL] = "Resource not available, unspecified",
333 [RSL_ERR_TRANSC_UNAVAIL] = "Transcoding not available",
334 [RSL_ERR_SERV_OPT_UNAVAIL] = "Service or Option not available",
335 [RSL_ERR_ENCR_UNIMPL] = "Encryption algorithm not implemented",
336 [RSL_ERR_SERV_OPT_UNIMPL] = "Service or Option not implemented",
337 [RSL_ERR_RCH_ALR_ACTV_ALLOC] = "Radio channel already activated",
338 [RSL_ERR_INVALID_MESSAGE] = "Invalid Message, unspecified",
339 [RSL_ERR_MSG_DISCR] = "Message Discriminator Error",
340 [RSL_ERR_MSG_TYPE] = "Message Type Error",
341 [RSL_ERR_MSG_SEQ] = "Message Sequence Error",
342 [RSL_ERR_IE_ERROR] = "General IE error",
343 [RSL_ERR_MAND_IE_ERROR] = "Mandatory IE error",
344 [RSL_ERR_OPT_IE_ERROR] = "Optional IE error",
345 [RSL_ERR_IE_NONEXIST] = "IE non-existent",
346 [RSL_ERR_IE_LENGTH] = "IE length error",
347 [RSL_ERR_IE_CONTENT] = "IE content error",
348 [RSL_ERR_PROTO] = "Protocol error, unspecified",
349 [RSL_ERR_INTERWORKING] = "Interworking error, unspecified",
350};
351
352static const char *rsl_err_name(u_int8_t err)
Harald Welte7f93cea2009-02-23 00:02:59 +0000353{
Harald Welte8830e072009-07-28 17:58:09 +0200354 if (rsl_err_vals[err])
355 return rsl_err_vals[err];
356 else
357 return "unknown";
358}
359
360static void print_rsl_cause(const u_int8_t *cause_v, u_int8_t cause_len)
361{
Harald Welte7f93cea2009-02-23 00:02:59 +0000362 int i;
363
Harald Welte8830e072009-07-28 17:58:09 +0200364 DEBUGPC(DRSL, "CAUSE=0x%02x(%s) ",
365 cause_v[0], rsl_err_name(cause_v[0]));
366 for (i = 1; i < cause_len-1; i++)
367 DEBUGPC(DRSL, "%02x ", cause_v[i]);
Harald Welte7f93cea2009-02-23 00:02:59 +0000368}
369
Harald Welte52b1f982008-12-23 20:25:15 +0000370/* Send a BCCH_INFO message as per Chapter 8.5.1 */
Harald Weltee79769b2009-02-07 00:48:17 +0000371int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000372 const u_int8_t *data, int len)
373{
374 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000375 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000376
377 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof*dh);
378 init_dchan_hdr(dh, RSL_MT_BCCH_INFO);
379 dh->chan_nr = RSL_CHAN_BCCH;
380
381 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
382 msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
383
Harald Weltee79769b2009-02-07 00:48:17 +0000384 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000385
386 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000387}
388
Harald Weltee79769b2009-02-07 00:48:17 +0000389int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
Harald Welte52b1f982008-12-23 20:25:15 +0000390 const u_int8_t *data, int len)
391{
392 struct abis_rsl_common_hdr *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000393 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000394
395 ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
396 ch->msg_discr = ABIS_RSL_MDISC_TRX;
397 ch->msg_type = RSL_MT_SACCH_FILL;
398
399 msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
Harald Welte702d8702008-12-26 20:25:35 +0000400 msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
Harald Welte52b1f982008-12-23 20:25:15 +0000401
Harald Weltee79769b2009-02-07 00:48:17 +0000402 msg->trx = trx;
Harald Welte8470bf22008-12-25 23:28:35 +0000403
404 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000405}
406
Harald Weltefcd24452009-06-20 18:15:19 +0200407int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db)
408{
409 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200410 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200411 u_int8_t chan_nr = lchan2chan_nr(lchan);
412
413 db = abs(db);
414 if (db > 30)
415 return -EINVAL;
416
Harald Welteeab33352009-06-27 03:09:08 +0200417 msg = rsl_msgb_alloc();
418
Harald Weltefcd24452009-06-20 18:15:19 +0200419 lchan->bs_power = db/2;
420 if (fpc)
421 lchan->bs_power |= 0x10;
422
423 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
424 init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL);
425 dh->chan_nr = chan_nr;
426
427 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
428
429 msg->trx = lchan->ts->trx;
430
431 return abis_rsl_sendmsg(msg);
432}
433
434/* determine power control level for given dBm value, as indicated
435 * by the tables in chapter 4.1.1 of GSM TS 05.05 */
436static int ms_pwr_ctl_lvl(struct gsm_bts *bts, unsigned int dbm)
437{
438 switch (bts->band) {
439 case GSM_BAND_400:
440 case GSM_BAND_900:
441 case GSM_BAND_850:
442 if (dbm >= 39)
443 return 0;
444 else if (dbm < 5)
445 return 19;
446 else
447 return 2 + ((39 - dbm) / 2);
448 break;
449 case GSM_BAND_1800:
450 if (dbm >= 36)
451 return 29;
452 else if (dbm >= 34)
453 return 30;
454 else if (dbm >= 32)
455 return 31;
456 else
457 return (30 - dbm) / 2;
458 break;
459 case GSM_BAND_1900:
460 if (dbm >= 33)
461 return 30;
462 else if (dbm >= 32)
463 return 31;
464 else
465 return (30 - dbm) / 2;
466 break;
467 }
468 return -EINVAL;
469}
470
Harald Weltefe9af262009-06-20 18:44:35 +0200471static int ms_pwr_dbm(enum gsm_band band, u_int8_t lvl)
472{
473 lvl &= 0x1f;
474
475 switch (band) {
476 case GSM_BAND_400:
477 case GSM_BAND_900:
478 case GSM_BAND_850:
479 if (lvl < 2)
480 return 39;
481 else if (lvl < 20)
482 return 39 - ((lvl - 2) * 2) ;
483 else
484 return 5;
485 break;
486 case GSM_BAND_1800:
487 if (lvl < 16)
488 return 30 - (lvl * 2);
489 else if (lvl < 29)
490 return 0;
491 else
492 return 36 - ((lvl - 29) * 2);
493 break;
494 case GSM_BAND_1900:
495 if (lvl < 16)
496 return 30 - (lvl * 2);
497 else if (lvl < 30)
498 return -EINVAL;
499 else
500 return 33 - (lvl - 30);
501 break;
502 }
503 return -EINVAL;
504}
505
Harald Weltefcd24452009-06-20 18:15:19 +0200506int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm)
507{
508 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200509 struct msgb *msg;
Harald Weltefcd24452009-06-20 18:15:19 +0200510 u_int8_t chan_nr = lchan2chan_nr(lchan);
511 int ctl_lvl;
512
513 ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts, dbm);
514 if (ctl_lvl < 0)
515 return ctl_lvl;
516
Harald Welteeab33352009-06-27 03:09:08 +0200517 msg = rsl_msgb_alloc();
518
Harald Weltefcd24452009-06-20 18:15:19 +0200519 lchan->ms_power = ctl_lvl;
520
521 if (fpc)
522 lchan->ms_power |= 0x20;
523
524 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
525 init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL);
526 dh->chan_nr = chan_nr;
527
528 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
529
530 msg->trx = lchan->ts->trx;
531
532 return abis_rsl_sendmsg(msg);
533}
534
Harald Welte9943c5b2009-07-29 15:41:29 +0200535static int channel_mode_from_lchan(struct rsl_ie_chan_mode *cm,
536 struct gsm_lchan *lchan)
537{
538 memset(cm, 0, sizeof(cm));
539
540 /* FIXME: what to do with data calls ? */
541 cm->dtx_dtu = 0x00;
542
543 /* set TCH Speech/Data */
544 cm->spd_ind = lchan->rsl_cmode;
545
546 switch (lchan->type) {
547 case GSM_LCHAN_SDCCH:
548 cm->chan_rt = RSL_CMOD_CRT_SDCCH;
549 break;
550 case GSM_LCHAN_TCH_F:
551 cm->chan_rt = RSL_CMOD_CRT_TCH_Bm;
552 break;
553 case GSM_LCHAN_TCH_H:
554 cm->chan_rt = RSL_CMOD_CRT_TCH_Lm;
555 break;
556 case GSM_LCHAN_NONE:
557 case GSM_LCHAN_UNKNOWN:
558 default:
559 return -EINVAL;
560 }
561
562 switch (lchan->tch_mode) {
563 case GSM48_CMODE_SIGN:
564 cm->chan_rate = 0;
565 break;
566 case GSM48_CMODE_SPEECH_V1:
567 cm->chan_rate = RSL_CMOD_SP_GSM1;
568 break;
569 case GSM48_CMODE_SPEECH_EFR:
570 cm->chan_rate = RSL_CMOD_SP_GSM2;
571 break;
572 case GSM48_CMODE_SPEECH_AMR:
573 cm->chan_rate = RSL_CMOD_SP_GSM3;
574 break;
575 case GSM48_CMODE_DATA_14k5:
576 cm->chan_rate = RSL_CMOD_SP_NT_14k5;
577 break;
578 case GSM48_CMODE_DATA_12k0:
579 cm->chan_rate = RSL_CMOD_SP_NT_12k0;
580 break;
581 case GSM48_CMODE_DATA_6k0:
582 cm->chan_rate = RSL_CMOD_SP_NT_6k0;
583 break;
584 default:
585 return -EINVAL;
586 }
587
588 return 0;
589}
590
Harald Welte52b1f982008-12-23 20:25:15 +0000591/* Chapter 8.4.1 */
Harald Welteddab3c72009-02-28 13:19:15 +0000592#if 0
Harald Weltee79769b2009-02-07 00:48:17 +0000593int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
Harald Welte52b1f982008-12-23 20:25:15 +0000594 u_int8_t act_type,
595 struct rsl_ie_chan_mode *chan_mode,
596 struct rsl_ie_chan_ident *chan_ident,
597 u_int8_t bs_power, u_int8_t ms_power,
598 u_int8_t ta)
599{
600 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000601 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000602
603 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
604 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
605 dh->chan_nr = chan_nr;
606
607 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
608 /* For compatibility with Phase 1 */
609 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
610 (u_int8_t *) chan_mode);
611 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
Harald Welte702d8702008-12-26 20:25:35 +0000612 (u_int8_t *) chan_ident);
Harald Welte702d8702008-12-26 20:25:35 +0000613#if 0
Harald Welte52b1f982008-12-23 20:25:15 +0000614 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
615 (u_int8_t *) &encr_info);
Harald Welte702d8702008-12-26 20:25:35 +0000616#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000617 msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
Harald Welte52b1f982008-12-23 20:25:15 +0000618 msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
619 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
620
Harald Weltee79769b2009-02-07 00:48:17 +0000621 msg->trx = trx;
622
Harald Welte8470bf22008-12-25 23:28:35 +0000623 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000624}
Harald Welteddab3c72009-02-28 13:19:15 +0000625#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000626
Harald Welte8f5e2392009-02-03 12:57:37 +0000627int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
Harald Welte9943c5b2009-07-29 15:41:29 +0200628 u_int8_t ta)
Harald Welte4b634542008-12-27 01:55:51 +0000629{
630 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200631 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200632 int rc;
Harald Welte4b634542008-12-27 01:55:51 +0000633
634 u_int8_t chan_nr = lchan2chan_nr(lchan);
635 u_int16_t arfcn = lchan->ts->trx->arfcn;
636 struct rsl_ie_chan_mode cm;
637 struct rsl_ie_chan_ident ci;
638
Harald Welte9943c5b2009-07-29 15:41:29 +0200639 rc = channel_mode_from_lchan(&cm, lchan);
640 if (rc < 0)
641 return rc;
Harald Welte4b634542008-12-27 01:55:51 +0000642
Harald Welte02b0e092009-02-28 13:11:07 +0000643 memset(&ci, 0, sizeof(ci));
Harald Welte4b634542008-12-27 01:55:51 +0000644 ci.chan_desc.iei = 0x64;
645 ci.chan_desc.chan_nr = chan_nr;
Harald Welte02b0e092009-02-28 13:11:07 +0000646 ci.chan_desc.oct3 = (lchan->ts->trx->bts->tsc << 5) | ((arfcn & 0x3ff) >> 8);
Harald Welte4b634542008-12-27 01:55:51 +0000647 ci.chan_desc.oct4 = arfcn & 0xff;
648
Harald Welteeab33352009-06-27 03:09:08 +0200649 msg = rsl_msgb_alloc();
Harald Welte4b634542008-12-27 01:55:51 +0000650 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
651 init_dchan_hdr(dh, RSL_MT_CHAN_ACTIV);
652 dh->chan_nr = chan_nr;
653
654 msgb_tv_put(msg, RSL_IE_ACT_TYPE, act_type);
655 /* For compatibility with Phase 1 */
656 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
657 (u_int8_t *) &cm);
658 msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
659 (u_int8_t *) &ci);
Harald Welte4b634542008-12-27 01:55:51 +0000660#if 0
661 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
662 (u_int8_t *) &encr_info);
Harald Welte4b634542008-12-27 01:55:51 +0000663#endif
Harald Welted4c9bf32009-02-15 16:56:18 +0000664 msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
665 msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
Harald Welte4b634542008-12-27 01:55:51 +0000666 msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
667
Harald Weltee79769b2009-02-07 00:48:17 +0000668 msg->trx = lchan->ts->trx;
669
Harald Welte4b634542008-12-27 01:55:51 +0000670 return abis_rsl_sendmsg(msg);
671}
672
Harald Welte470abb72009-07-29 11:38:15 +0200673/* Chapter 8.4.9: Modify channel mode on BTS side */
Harald Welteda783762009-02-18 03:29:53 +0000674int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
675{
676 struct abis_rsl_dchan_hdr *dh;
Harald Welteeab33352009-06-27 03:09:08 +0200677 struct msgb *msg;
Harald Welte9943c5b2009-07-29 15:41:29 +0200678 int rc;
Harald Welteda783762009-02-18 03:29:53 +0000679
680 u_int8_t chan_nr = lchan2chan_nr(lchan);
681 struct rsl_ie_chan_mode cm;
682
Harald Welte9943c5b2009-07-29 15:41:29 +0200683 rc = channel_mode_from_lchan(&cm, lchan);
684 if (rc < 0)
685 return rc;
Harald Welteda783762009-02-18 03:29:53 +0000686
Harald Welteeab33352009-06-27 03:09:08 +0200687 msg = rsl_msgb_alloc();
Harald Welteda783762009-02-18 03:29:53 +0000688 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
689 init_dchan_hdr(dh, RSL_MT_MODE_MODIFY_REQ);
690 dh->chan_nr = chan_nr;
691
692 msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
693 (u_int8_t *) &cm);
694#if 0
695 msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
696 (u_int8_t *) &encr_info);
697#endif
698
699 msg->trx = lchan->ts->trx;
700
701 return abis_rsl_sendmsg(msg);
702}
703
Harald Welteae0f2362009-07-19 18:36:49 +0200704/* Chapter 8.4.5 */
705int rsl_deact_sacch(struct gsm_lchan *lchan)
706{
707 struct abis_rsl_dchan_hdr *dh;
708 struct msgb *msg = rsl_msgb_alloc();
709
710 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
711 init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
712 dh->chan_nr = lchan2chan_nr(lchan);
713
714 msg->lchan = lchan;
715 msg->trx = lchan->ts->trx;
716
717 DEBUGP(DRSL, "DEACTivate SACCH CMD channel=%s chan_nr=0x%02x\n",
718 gsm_ts_name(lchan->ts), dh->chan_nr);
719
720 return abis_rsl_sendmsg(msg);
721}
722
Holger Freyther36cbeff2008-12-30 19:15:20 +0000723/* Chapter 9.1.7 of 04.08 */
Harald Welte8470bf22008-12-25 23:28:35 +0000724int rsl_chan_release(struct gsm_lchan *lchan)
Harald Welte52b1f982008-12-23 20:25:15 +0000725{
726 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000727 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000728
729 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
730 init_dchan_hdr(dh, RSL_MT_RF_CHAN_REL);
Harald Welte8470bf22008-12-25 23:28:35 +0000731 dh->chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +0000732
Harald Welte8470bf22008-12-25 23:28:35 +0000733 msg->lchan = lchan;
734 msg->trx = lchan->ts->trx;
735
Harald Weltef325eb42009-02-19 17:07:39 +0000736 DEBUGP(DRSL, "Channel Release CMD channel=%s chan_nr=0x%02x\n",
737 gsm_ts_name(lchan->ts), dh->chan_nr);
Harald Welte2d5b6382008-12-27 19:46:06 +0000738
Harald Welte8470bf22008-12-25 23:28:35 +0000739 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000740}
741
742int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
743 u_int8_t *ms_ident, u_int8_t chan_needed)
744{
745 struct abis_rsl_dchan_hdr *dh;
Harald Welte8470bf22008-12-25 23:28:35 +0000746 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000747
748 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
749 init_dchan_hdr(dh, RSL_MT_PAGING_CMD);
750 dh->chan_nr = RSL_CHAN_PCH_AGCH;
751
752 msgb_tv_put(msg, RSL_IE_PAGING_GROUP, paging_group);
Harald Welte255539c2008-12-28 02:26:27 +0000753 msgb_tlv_put(msg, RSL_IE_MS_IDENTITY, len-2, ms_ident+2);
Harald Welte52b1f982008-12-23 20:25:15 +0000754 msgb_tv_put(msg, RSL_IE_CHAN_NEEDED, chan_needed);
755
Harald Welte8470bf22008-12-25 23:28:35 +0000756 msg->trx = bts->c0;
757
758 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000759}
760
Holger Freyther7448a532009-01-04 20:18:23 +0000761int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_need,
762 struct gsm_subscriber *subscr)
763{
Holger Freytherca362a62009-01-04 21:05:01 +0000764#if 0
Holger Freyther7448a532009-01-04 20:18:23 +0000765 u_int8_t mi[128];
766 unsigned int mi_len;
767 u_int8_t paging_group;
Holger Freytherca362a62009-01-04 21:05:01 +0000768#endif
Holger Freyther7448a532009-01-04 20:18:23 +0000769
770 return -1;
771}
772
Harald Welte52b1f982008-12-23 20:25:15 +0000773int imsi_str2bcd(u_int8_t *bcd_out, const char *str_in)
774{
775 int i, len = strlen(str_in);
776
777 for (i = 0; i < len; i++) {
778 int num = str_in[i] - 0x30;
779 if (num < 0 || num > 9)
780 return -1;
781 if (i % 2 == 0)
782 bcd_out[i/2] = num;
783 else
784 bcd_out[i/2] |= (num << 4);
785 }
786
787 return 0;
788}
789
Harald Welte702d8702008-12-26 20:25:35 +0000790/* Chapter 8.5.6 */
Harald Welte52b1f982008-12-23 20:25:15 +0000791int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val)
792{
Harald Welte8470bf22008-12-25 23:28:35 +0000793 struct msgb *msg = rsl_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000794 struct abis_rsl_dchan_hdr *dh;
Harald Welte362322e2009-02-15 14:36:38 +0000795 u_int8_t buf[MACBLOCK_SIZE];
Harald Welte52b1f982008-12-23 20:25:15 +0000796
797 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
798 init_dchan_hdr(dh, RSL_MT_IMMEDIATE_ASSIGN_CMD);
799 dh->chan_nr = RSL_CHAN_PCH_AGCH;
800
Harald Welte362322e2009-02-15 14:36:38 +0000801 switch (bts->type) {
802 case GSM_BTS_TYPE_BS11:
803 msgb_tlv_put(msg, RSL_IE_IMM_ASS_INFO, len, val);
804 break;
805 default:
806 /* If phase 2, construct a FULL_IMM_ASS_INFO */
807 pad_macblock(buf, val, len);
808 msgb_tlv_put(msg, RSL_IE_FULL_IMM_ASS_INFO, MACBLOCK_SIZE, buf);
809 break;
810 }
Harald Welte52b1f982008-12-23 20:25:15 +0000811
Harald Welte8470bf22008-12-25 23:28:35 +0000812 msg->trx = bts->c0;
813
814 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000815}
816
Harald Welte8470bf22008-12-25 23:28:35 +0000817/* Send "DATA REQUEST" message with given L3 Info payload */
Harald Welte52b1f982008-12-23 20:25:15 +0000818/* Chapter 8.3.1 */
Harald Welte8470bf22008-12-25 23:28:35 +0000819int rsl_data_request(struct msgb *msg, u_int8_t link_id)
Harald Welte52b1f982008-12-23 20:25:15 +0000820{
Harald Welte8470bf22008-12-25 23:28:35 +0000821 u_int8_t l3_len = msg->tail - (u_int8_t *)msgb_l3(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000822 struct abis_rsl_rll_hdr *rh;
823
Harald Welte8470bf22008-12-25 23:28:35 +0000824 if (msg->lchan == NULL) {
825 fprintf(stderr, "cannot send DATA REQUEST to unknown lchan\n");
826 return -EINVAL;
827 }
Harald Welte52b1f982008-12-23 20:25:15 +0000828
Harald Welte8470bf22008-12-25 23:28:35 +0000829 /* First push the L3 IE tag and length */
Harald Welte4b634542008-12-27 01:55:51 +0000830 msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
Harald Welte8470bf22008-12-25 23:28:35 +0000831
832 /* Then push the RSL header */
Harald Welte52b1f982008-12-23 20:25:15 +0000833 rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh));
834 init_llm_hdr(rh, RSL_MT_DATA_REQ);
Harald Welte4a543e82009-02-28 13:17:55 +0000835 rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
Harald Welte8470bf22008-12-25 23:28:35 +0000836 rh->chan_nr = lchan2chan_nr(msg->lchan);
837 rh->link_id = link_id;
Harald Welte52b1f982008-12-23 20:25:15 +0000838
Harald Welte8470bf22008-12-25 23:28:35 +0000839 msg->trx = msg->lchan->ts->trx;
840
841 return abis_rsl_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000842}
843
Harald Welteedcc5272009-08-09 13:47:35 +0200844/* Send "ESTABLISH REQUEST" message with given L3 Info payload */
845/* Chapter 8.3.1 */
846int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id)
847{
848 struct msgb *msg = rsl_msgb_alloc();
849 struct abis_rsl_rll_hdr *rh;
850
851 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
Harald Welte1c409272009-08-09 14:13:58 +0200852 init_llm_hdr(rh, RSL_MT_EST_REQ);
Harald Welteedcc5272009-08-09 13:47:35 +0200853 //rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
854 rh->chan_nr = lchan2chan_nr(lchan);
855 rh->link_id = link_id;
856
857 msg->trx = lchan->ts->trx;
858
859 return abis_rsl_sendmsg(msg);
860}
861
Harald Welted2dc1de2009-08-08 13:15:07 +0200862/* Chapter 8.3.7 Request the release of multiframe mode of RLL connection.
863 This is what higher layers should call. The BTS then responds with
864 RELEASE CONFIRM, which we in turn use to trigger RSL CHANNEL RELEASE,
865 which in turn is acknowledged by RSL CHANNEL RELEASE ACK, which calls
866 lchan_free() */
867int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id)
868{
869 struct msgb *msg = rsl_msgb_alloc();
870 struct abis_rsl_rll_hdr *rh;
871
872 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
873 init_llm_hdr(rh, RSL_MT_REL_REQ);
874 //rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
875 rh->chan_nr = lchan2chan_nr(lchan);
876 rh->link_id = link_id;
877
878 msg->trx = lchan->ts->trx;
879
880 return abis_rsl_sendmsg(msg);
881}
882
Harald Welte702d8702008-12-26 20:25:35 +0000883/* Chapter 8.4.2: Channel Activate Acknowledge */
884static int rsl_rx_chan_act_ack(struct msgb *msg)
885{
886 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
887
888 /* BTS has confirmed channel activation, we now need
889 * to assign the activated channel to the MS */
Harald Welte4b634542008-12-27 01:55:51 +0000890 if (rslh->ie_chan != RSL_IE_CHAN_NR)
891 return -EINVAL;
892
Harald Welte4b634542008-12-27 01:55:51 +0000893 return 0;
894}
Harald Welte702d8702008-12-26 20:25:35 +0000895
Harald Welte4b634542008-12-27 01:55:51 +0000896/* Chapter 8.4.3: Channel Activate NACK */
897static int rsl_rx_chan_act_nack(struct msgb *msg)
898{
Harald Welte6dab0552009-05-01 17:21:37 +0000899 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
900 struct tlv_parsed tp;
Harald Welte4b634542008-12-27 01:55:51 +0000901
Harald Welte6dab0552009-05-01 17:21:37 +0000902 /* BTS has rejected channel activation ?!? */
903 if (dh->ie_chan != RSL_IE_CHAN_NR)
Harald Welte4b634542008-12-27 01:55:51 +0000904 return -EINVAL;
Harald Welte6dab0552009-05-01 17:21:37 +0000905
906 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
907 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
Harald Welte8830e072009-07-28 17:58:09 +0200908 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
909 TLVP_LEN(&tp, RSL_IE_CAUSE));
910
Harald Welte4b634542008-12-27 01:55:51 +0000911 return 0;
Harald Welte702d8702008-12-26 20:25:35 +0000912}
913
Harald Welte7f93cea2009-02-23 00:02:59 +0000914/* Chapter 8.4.4: Connection Failure Indication */
915static int rsl_rx_conn_fail(struct msgb *msg)
916{
917 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
918 struct tlv_parsed tp;
919
920 DEBUGPC(DRSL, "CONNECTION FAIL: ");
Harald Welte7f93cea2009-02-23 00:02:59 +0000921
922 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
923
Harald Welte8830e072009-07-28 17:58:09 +0200924 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
925 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
926 TLVP_LEN(&tp, RSL_IE_CAUSE));
927
Harald Welte7f93cea2009-02-23 00:02:59 +0000928 if (msg->trx->bts->type == GSM_BTS_TYPE_BS11) {
929 /* FIXME: we have no idea what cause 0x18 is !!! */
930 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE) &&
931 TLVP_LEN(&tp, RSL_IE_CAUSE) >= 1 &&
932 *TLVP_VAL(&tp, RSL_IE_CAUSE) == 0x18) {
Harald Welte73be3aa2009-07-04 10:05:51 +0200933 DEBUGPC(DRSL, "Cause 0x18 IGNORING\n");
934 return 0;
Harald Welte7f93cea2009-02-23 00:02:59 +0000935 }
936 }
937
Holger Freytherf7b2a0e2009-06-02 02:55:17 +0000938 DEBUGPC(DRSL, "RELEASING.\n");
Harald Welte7f93cea2009-02-23 00:02:59 +0000939
940 /* FIXME: only free it after channel release ACK */
941 return rsl_chan_release(msg->lchan);
942}
943
Harald Welte440fed02009-05-01 18:43:47 +0000944static int rsl_rx_meas_res(struct msgb *msg)
945{
946 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
947 struct tlv_parsed tp;
948
Harald Welte10d0e672009-06-27 02:53:10 +0200949 DEBUGPC(DMEAS, "MEASUREMENT RESULT ");
Harald Welte440fed02009-05-01 18:43:47 +0000950 rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
951
952 if (TLVP_PRESENT(&tp, RSL_IE_MEAS_RES_NR))
Harald Welte10d0e672009-06-27 02:53:10 +0200953 DEBUGPC(DMEAS, "NR=%d ", *TLVP_VAL(&tp, RSL_IE_MEAS_RES_NR));
Harald Welte440fed02009-05-01 18:43:47 +0000954 if (TLVP_PRESENT(&tp, RSL_IE_UPLINK_MEAS)) {
955 u_int8_t len = TLVP_LEN(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte75d34a82009-05-23 06:11:13 +0000956 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_UPLINK_MEAS);
Harald Welte440fed02009-05-01 18:43:47 +0000957 if (len >= 3) {
958 if (val[0] & 0x40)
Harald Welte10d0e672009-06-27 02:53:10 +0200959 DEBUGPC(DMEAS, "DTXd ");
960 DEBUGPC(DMEAS, "RXL-FULL-up=%d RXL-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000961 val[0] & 0x3f, val[1] & 0x3f);
Harald Welte10d0e672009-06-27 02:53:10 +0200962 DEBUGPC(DMEAS, "RXQ-FULL-up=%d RXQ-SUB-up=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000963 val[2]>>3 & 0x7, val[2] & 0x7);
964 }
965 }
966 if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
Harald Welte10d0e672009-06-27 02:53:10 +0200967 DEBUGPC(DMEAS, "BS_POWER=%d ", *TLVP_VAL(&tp, RSL_IE_BS_POWER));
Harald Welte440fed02009-05-01 18:43:47 +0000968 if (TLVP_PRESENT(&tp, RSL_IE_MS_TIMING_OFFSET))
Harald Welte10d0e672009-06-27 02:53:10 +0200969 DEBUGPC(DMEAS, "MS_TO=%d ",
Harald Welte440fed02009-05-01 18:43:47 +0000970 *TLVP_VAL(&tp, RSL_IE_MS_TIMING_OFFSET));
Harald Weltefe9af262009-06-20 18:44:35 +0200971 if (TLVP_PRESENT(&tp, RSL_IE_L1_INFO)) {
Harald Welte86c162d2009-07-12 09:45:05 +0200972 const u_int8_t *val = TLVP_VAL(&tp, RSL_IE_L1_INFO);
Harald Weltefe9af262009-06-20 18:44:35 +0200973 u_int8_t pwr_lvl = val[0] >> 3;
Harald Welte10d0e672009-06-27 02:53:10 +0200974 DEBUGPC(DMEAS, "L1_MS_PWR=%ddBm ",
Harald Weltefe9af262009-06-20 18:44:35 +0200975 ms_pwr_dbm(msg->trx->bts->band, pwr_lvl));
Harald Welte10d0e672009-06-27 02:53:10 +0200976 DEBUGPC(DMEAS, "L1_FPC=%u ", val[0] & 0x04 ? 1 : 0);
977 DEBUGPC(DMEAS, "L1_TA=%u ", val[1]);
Harald Weltefe9af262009-06-20 18:44:35 +0200978 }
Harald Weltef7c43522009-06-09 20:24:21 +0000979 if (TLVP_PRESENT(&tp, RSL_IE_L3_INFO)) {
Harald Welte10d0e672009-06-27 02:53:10 +0200980 DEBUGPC(DMEAS, "L3\n");
Harald Weltef7c43522009-06-09 20:24:21 +0000981 msg->l3h = TLVP_VAL(&tp, RSL_IE_L3_INFO);
982 return gsm0408_rcvmsg(msg);
983 } else
Harald Welte10d0e672009-06-27 02:53:10 +0200984 DEBUGPC(DMEAS, "\n");
Harald Welte60d68f12009-06-05 20:07:43 +0000985
Harald Welte75d34a82009-05-23 06:11:13 +0000986 return 0;
Harald Welte440fed02009-05-01 18:43:47 +0000987}
988
Harald Welte52b1f982008-12-23 20:25:15 +0000989static int abis_rsl_rx_dchan(struct msgb *msg)
990{
Harald Welte8470bf22008-12-25 23:28:35 +0000991 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
992 int rc = 0;
Harald Weltef325eb42009-02-19 17:07:39 +0000993 char *ts_name;
Harald Welte52b1f982008-12-23 20:25:15 +0000994
Harald Welte8470bf22008-12-25 23:28:35 +0000995 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +0000996 ts_name = gsm_ts_name(msg->lchan->ts);
997
Harald Welte10d0e672009-06-27 02:53:10 +0200998 if (rslh->c.msg_type != RSL_MT_MEAS_RES)
999 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ", ts_name, rslh->chan_nr);
Harald Welte8470bf22008-12-25 23:28:35 +00001000
1001 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001002 case RSL_MT_CHAN_ACTIV_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001003 DEBUGPC(DRSL, "CHANNEL ACTIVATE ACK\n");
Harald Welte4b634542008-12-27 01:55:51 +00001004 rc = rsl_rx_chan_act_ack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001005 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001006 case RSL_MT_CHAN_ACTIV_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001007 DEBUGPC(DRSL, "CHANNEL ACTIVATE NACK\n");
Harald Welte4b634542008-12-27 01:55:51 +00001008 rc = rsl_rx_chan_act_nack(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001009 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001010 case RSL_MT_CONN_FAIL:
Harald Welte7f93cea2009-02-23 00:02:59 +00001011 rc = rsl_rx_conn_fail(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001012 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001013 case RSL_MT_MEAS_RES:
Harald Welte440fed02009-05-01 18:43:47 +00001014 rc = rsl_rx_meas_res(msg);
Harald Welte2d5b6382008-12-27 19:46:06 +00001015 break;
1016 case RSL_MT_RF_CHAN_REL_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001017 DEBUGPC(DRSL, "RF CHANNEL RELEASE ACK\n");
Harald Welte2d5b6382008-12-27 19:46:06 +00001018 lchan_free(msg->lchan);
Harald Welte8470bf22008-12-25 23:28:35 +00001019 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001020 case RSL_MT_MODE_MODIFY_ACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001021 DEBUGPC(DRSL, "CHANNEL MODE MODIFY ACK\n");
Harald Welteda783762009-02-18 03:29:53 +00001022 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001023 case RSL_MT_MODE_MODIFY_NACK:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001024 DEBUGPC(DRSL, "CHANNEL MODE MODIFY NACK\n");
Harald Welteda783762009-02-18 03:29:53 +00001025 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001026 case RSL_MT_PHY_CONTEXT_CONF:
1027 case RSL_MT_PREPROC_MEAS_RES:
Harald Welte52b1f982008-12-23 20:25:15 +00001028 case RSL_MT_TALKER_DET:
1029 case RSL_MT_LISTENER_DET:
1030 case RSL_MT_REMOTE_CODEC_CONF_REP:
1031 case RSL_MT_MR_CODEC_MOD_ACK:
1032 case RSL_MT_MR_CODEC_MOD_NACK:
1033 case RSL_MT_MR_CODEC_MOD_PER:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001034 DEBUGPC(DRSL, "Unimplemented Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001035 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001036 break;
1037 default:
Holger Freyther79f4ae62009-06-02 03:25:04 +00001038 DEBUGPC(DRSL, "unknown Abis RSL DChan msg 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001039 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001040 return -EINVAL;
1041 }
Harald Weltef325eb42009-02-19 17:07:39 +00001042
Harald Welte8470bf22008-12-25 23:28:35 +00001043 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001044}
1045
Harald Welte702d8702008-12-26 20:25:35 +00001046static int rsl_rx_error_rep(struct msgb *msg)
1047{
1048 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8830e072009-07-28 17:58:09 +02001049 struct tlv_parsed tp;
Harald Welte702d8702008-12-26 20:25:35 +00001050
Harald Welte7f93cea2009-02-23 00:02:59 +00001051 DEBUGP(DRSL, "ERROR REPORT ");
Harald Welte8830e072009-07-28 17:58:09 +02001052
1053 rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
1054
1055 if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
1056 print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
1057 TLVP_LEN(&tp, RSL_IE_CAUSE));
1058
Holger Freyther79f4ae62009-06-02 03:25:04 +00001059 DEBUGPC(DRSL, "\n");
Harald Welte702d8702008-12-26 20:25:35 +00001060
1061 return 0;
1062}
1063
Harald Welte52b1f982008-12-23 20:25:15 +00001064static int abis_rsl_rx_trx(struct msgb *msg)
1065{
Harald Welte702d8702008-12-26 20:25:35 +00001066 struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001067 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001068
1069 switch (rslh->msg_type) {
Harald Welte702d8702008-12-26 20:25:35 +00001070 case RSL_MT_ERROR_REPORT:
1071 rc = rsl_rx_error_rep(msg);
1072 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001073 case RSL_MT_RF_RES_IND:
1074 /* interference on idle channels of TRX */
Harald Welte3cf7c3f2009-05-01 18:28:00 +00001075 //DEBUGP(DRSL, "TRX: RF Interference Indication\n");
Harald Welte8f5e2392009-02-03 12:57:37 +00001076 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001077 case RSL_MT_OVERLOAD:
1078 /* indicate CCCH / ACCH / processor overload */
Harald Weltef325eb42009-02-19 17:07:39 +00001079 DEBUGP(DRSL, "TRX: CCCH/ACCH/CPU Overload\n");
Harald Welte52b1f982008-12-23 20:25:15 +00001080 break;
1081 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001082 DEBUGP(DRSL, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001083 rslh->msg_type);
1084 return -EINVAL;
1085 }
Harald Welte8470bf22008-12-25 23:28:35 +00001086 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001087}
1088
Harald Welte8470bf22008-12-25 23:28:35 +00001089/* MS has requested a channel on the RACH */
Harald Welte52b1f982008-12-23 20:25:15 +00001090static int rsl_rx_chan_rqd(struct msgb *msg)
1091{
Harald Welte702d8702008-12-26 20:25:35 +00001092 struct gsm_bts *bts = msg->trx->bts;
Harald Welte8470bf22008-12-25 23:28:35 +00001093 struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
1094 struct gsm48_req_ref *rqd_ref;
Harald Welte52b1f982008-12-23 20:25:15 +00001095 struct gsm48_imm_ass ia;
Harald Welte8470bf22008-12-25 23:28:35 +00001096 enum gsm_chan_t lctype;
Harald Welte2cbe0922008-12-29 04:09:31 +00001097 enum gsm_chreq_reason_t chreq_reason;
Harald Welte8470bf22008-12-25 23:28:35 +00001098 struct gsm_lchan *lchan;
1099 u_int8_t rqd_ta;
Holger Freyther3186bf22008-12-29 06:23:49 +00001100 int ret;
Harald Welte8470bf22008-12-25 23:28:35 +00001101
Harald Welte52b1f982008-12-23 20:25:15 +00001102 u_int16_t arfcn;
1103 u_int8_t ts_number, subch;
1104
Harald Welte8470bf22008-12-25 23:28:35 +00001105 /* parse request reference to be used in immediate assign */
1106 if (rqd_hdr->data[0] != RSL_IE_REQ_REFERENCE)
1107 return -EINVAL;
1108
1109 rqd_ref = (struct gsm48_req_ref *) &rqd_hdr->data[1];
1110
1111 /* parse access delay and use as TA */
1112 if (rqd_hdr->data[sizeof(struct gsm48_req_ref)+1] != RSL_IE_ACCESS_DELAY)
1113 return -EINVAL;
1114 rqd_ta = rqd_hdr->data[sizeof(struct gsm48_req_ref)+2];
1115
1116 /* determine channel type (SDCCH/TCH_F/TCH_H) based on
1117 * request reference RA */
1118 lctype = get_ctype_by_chreq(bts, rqd_ref->ra);
Harald Welte2cbe0922008-12-29 04:09:31 +00001119 chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra);
1120
Harald Welte8470bf22008-12-25 23:28:35 +00001121 /* check availability / allocate channel */
1122 lchan = lchan_alloc(bts, lctype);
1123 if (!lchan) {
1124 fprintf(stderr, "CHAN RQD: no resources\n");
1125 /* FIXME: send some kind of reject ?!? */
1126 return -ENOMEM;
1127 }
1128
1129 ts_number = lchan->ts->nr;
1130 arfcn = lchan->ts->trx->arfcn;
1131 subch = lchan->nr;
Harald Welte52b1f982008-12-23 20:25:15 +00001132
Harald Weltef89abbd2009-08-04 02:31:55 +02001133 lchan->ms_power = ms_pwr_ctl_lvl(bts, 20 /* dBm == 100mW */);
1134 lchan->bs_power = 0x0f; /* 30dB reduction */
Harald Welte9943c5b2009-07-29 15:41:29 +02001135 lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
1136 rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
Harald Welte52b1f982008-12-23 20:25:15 +00001137
1138 /* create IMMEDIATE ASSIGN 04.08 messge */
1139 memset(&ia, 0, sizeof(ia));
1140 ia.l2_plen = 0x2d;
1141 ia.proto_discr = GSM48_PDISC_RR;
1142 ia.msg_type = GSM48_MT_RR_IMM_ASS;
Harald Welte2d5b6382008-12-27 19:46:06 +00001143 ia.page_mode = GSM48_PM_SAME;
Harald Welte4b634542008-12-27 01:55:51 +00001144 ia.chan_desc.chan_nr = lchan2chan_nr(lchan);
Harald Welte52b1f982008-12-23 20:25:15 +00001145 ia.chan_desc.h0.h = 0;
1146 ia.chan_desc.h0.arfcn_high = arfcn >> 8;
1147 ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
Harald Welte814c4b72009-07-21 20:55:56 +02001148 ia.chan_desc.h0.tsc = bts->tsc;
Harald Welte8470bf22008-12-25 23:28:35 +00001149 /* use request reference extracted from CHAN_RQD */
1150 memcpy(&ia.req_ref, rqd_ref, sizeof(ia.req_ref));
1151 ia.timing_advance = rqd_ta;
Harald Welte52b1f982008-12-23 20:25:15 +00001152 ia.mob_alloc_len = 0;
1153
Harald Welte8f5e2392009-02-03 12:57:37 +00001154 DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %s "
Holger Freyther79f4ae62009-06-02 03:25:04 +00001155 "chan_nr=0x%02x r=%s ra=0x%02x\n",
Harald Welteca64da92009-01-04 16:54:12 +00001156 arfcn, ts_number, subch, gsm_lchan_name(lchan->type),
Harald Welte4a543e82009-02-28 13:17:55 +00001157 ia.chan_desc.chan_nr, gsm_chreq_name(chreq_reason),
1158 rqd_ref->ra);
Harald Welte75a983f2008-12-27 21:34:06 +00001159
Harald Welte09e38af2009-02-16 22:52:23 +00001160 /* FIXME: Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
Holger Freyther3186bf22008-12-29 06:23:49 +00001161
Harald Welte52b1f982008-12-23 20:25:15 +00001162 /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
Holger Freyther3186bf22008-12-29 06:23:49 +00001163 ret = rsl_imm_assign_cmd(bts, sizeof(ia), (u_int8_t *) &ia);
1164
Harald Welte817f3c82008-12-30 14:57:59 +00001165 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +00001166}
1167
Harald Welteea280442009-02-02 22:29:56 +00001168/* MS has requested a channel on the RACH */
1169static int rsl_rx_ccch_load(struct msgb *msg)
1170{
1171 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
1172 u_int16_t pg_buf_space;
Holger Freyther8c563cf2009-02-03 20:08:51 +00001173 u_int16_t rach_slot_count = -1;
1174 u_int16_t rach_busy_count = -1;
1175 u_int16_t rach_access_count = -1;
Harald Welteea280442009-02-02 22:29:56 +00001176
1177 switch (rslh->data[0]) {
1178 case RSL_IE_PAGING_LOAD:
1179 pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
Holger Freyther392209c2009-02-10 00:06:19 +00001180 paging_update_buffer_space(msg->trx->bts, pg_buf_space);
Harald Welteea280442009-02-02 22:29:56 +00001181 break;
1182 case RSL_IE_RACH_LOAD:
Holger Freyther8c563cf2009-02-03 20:08:51 +00001183 if (msg->data_len >= 7) {
1184 rach_slot_count = rslh->data[2] << 8 | rslh->data[3];
1185 rach_busy_count = rslh->data[4] << 8 | rslh->data[5];
1186 rach_access_count = rslh->data[6] << 8 | rslh->data[7];
1187 }
Harald Welteea280442009-02-02 22:29:56 +00001188 break;
1189 default:
1190 break;
1191 }
1192
1193 return 0;
1194}
1195
Harald Welte52b1f982008-12-23 20:25:15 +00001196static int abis_rsl_rx_cchan(struct msgb *msg)
1197{
Harald Welteea280442009-02-02 22:29:56 +00001198 struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001199 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001200
Harald Welte8470bf22008-12-25 23:28:35 +00001201 msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
1202
1203 switch (rslh->c.msg_type) {
Harald Welte52b1f982008-12-23 20:25:15 +00001204 case RSL_MT_CHAN_RQD:
1205 /* MS has requested a channel on the RACH */
1206 rc = rsl_rx_chan_rqd(msg);
1207 break;
Harald Welteea280442009-02-02 22:29:56 +00001208 case RSL_MT_CCCH_LOAD_IND:
1209 /* current load on the CCCH */
1210 rc = rsl_rx_ccch_load(msg);
1211 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001212 case RSL_MT_DELETE_IND:
1213 /* CCCH overloaded, IMM_ASSIGN was dropped */
1214 case RSL_MT_CBCH_LOAD_IND:
1215 /* current load on the CBCH */
Harald Welte8f5e2392009-02-03 12:57:37 +00001216 fprintf(stderr, "Unimplemented Abis RSL TRX message type "
1217 "0x%02x\n", rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001218 break;
1219 default:
1220 fprintf(stderr, "Unknown Abis RSL TRX message type 0x%02x\n",
Harald Welte8470bf22008-12-25 23:28:35 +00001221 rslh->c.msg_type);
Harald Welte52b1f982008-12-23 20:25:15 +00001222 return -EINVAL;
1223 }
Harald Welte8470bf22008-12-25 23:28:35 +00001224
1225 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001226}
1227
Harald Welte4b634542008-12-27 01:55:51 +00001228static int rsl_rx_rll_err_ind(struct msgb *msg)
1229{
1230 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1231 u_int8_t *rlm_cause = rllh->data;
1232
Harald Welte602f2b82009-08-04 02:50:21 +02001233 DEBUGPC(DRLL, "ERROR INDICATION cause=0x%02x\n", rlm_cause[1]);
Harald Welteedcc5272009-08-09 13:47:35 +02001234
1235 rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
Harald Welte4b634542008-12-27 01:55:51 +00001236
Harald Welte81543bc2009-07-04 09:40:05 +02001237 if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED)
1238 return rsl_chan_release(msg->lchan);
1239
Harald Welte4b634542008-12-27 01:55:51 +00001240 return 0;
1241}
Harald Weltef325eb42009-02-19 17:07:39 +00001242
Harald Welte52b1f982008-12-23 20:25:15 +00001243/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST
1244 0x02, 0x06,
1245 0x01, 0x20,
1246 0x02, 0x00,
1247 0x0b, 0x00, 0x0f, 0x05, 0x08, ... */
1248
1249static int abis_rsl_rx_rll(struct msgb *msg)
1250{
1251 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
Harald Weltef325eb42009-02-19 17:07:39 +00001252 int rc = 0;
1253 char *ts_name;
Harald Welte8470bf22008-12-25 23:28:35 +00001254
1255 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001256 ts_name = gsm_ts_name(msg->lchan->ts);
1257 DEBUGP(DRLL, "channel=%s chan_nr=0x%02x ", ts_name, rllh->chan_nr);
Harald Welte52b1f982008-12-23 20:25:15 +00001258
1259 switch (rllh->c.msg_type) {
1260 case RSL_MT_DATA_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001261 DEBUGPC(DRLL, "DATA INDICATION\n");
Harald Welte4a543e82009-02-28 13:17:55 +00001262 if (msgb_l2len(msg) >
1263 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1264 rllh->data[0] == RSL_IE_L3_INFO) {
1265 msg->l3h = &rllh->data[3];
1266 return gsm0408_rcvmsg(msg);
1267 }
Harald Welte52b1f982008-12-23 20:25:15 +00001268 break;
1269 case RSL_MT_EST_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001270 DEBUGPC(DRLL, "ESTABLISH INDICATION\n");
Harald Welte4a543e82009-02-28 13:17:55 +00001271 if (msgb_l2len(msg) >
1272 sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) &&
1273 rllh->data[0] == RSL_IE_L3_INFO) {
1274 msg->l3h = &rllh->data[3];
1275 return gsm0408_rcvmsg(msg);
1276 }
Harald Welte52b1f982008-12-23 20:25:15 +00001277 break;
Harald Welteedcc5272009-08-09 13:47:35 +02001278 case RSL_MT_EST_CONF:
Harald Welte1c409272009-08-09 14:13:58 +02001279 DEBUGPC(DRLL, "ESTABLISH CONFIRM\n");
Harald Welteedcc5272009-08-09 13:47:35 +02001280 rll_indication(msg->lchan, rllh->link_id,
1281 BSC_RLLR_IND_EST_CONF);
1282 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001283 case RSL_MT_REL_IND:
Harald Welted2dc1de2009-08-08 13:15:07 +02001284 /* BTS informs us of having received DISC from MS */
Harald Welte602f2b82009-08-04 02:50:21 +02001285 DEBUGPC(DRLL, "RELEASE INDICATION\n");
Harald Welteedcc5272009-08-09 13:47:35 +02001286 rll_indication(msg->lchan, rllh->link_id,
1287 BSC_RLLR_IND_REL_IND);
Harald Welted2dc1de2009-08-08 13:15:07 +02001288 /* we can now releae the channel on the BTS/Abis side */
1289 rsl_chan_release(msg->lchan);
Harald Welte2d5b6382008-12-27 19:46:06 +00001290 break;
1291 case RSL_MT_REL_CONF:
Harald Welted2dc1de2009-08-08 13:15:07 +02001292 /* BTS informs us of having received UA from MS,
1293 * in response to DISC that we've sent earlier */
Harald Welte602f2b82009-08-04 02:50:21 +02001294 DEBUGPC(DRLL, "RELEASE CONFIRMATION\n");
Harald Welted2dc1de2009-08-08 13:15:07 +02001295 /* we can now releae the channel on the BTS/Abis side */
1296 rsl_chan_release(msg->lchan);
Harald Welte4b634542008-12-27 01:55:51 +00001297 break;
1298 case RSL_MT_ERROR_IND:
1299 rc = rsl_rx_rll_err_ind(msg);
1300 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001301 case RSL_MT_UNIT_DATA_IND:
Harald Welte602f2b82009-08-04 02:50:21 +02001302 DEBUGPC(DRLL, "unimplemented Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001303 rllh->c.msg_type);
1304 break;
1305 default:
Harald Welte602f2b82009-08-04 02:50:21 +02001306 DEBUGPC(DRLL, "unknown Abis RLL message type 0x%02x\n",
Harald Welte52b1f982008-12-23 20:25:15 +00001307 rllh->c.msg_type);
1308 }
Harald Welte8470bf22008-12-25 23:28:35 +00001309 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001310}
1311
Harald Weltef4e79f22009-07-28 18:11:56 +02001312static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
1313{
Harald Weltef4e79f22009-07-28 18:11:56 +02001314 switch (tch_mode) {
1315 case GSM48_CMODE_SPEECH_V1:
1316 return 0x00;
1317 case GSM48_CMODE_SPEECH_EFR:
1318 return 0x01;
1319 case GSM48_CMODE_SPEECH_AMR:
1320 return 0x02;
1321 /* FIXME: Type1 half-rate and type3 half-rate */
1322 }
Harald Welte58ca5b72009-07-29 12:12:18 +02001323 DEBUGPC(DRSL, "Cannot determine ip.access speech mode for "
1324 "tch_mode == 0x%02x\n", tch_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001325 return 0;
Harald Weltef4e79f22009-07-28 18:11:56 +02001326}
1327
Harald Welte75099262009-02-16 21:12:08 +00001328/* ip.access specific RSL extensions */
1329int rsl_ipacc_bind(struct gsm_lchan *lchan)
1330{
1331 struct msgb *msg = rsl_msgb_alloc();
1332 struct abis_rsl_dchan_hdr *dh;
Harald Welte58ca5b72009-07-29 12:12:18 +02001333 u_int8_t speech_mode;
Harald Welte75099262009-02-16 21:12:08 +00001334
1335 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1336 init_dchan_hdr(dh, RSL_MT_IPAC_BIND);
1337 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1338 dh->chan_nr = lchan2chan_nr(lchan);
1339
Harald Weltef4e79f22009-07-28 18:11:56 +02001340 /* 0x1- == receive-only, 0x-1 == EFR codec */
Harald Welte58ca5b72009-07-29 12:12:18 +02001341 speech_mode = 0x10 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1342 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001343
Harald Welte58ca5b72009-07-29 12:12:18 +02001344 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND "
1345 "speech_mode=0x%02x\n", gsm_ts_name(lchan->ts),
1346 dh->chan_nr, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001347
Harald Welte75099262009-02-16 21:12:08 +00001348 msg->trx = lchan->ts->trx;
1349
1350 return abis_rsl_sendmsg(msg);
1351}
1352
Harald Welte20855542009-07-12 09:50:35 +02001353int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
1354 u_int16_t conn_id, u_int8_t rtp_payload2)
Harald Welte75099262009-02-16 21:12:08 +00001355{
1356 struct msgb *msg = rsl_msgb_alloc();
1357 struct abis_rsl_dchan_hdr *dh;
1358 u_int8_t *att_f8, *att_ip, *att_port;
Harald Welte58ca5b72009-07-29 12:12:18 +02001359 u_int8_t speech_mode;
Harald Weltef4e79f22009-07-28 18:11:56 +02001360 struct in_addr ia;
Harald Welte75099262009-02-16 21:12:08 +00001361
1362 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
1363 init_dchan_hdr(dh, RSL_MT_IPAC_CONNECT);
1364 dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
1365 dh->chan_nr = lchan2chan_nr(lchan);
1366
Harald Welte58ca5b72009-07-29 12:12:18 +02001367 /* 0x0- == both directions, 0x-1 == EFR codec */
1368 speech_mode = 0x00 | ipa_smod_s_for_tch_mode(lchan->tch_mode);
1369
Harald Weltef4e79f22009-07-28 18:11:56 +02001370 ia.s_addr = htonl(ip);
Harald Welte58ca5b72009-07-29 12:12:18 +02001371 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_CONNECT "
1372 "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d speech_mode=0x%02x\n",
Harald Weltef4e79f22009-07-28 18:11:56 +02001373 gsm_ts_name(lchan->ts), dh->chan_nr,
Harald Welte58ca5b72009-07-29 12:12:18 +02001374 inet_ntoa(ia), port, rtp_payload2, conn_id, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001375
Harald Welte20855542009-07-12 09:50:35 +02001376 att_f8 = msgb_put(msg, sizeof(conn_id)+1);
Harald Welte86c162d2009-07-12 09:45:05 +02001377 att_f8[0] = RSL_IE_IPAC_CONN_ID;
Harald Welte20855542009-07-12 09:50:35 +02001378 att_f8[1] = conn_id >> 8;
1379 att_f8[2] = conn_id & 0xff;
Harald Welte75099262009-02-16 21:12:08 +00001380
1381 att_ip = msgb_put(msg, sizeof(ip)+1);
1382 att_ip[0] = RSL_IE_IPAC_REMOTE_IP;
1383 att_ip[1] = ip >> 24;
1384 att_ip[2] = ip >> 16;
1385 att_ip[3] = ip >> 8;
1386 att_ip[4] = ip & 0xff;
Harald Welteda783762009-02-18 03:29:53 +00001387 //att_ip[4] = 11;
Harald Welte75099262009-02-16 21:12:08 +00001388
1389 att_port = msgb_put(msg, sizeof(port)+1);
1390 att_port[0] = RSL_IE_IPAC_REMOTE_PORT;
1391 att_port[1] = port >> 8;
1392 att_port[2] = port & 0xff;
1393
Harald Welte58ca5b72009-07-29 12:12:18 +02001394 msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, speech_mode);
Harald Weltef4e79f22009-07-28 18:11:56 +02001395 if (rtp_payload2)
1396 msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
1397
Harald Welte75099262009-02-16 21:12:08 +00001398 msg->trx = lchan->ts->trx;
1399
1400 return abis_rsl_sendmsg(msg);
1401}
1402
1403static int abis_rsl_rx_ipacc_bindack(struct msgb *msg)
1404{
1405 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1406 struct tlv_parsed tv;
1407 struct gsm_bts_trx_ts *ts = msg->lchan->ts;
Harald Welte167df882009-02-17 14:35:45 +00001408 struct in_addr ip;
Harald Welte75099262009-02-16 21:12:08 +00001409 u_int16_t port, attr_f8;
1410
1411 /* the BTS has acknowledged a local bind, it now tells us the IP
1412 * address and port number to which it has bound the given logical
1413 * channel */
1414
1415 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
1416 if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
1417 !TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
Harald Welte86c162d2009-07-12 09:45:05 +02001418 !TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
Harald Weltef325eb42009-02-19 17:07:39 +00001419 DEBUGPC(DRSL, "mandatory IE missing");
Harald Welte75099262009-02-16 21:12:08 +00001420 return -EINVAL;
1421 }
Harald Welte167df882009-02-17 14:35:45 +00001422 ip.s_addr = *((u_int32_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_IP));
Harald Welte75099262009-02-16 21:12:08 +00001423 port = *((u_int16_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_PORT));
1424 attr_f8 = *((u_int16_t *) TLVP_VAL(&tv, 0xf8));
1425
Harald Weltef4e79f22009-07-28 18:11:56 +02001426 DEBUGPC(DRSL, "IP=%s PORT=%d CONN_ID=%d ",
1427 inet_ntoa(ip), ntohs(port), ntohs(attr_f8));
1428
1429 if (TLVP_PRESENT(&tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
1430 ts->abis_ip.rtp_payload2 =
1431 *TLVP_VAL(&tv, RSL_IE_IPAC_RTP_PAYLOAD2);
1432 DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
1433 ts->abis_ip.rtp_payload2);
1434 }
Harald Welte167df882009-02-17 14:35:45 +00001435
Harald Welte75099262009-02-16 21:12:08 +00001436 /* update our local information about this TS */
Harald Welte167df882009-02-17 14:35:45 +00001437 ts->abis_ip.bound_ip = ntohl(ip.s_addr);
1438 ts->abis_ip.bound_port = ntohs(port);
Harald Welte20855542009-07-12 09:50:35 +02001439 ts->abis_ip.conn_id = ntohs(attr_f8);
Harald Welte75099262009-02-16 21:12:08 +00001440
Harald Welte167df882009-02-17 14:35:45 +00001441 dispatch_signal(SS_ABISIP, S_ABISIP_BIND_ACK, msg->lchan);
1442
Harald Welte75099262009-02-16 21:12:08 +00001443 return 0;
1444}
1445
1446static int abis_rsl_rx_ipacc_disc_ind(struct msgb *msg)
1447{
1448 struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
1449 struct tlv_parsed tv;
1450
1451 rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
Harald Welte75099262009-02-16 21:12:08 +00001452
Harald Welte8830e072009-07-28 17:58:09 +02001453 if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
1454 print_rsl_cause(TLVP_VAL(&tv, RSL_IE_CAUSE),
1455 TLVP_LEN(&tv, RSL_IE_CAUSE));
Harald Welte75099262009-02-16 21:12:08 +00001456
Harald Welte888b1142009-07-28 18:02:05 +02001457 dispatch_signal(SS_ABISIP, S_ABISIP_DISC_IND, msg->lchan);
1458
Harald Welte75099262009-02-16 21:12:08 +00001459 return 0;
1460}
1461
1462static int abis_rsl_rx_ipacc(struct msgb *msg)
1463{
1464 struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
1465 int rc = 0;
1466
1467 msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
Harald Weltef325eb42009-02-19 17:07:39 +00001468 DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ",
1469 gsm_ts_name(msg->lchan->ts), rllh->chan_nr);
Harald Welte75099262009-02-16 21:12:08 +00001470
1471 switch (rllh->c.msg_type) {
1472 case RSL_MT_IPAC_BIND_ACK:
Harald Welte4a543e82009-02-28 13:17:55 +00001473 DEBUGPC(DRSL, "IPAC_BIND_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001474 rc = abis_rsl_rx_ipacc_bindack(msg);
1475 break;
1476 case RSL_MT_IPAC_BIND_NACK:
1477 /* somehow the BTS was unable to bind the lchan to its local
1478 * port?!? */
Harald Weltef325eb42009-02-19 17:07:39 +00001479 DEBUGPC(DRSL, "IPAC_BIND_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001480 break;
1481 case RSL_MT_IPAC_CONNECT_ACK:
1482 /* the BTS tells us that a connect operation was successful */
Harald Weltef325eb42009-02-19 17:07:39 +00001483 DEBUGPC(DRSL, "IPAC_CONNECT_ACK ");
Harald Welte75099262009-02-16 21:12:08 +00001484 break;
1485 case RSL_MT_IPAC_CONNECT_NACK:
1486 /* somehow the BTS was unable to connect the lchan to a remote
1487 * port */
Harald Weltef325eb42009-02-19 17:07:39 +00001488 DEBUGPC(DRSL, "IPAC_CONNECT_NACK ");
Harald Welte75099262009-02-16 21:12:08 +00001489 break;
1490 case RSL_MT_IPAC_DISCONNECT_IND:
Harald Weltef325eb42009-02-19 17:07:39 +00001491 DEBUGPC(DRSL, "IPAC_DISCONNECT_IND ");
Harald Welte75099262009-02-16 21:12:08 +00001492 rc = abis_rsl_rx_ipacc_disc_ind(msg);
1493 break;
1494 default:
Harald Weltef325eb42009-02-19 17:07:39 +00001495 DEBUGPC(DRSL, "Unknown ip.access msg_type 0x%02x", rllh->c.msg_type);
Harald Welte75099262009-02-16 21:12:08 +00001496 break;
1497 }
Harald Welte6dab0552009-05-01 17:21:37 +00001498 DEBUGPC(DRSL, "\n");
Harald Welte75099262009-02-16 21:12:08 +00001499
1500 return rc;
1501}
1502
1503
Harald Welte52b1f982008-12-23 20:25:15 +00001504/* Entry-point where L2 RSL from BTS enters */
Harald Welte8470bf22008-12-25 23:28:35 +00001505int abis_rsl_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +00001506{
1507 struct abis_rsl_common_hdr *rslh = msgb_l2(msg) ;
Harald Welte8f5e2392009-02-03 12:57:37 +00001508 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +00001509
1510 switch (rslh->msg_discr & 0xfe) {
1511 case ABIS_RSL_MDISC_RLL:
1512 rc = abis_rsl_rx_rll(msg);
1513 break;
1514 case ABIS_RSL_MDISC_DED_CHAN:
1515 rc = abis_rsl_rx_dchan(msg);
1516 break;
1517 case ABIS_RSL_MDISC_COM_CHAN:
Harald Welte52b1f982008-12-23 20:25:15 +00001518 rc = abis_rsl_rx_cchan(msg);
1519 break;
Harald Welte8470bf22008-12-25 23:28:35 +00001520 case ABIS_RSL_MDISC_TRX:
1521 rc = abis_rsl_rx_trx(msg);
1522 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001523 case ABIS_RSL_MDISC_LOC:
Harald Welte8f5e2392009-02-03 12:57:37 +00001524 fprintf(stderr, "unimplemented RSL msg disc 0x%02x\n",
1525 rslh->msg_discr);
1526 break;
Harald Welte75099262009-02-16 21:12:08 +00001527 case ABIS_RSL_MDISC_IPACCESS:
1528 rc = abis_rsl_rx_ipacc(msg);
1529 break;
Harald Welte52b1f982008-12-23 20:25:15 +00001530 default:
1531 fprintf(stderr, "unknown RSL message discriminator 0x%02x\n",
1532 rslh->msg_discr);
1533 return -EINVAL;
1534 }
Harald Welte4f4a3902008-12-26 00:04:49 +00001535 msgb_free(msg);
Harald Welte8470bf22008-12-25 23:28:35 +00001536 return rc;
Harald Welte52b1f982008-12-23 20:25:15 +00001537}
Holger Freyther3b72a892009-02-04 00:31:39 +00001538
1539
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001540/* Section 3.3.2.3 TS 05.02. I think this looks like a table */
Holger Freyther3b72a892009-02-04 00:31:39 +00001541int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf)
1542{
1543 switch (ccch_conf) {
1544 case RSL_BCCH_CCCH_CONF_1_NC:
1545 return 1;
1546 case RSL_BCCH_CCCH_CONF_1_C:
1547 return 1;
1548 case RSL_BCCH_CCCH_CONF_2_NC:
1549 return 2;
1550 case RSL_BCCH_CCCH_CONF_3_NC:
1551 return 3;
1552 case RSL_BCCH_CCCH_CONF_4_NC:
1553 return 4;
1554 default:
1555 return -1;
1556 }
1557}
1558
Holger Hans Peter Freyther3d571832009-07-09 20:43:16 +02001559/* Section 3.3.2.3 TS 05.02 */
Holger Freyther3b72a892009-02-04 00:31:39 +00001560int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf)
1561{
1562 switch (ccch_conf) {
1563 case RSL_BCCH_CCCH_CONF_1_NC:
1564 return 0;
1565 case RSL_BCCH_CCCH_CONF_1_C:
1566 return 1;
1567 case RSL_BCCH_CCCH_CONF_2_NC:
1568 return 0;
1569 case RSL_BCCH_CCCH_CONF_3_NC:
1570 return 0;
1571 case RSL_BCCH_CCCH_CONF_4_NC:
1572 return 0;
1573 default:
1574 return -1;
1575 }
1576}
1577
1578/* From Table 10.5.33 of GSM 04.08 */
1579int rsl_number_of_paging_subchannels(struct gsm_bts *bts)
1580{
1581 if (bts->chan_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C) {
1582 return MAX(1, (3 - bts->chan_desc.bs_ag_blks_res))
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001583 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001584 } else {
1585 return (9 - bts->chan_desc.bs_ag_blks_res)
Holger Freyther3aa8d6c2009-02-04 02:14:45 +00001586 * (bts->chan_desc.bs_pa_mfrms + 2);
Holger Freyther3b72a892009-02-04 00:31:39 +00001587 }
1588}