blob: a772f33b4326a5831d6b94005ea5dd9997c0838f [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
4/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
Holger Freytherba4d28a2008-12-29 06:23:44 +00005 * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welte8470bf22008-12-25 23:28:35 +00006 *
Harald Welte52b1f982008-12-23 20:25:15 +00007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
Harald Weltedb253af2008-12-30 17:56:55 +000030#include <time.h>
Harald Welte4b634542008-12-27 01:55:51 +000031#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000032
Harald Welte75a983f2008-12-27 21:34:06 +000033#include <openbsc/db.h>
Harald Welte8470bf22008-12-25 23:28:35 +000034#include <openbsc/msgb.h>
35#include <openbsc/debug.h>
36#include <openbsc/gsm_data.h>
37#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000038#include <openbsc/gsm_04_11.h>
Harald Welte8470bf22008-12-25 23:28:35 +000039#include <openbsc/gsm_04_08.h>
40#include <openbsc/abis_rsl.h>
Harald Welte52b1f982008-12-23 20:25:15 +000041
Harald Welte8470bf22008-12-25 23:28:35 +000042#define GSM48_ALLOC_SIZE 1024
43#define GSM48_ALLOC_HEADROOM 128
Harald Welte52b1f982008-12-23 20:25:15 +000044
Harald Welte65e74cc2008-12-29 01:55:35 +000045static int gsm48_tx_simple(struct gsm_lchan *lchan,
46 u_int8_t pdisc, u_int8_t msg_type);
Holger Freytherb7193e42008-12-29 17:44:08 +000047static void schedule_reject(struct gsm_lchan *lchan);
Harald Welte65e74cc2008-12-29 01:55:35 +000048
Harald Welte52b1f982008-12-23 20:25:15 +000049struct gsm_lai {
50 u_int16_t mcc;
51 u_int16_t mnc;
52 u_int16_t lac;
53};
54
Holger Freyther89824fc2008-12-30 16:18:18 +000055static int authorize_everonye = 0;
56void gsm0408_allow_everyone(int everyone)
57{
58 printf("Allowing everyone?\n");
59 authorize_everonye = everyone;
60}
61
Holger Freythere97f7fb2008-12-31 18:52:11 +000062static int reject_cause = 0;
63void gsm0408_set_reject_cause(int cause)
64{
65 reject_cause = cause;
66}
67
Holger Freyther73487a22008-12-31 18:53:57 +000068static int authorize_subscriber(struct gsm_loc_updating_operation *loc,
69 struct gsm_subscriber *subscriber)
Holger Freyther89824fc2008-12-30 16:18:18 +000070{
71 if (!subscriber)
72 return 0;
73
Holger Freyther73487a22008-12-31 18:53:57 +000074 /*
75 * Do not send accept yet as more information should arrive. Some
76 * phones will not send us the information and we will have to check
77 * what we want to do with that.
78 */
79 if (loc && (loc->waiting_for_imsi || loc->waiting_for_imei))
80 return 0;
81
Holger Freyther89824fc2008-12-30 16:18:18 +000082 if (authorize_everonye)
83 return 1;
84
85 return subscriber->authorized;
86}
Holger Freyther07cc8d82008-12-29 06:23:46 +000087
Holger Freyther73487a22008-12-31 18:53:57 +000088static void release_loc_updating_req(struct gsm_lchan *lchan)
89{
Harald Welte179f0642008-12-31 23:59:18 +000090 if (!lchan->loc_operation)
Holger Freyther73487a22008-12-31 18:53:57 +000091 return;
92
93 del_timer(&lchan->loc_operation->updating_timer);
94 free(lchan->loc_operation);
95 lchan->loc_operation = 0;
96}
97
98static void allocate_loc_updating_req(struct gsm_lchan *lchan)
99{
100 release_loc_updating_req(lchan);
101
102 lchan->loc_operation = (struct gsm_loc_updating_operation *)
103 malloc(sizeof(*lchan->loc_operation));
104 memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation));
105}
Holger Freyther07cc8d82008-12-29 06:23:46 +0000106
Harald Welte52b1f982008-12-23 20:25:15 +0000107static void parse_lai(struct gsm_lai *lai, const struct gsm48_loc_area_id *lai48)
108{
109 u_int8_t dig[4];
110
111 /* MCC */
112 dig[1] = lai48->digits[0] & 0x0f;
113 dig[2] = lai48->digits[0] >> 4;
114 dig[3] = lai48->digits[1] & 0x0f;
115 lai->mcc = dig[3] * 100 + dig[2];
116
117 /* MNC */
118 dig[1] = lai48->digits[1] >> 4;
119 dig[2] = lai48->digits[2] & 0x0f;
120 dig[3] = lai48->digits[2] >> 4;
121 lai->mnc = dig[3] * 100 + dig[2];
122
123 lai->lac = lai48->lac;
124}
125
126static void to_bcd(u_int8_t *bcd, u_int16_t val)
127{
Harald Welte4b634542008-12-27 01:55:51 +0000128 bcd[2] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000129 val = val / 10;
130 bcd[1] = val % 10;
131 val = val / 10;
Harald Welte4b634542008-12-27 01:55:51 +0000132 bcd[0] = val % 10;
Harald Welte52b1f982008-12-23 20:25:15 +0000133 val = val / 10;
134}
135
Harald Weltedb253af2008-12-30 17:56:55 +0000136static u_int8_t to_bcd8(unsigned int val)
137{
138 u_int8_t bcd;
139
140 bcd = (val % 10) & 0x0f;
141 val = val / 10;
142 bcd |= (val % 10) << 4;
143
144 return bcd;
145}
146
Holger Freyther17746612008-12-28 16:32:44 +0000147void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
Harald Welte52b1f982008-12-23 20:25:15 +0000148 u_int16_t mnc, u_int16_t lac)
149{
150 u_int8_t bcd[3];
151
152 to_bcd(bcd, mcc);
153 lai48->digits[0] = bcd[0] | (bcd[1] << 4);
154 lai48->digits[1] = bcd[2];
155
156 to_bcd(bcd, mnc);
Harald Welte4b634542008-12-27 01:55:51 +0000157 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
158#if 0
Harald Welte8470bf22008-12-25 23:28:35 +0000159 lai48->digits[1] |= bcd[2] << 4;
160 lai48->digits[2] = bcd[0] | (bcd[1] << 4);
Harald Welte4b634542008-12-27 01:55:51 +0000161#else
162 lai48->digits[1] |= 0xf << 4;
163 lai48->digits[2] = bcd[1] | (bcd[2] << 4);
164#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000165
Harald Welte4b634542008-12-27 01:55:51 +0000166 lai48->lac = htons(lac);
Harald Welte52b1f982008-12-23 20:25:15 +0000167}
168
Harald Welte255539c2008-12-28 02:26:27 +0000169#define TMSI_LEN 5
Harald Welte52b1f982008-12-23 20:25:15 +0000170#define MID_TMSI_LEN (TMSI_LEN + 2)
171
Harald Welte255539c2008-12-28 02:26:27 +0000172int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000173{
Harald Welte65e74cc2008-12-29 01:55:35 +0000174 u_int32_t *tptr = (u_int32_t *) &buf[3];
Harald Welte255539c2008-12-28 02:26:27 +0000175
Harald Welte4b634542008-12-27 01:55:51 +0000176 buf[0] = GSM48_IE_MOBILE_ID;
Harald Welte1a412182008-12-27 22:13:43 +0000177 buf[1] = TMSI_LEN;
Harald Welte4b634542008-12-27 01:55:51 +0000178 buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
Harald Welte255539c2008-12-28 02:26:27 +0000179 *tptr = htonl(tmsi);
180
181 return 7;
Harald Welte52b1f982008-12-23 20:25:15 +0000182}
183
Harald Welte8470bf22008-12-25 23:28:35 +0000184static struct msgb *gsm48_msgb_alloc(void)
185{
186 return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM);
187}
188
Harald Welte65e74cc2008-12-29 01:55:35 +0000189static int gsm48_sendmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000190{
Harald Welte65e74cc2008-12-29 01:55:35 +0000191 struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
192
193 if (msg->lchan) {
Harald Welte8470bf22008-12-25 23:28:35 +0000194 msg->trx = msg->lchan->ts->trx;
Harald Welte52b1f982008-12-23 20:25:15 +0000195
Harald Welte65e74cc2008-12-29 01:55:35 +0000196 if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC) {
197 /* Send a 04.08 call control message, add transaction
198 * ID and TI flag */
199 gh->proto_discr |= msg->lchan->call.transaction_id;
200
201 /* GSM 04.07 Section 11.2.3.1.3 */
202 switch (msg->lchan->call.type) {
203 case GSM_CT_MO:
204 gh->proto_discr |= 0x80;
205 break;
206 case GSM_CT_MT:
207 break;
208 }
209 }
210 }
211
Harald Welte4b634542008-12-27 01:55:51 +0000212 msg->l3h = msg->data;
213
Harald Welte8470bf22008-12-25 23:28:35 +0000214 return rsl_data_request(msg, 0);
Harald Welte52b1f982008-12-23 20:25:15 +0000215}
216
Harald Welte52b1f982008-12-23 20:25:15 +0000217
Holger Freyther429e7762008-12-30 13:28:30 +0000218/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
Harald Welte8470bf22008-12-25 23:28:35 +0000219int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
Harald Welte52b1f982008-12-23 20:25:15 +0000220{
Harald Welte8470bf22008-12-25 23:28:35 +0000221 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000222 struct gsm48_hdr *gh;
223
Harald Welte8470bf22008-12-25 23:28:35 +0000224 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +0000225
226 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
227 gh->proto_discr = GSM48_PDISC_MM;
Harald Welte10b487b2008-12-27 19:53:37 +0000228 gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
Harald Welte52b1f982008-12-23 20:25:15 +0000229 gh->data[0] = cause;
230
Harald Weltedb253af2008-12-30 17:56:55 +0000231 DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
232
233 //gsm0411_send_sms(lchan, NULL);
Harald Welte52b1f982008-12-23 20:25:15 +0000234
Harald Welte65e74cc2008-12-29 01:55:35 +0000235 return gsm48_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000236}
237
238/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
Harald Welte75a983f2008-12-27 21:34:06 +0000239int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
Harald Welte52b1f982008-12-23 20:25:15 +0000240{
Harald Welte8470bf22008-12-25 23:28:35 +0000241 struct gsm_bts *bts = lchan->ts->trx->bts;
242 struct msgb *msg = gsm48_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000243 struct gsm48_hdr *gh;
244 struct gsm48_loc_area_id *lai;
245 u_int8_t *mid;
Holger Freyther07cc8d82008-12-29 06:23:46 +0000246 int ret;
Harald Welte52b1f982008-12-23 20:25:15 +0000247
Harald Welte8470bf22008-12-25 23:28:35 +0000248 msg->lchan = lchan;
Harald Welte52b1f982008-12-23 20:25:15 +0000249
250 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
251 gh->proto_discr = GSM48_PDISC_MM;
252 gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT;
253
254 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
Holger Freyther17746612008-12-28 16:32:44 +0000255 gsm0408_generate_lai(lai, bts->network->country_code,
Harald Welte52b1f982008-12-23 20:25:15 +0000256 bts->network->network_code, bts->location_area_code);
257
258 mid = msgb_put(msg, MID_TMSI_LEN);
259 generate_mid_from_tmsi(mid, tmsi);
260
261 DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
262
Holger Freyther07cc8d82008-12-29 06:23:46 +0000263 /* inform the upper layer on the progress */
Holger Freytherb7193e42008-12-29 17:44:08 +0000264 if (bts->network->update_request)
265 (*bts->network->update_request)(bts, tmsi, 1);
Holger Freyther07cc8d82008-12-29 06:23:46 +0000266
Harald Weltedb253af2008-12-30 17:56:55 +0000267 ret = gsm48_sendmsg(msg);
268
269 /* return gsm48_cc_tx_setup(lchan); */
270 ret = gsm48_tx_mm_info(lchan);
271 ret = gsm0411_send_sms(lchan, NULL);
272
Holger Freyther07cc8d82008-12-29 06:23:46 +0000273 return ret;
Harald Welte52b1f982008-12-23 20:25:15 +0000274}
275
Harald Weltefc977a82008-12-27 10:19:37 +0000276static char bcd2char(u_int8_t bcd)
277{
278 if (bcd < 0xa)
279 return '0' + bcd;
280 else
281 return 'A' + (bcd - 0xa);
282}
283
284/* 10.5.1.4 */
285static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
286{
287 int i;
288 u_int8_t mi_type;
289 char *str_cur = string;
290
291 mi_type = mi[0] & GSM_MI_TYPE_MASK;
292
293 switch (mi_type) {
294 case GSM_MI_TYPE_NONE:
295 break;
296 case GSM_MI_TYPE_TMSI:
Harald Weltedb253af2008-12-30 17:56:55 +0000297 /* skip padding nibble at the beginning, start at offset 1... */
298 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +0000299 if (str_cur + 2 >= string + str_len)
300 return str_cur - string;
301 *str_cur++ = bcd2char(mi[i] >> 4);
302 *str_cur++ = bcd2char(mi[i] & 0xf);
303 }
304 break;
305 case GSM_MI_TYPE_IMSI:
306 case GSM_MI_TYPE_IMEI:
307 case GSM_MI_TYPE_IMEISV:
Harald Weltedb253af2008-12-30 17:56:55 +0000308 *str_cur++ = bcd2char(mi[0] >> 4);
309
310 for (i = 1; i < mi_len; i++) {
Harald Weltefc977a82008-12-27 10:19:37 +0000311 if (str_cur + 2 >= string + str_len)
312 return str_cur - string;
313 *str_cur++ = bcd2char(mi[i] & 0xf);
Harald Weltedb253af2008-12-30 17:56:55 +0000314 /* skip last nibble in last input byte when GSM_EVEN */
315 if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
316 *str_cur++ = bcd2char(mi[i] >> 4);
Harald Weltefc977a82008-12-27 10:19:37 +0000317 }
318 break;
319 default:
320 break;
321 }
Harald Weltefc977a82008-12-27 10:19:37 +0000322 *str_cur++ = '\0';
Harald Weltedb253af2008-12-30 17:56:55 +0000323
Harald Weltefc977a82008-12-27 10:19:37 +0000324 return str_cur - string;
325}
326
Harald Welte231ad4f2008-12-27 11:15:38 +0000327/* Chapter 9.2.10 */
328static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
329{
330 struct msgb *msg = gsm48_msgb_alloc();
331 struct gsm48_hdr *gh;
Harald Weltefc977a82008-12-27 10:19:37 +0000332
Harald Welte231ad4f2008-12-27 11:15:38 +0000333 msg->lchan = lchan;
334
335 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
336 gh->proto_discr = GSM48_PDISC_MM;
337 gh->msg_type = GSM48_MT_MM_ID_REQ;
338 gh->data[0] = id_type;
339
Harald Welte65e74cc2008-12-29 01:55:35 +0000340 return gsm48_sendmsg(msg);
Harald Welte231ad4f2008-12-27 11:15:38 +0000341}
342
343#define MI_SIZE 32
344
345/* Chapter 9.2.11 */
346static int mm_rx_id_resp(struct msgb *msg)
347{
348 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte75a983f2008-12-27 21:34:06 +0000349 struct gsm_lchan *lchan = msg->lchan;
Harald Welte231ad4f2008-12-27 11:15:38 +0000350 u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
351 char mi_string[MI_SIZE];
Harald Welte75a983f2008-12-27 21:34:06 +0000352 u_int32_t tmsi;
Harald Welte231ad4f2008-12-27 11:15:38 +0000353
354 mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte61253062008-12-27 11:25:50 +0000355 DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
Harald Welte231ad4f2008-12-27 11:15:38 +0000356 mi_type, mi_string);
357
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000358 /*
359 * Rogue messages could trick us but so is life
360 */
361 put_lchan(lchan);
362
Harald Welte75a983f2008-12-27 21:34:06 +0000363 switch (mi_type) {
364 case GSM_MI_TYPE_IMSI:
365 if (!lchan->subscr)
366 lchan->subscr = db_create_subscriber(mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +0000367 if (lchan->loc_operation)
368 lchan->loc_operation->waiting_for_imsi = 0;
Harald Welte75a983f2008-12-27 21:34:06 +0000369 break;
370 case GSM_MI_TYPE_IMEI:
Harald Welte255539c2008-12-28 02:26:27 +0000371 case GSM_MI_TYPE_IMEISV:
Harald Welte75a983f2008-12-27 21:34:06 +0000372 /* update subscribe <-> IMEI mapping */
373 if (lchan->subscr)
374 db_subscriber_assoc_imei(lchan->subscr, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +0000375 if (lchan->loc_operation)
376 lchan->loc_operation->waiting_for_imei = 0;
Harald Welte75a983f2008-12-27 21:34:06 +0000377 break;
378 }
Holger Freyther73487a22008-12-31 18:53:57 +0000379
380 /* Check if we can let the mobile station enter */
381 if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) {
382 db_subscriber_alloc_tmsi(lchan->subscr);
383 tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
384 release_loc_updating_req(lchan);
385 return gsm0408_loc_upd_acc(msg->lchan, tmsi);
386 }
387
Harald Welte75a983f2008-12-27 21:34:06 +0000388 return 0;
Harald Welte231ad4f2008-12-27 11:15:38 +0000389}
390
Harald Welte255539c2008-12-28 02:26:27 +0000391
392static void loc_upd_rej_cb(void *data)
393{
394 struct gsm_lchan *lchan = data;
395
Holger Freyther73487a22008-12-31 18:53:57 +0000396 release_loc_updating_req(lchan);
Holger Freythere97f7fb2008-12-31 18:52:11 +0000397 gsm0408_loc_upd_rej(lchan, reject_cause);
Harald Welte255539c2008-12-28 02:26:27 +0000398 rsl_chan_release(lchan);
399}
400
Holger Freytherb7193e42008-12-29 17:44:08 +0000401static void schedule_reject(struct gsm_lchan *lchan)
402{
Holger Freyther73487a22008-12-31 18:53:57 +0000403 lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb;
404 lchan->loc_operation->updating_timer.data = lchan;
405 schedule_timer(&lchan->loc_operation->updating_timer, 5, 0);
Holger Freytherb7193e42008-12-29 17:44:08 +0000406}
407
Harald Welte231ad4f2008-12-27 11:15:38 +0000408#define MI_SIZE 32
Harald Welte52b1f982008-12-23 20:25:15 +0000409/* Chapter 9.2.15 */
Harald Welte231ad4f2008-12-27 11:15:38 +0000410static int mm_rx_loc_upd_req(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000411{
Harald Welte8470bf22008-12-25 23:28:35 +0000412 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte702d8702008-12-26 20:25:35 +0000413 struct gsm_bts *bts = msg->trx->bts;
Harald Welte52b1f982008-12-23 20:25:15 +0000414 struct gsm48_loc_upd_req *lu;
415 struct gsm_subscriber *subscr;
Harald Welte255539c2008-12-28 02:26:27 +0000416 struct gsm_lchan *lchan = msg->lchan;
Harald Welte8470bf22008-12-25 23:28:35 +0000417 u_int8_t mi_type;
Harald Welte75a983f2008-12-27 21:34:06 +0000418 u_int32_t tmsi;
Harald Welte231ad4f2008-12-27 11:15:38 +0000419 char mi_string[MI_SIZE];
420 int rc;
Harald Welte52b1f982008-12-23 20:25:15 +0000421
Harald Welte8470bf22008-12-25 23:28:35 +0000422 lu = (struct gsm48_loc_upd_req *) gh->data;
423
424 mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
Harald Welte52b1f982008-12-23 20:25:15 +0000425
Harald Weltefc977a82008-12-27 10:19:37 +0000426 mi_to_string(mi_string, sizeof(mi_string), lu->mi, lu->mi_len);
427
Harald Welte231ad4f2008-12-27 11:15:38 +0000428 DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s)\n", mi_type, mi_string);
Holger Freyther73487a22008-12-31 18:53:57 +0000429
430 allocate_loc_updating_req(lchan);
431
Harald Welte52b1f982008-12-23 20:25:15 +0000432 switch (mi_type) {
433 case GSM_MI_TYPE_IMSI:
Harald Welte231ad4f2008-12-27 11:15:38 +0000434 /* we always want the IMEI, too */
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000435 use_lchan(lchan);
Harald Welte255539c2008-12-28 02:26:27 +0000436 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
Holger Freyther73487a22008-12-31 18:53:57 +0000437 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000438
Harald Welte52b1f982008-12-23 20:25:15 +0000439 /* look up subscriber based on IMSI */
Harald Welte75a983f2008-12-27 21:34:06 +0000440 subscr = db_create_subscriber(mi_string);
Harald Welte4b634542008-12-27 01:55:51 +0000441 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000442 case GSM_MI_TYPE_TMSI:
Harald Welte231ad4f2008-12-27 11:15:38 +0000443 /* we always want the IMEI, too */
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000444 use_lchan(lchan);
Harald Welte255539c2008-12-28 02:26:27 +0000445 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
Holger Freyther73487a22008-12-31 18:53:57 +0000446 lchan->loc_operation->waiting_for_imei = 1;
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000447
Harald Welte52b1f982008-12-23 20:25:15 +0000448 /* look up the subscriber based on TMSI, request IMSI if it fails */
Harald Weltefc977a82008-12-27 10:19:37 +0000449 subscr = subscr_get_by_tmsi(lu->mi);
Harald Welte52b1f982008-12-23 20:25:15 +0000450 if (!subscr) {
Harald Welte231ad4f2008-12-27 11:15:38 +0000451 /* send IDENTITY REQUEST message to get IMSI */
Holger Freytherc6ea9db2008-12-30 19:18:21 +0000452 use_lchan(lchan);
Harald Welte255539c2008-12-28 02:26:27 +0000453 rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
Holger Freyther73487a22008-12-31 18:53:57 +0000454 lchan->loc_operation->waiting_for_imsi = 1;
Harald Welte52b1f982008-12-23 20:25:15 +0000455 }
456 break;
457 case GSM_MI_TYPE_IMEI:
458 case GSM_MI_TYPE_IMEISV:
459 /* no sim card... FIXME: what to do ? */
460 fprintf(stderr, "Unimplemented mobile identity type\n");
461 break;
462 default:
463 fprintf(stderr, "Unknown mobile identity type\n");
464 break;
465 }
466
Harald Welte255539c2008-12-28 02:26:27 +0000467 lchan->subscr = subscr;
468
Holger Freyther73487a22008-12-31 18:53:57 +0000469 /*
470 * Schedule the reject timer and check if we can let the
471 * subscriber into our network immediately or if we need to wait
472 * for identity responses.
473 */
474 schedule_reject(lchan);
475 if (!authorize_subscriber(lchan->loc_operation, subscr))
Harald Weltee872cb12009-01-01 00:33:37 +0000476 return 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000477
Harald Welte75a983f2008-12-27 21:34:06 +0000478 db_subscriber_alloc_tmsi(subscr);
Harald Welte52b1f982008-12-23 20:25:15 +0000479 subscr_update(subscr, bts);
Harald Welte8470bf22008-12-25 23:28:35 +0000480
Harald Welte255539c2008-12-28 02:26:27 +0000481 tmsi = strtoul(subscr->tmsi, NULL, 10);
482
Holger Freyther73487a22008-12-31 18:53:57 +0000483 release_loc_updating_req(lchan);
Harald Welte255539c2008-12-28 02:26:27 +0000484 return gsm0408_loc_upd_acc(lchan, tmsi);
Harald Welte52b1f982008-12-23 20:25:15 +0000485}
486
Harald Weltedb253af2008-12-30 17:56:55 +0000487/* Section 9.2.15a */
488int gsm48_tx_mm_info(struct gsm_lchan *lchan)
489{
490 struct msgb *msg = gsm48_msgb_alloc();
491 struct gsm48_hdr *gh;
492 struct gsm_network *net = lchan->ts->trx->bts->network;
493 time_t cur_t;
494 struct tm* cur_time;
495 u_int8_t *ptr8;
496 u_int16_t *ptr16;
497 int name_len;
498 int tz15min;
499 int i;
500
501 msg->lchan = lchan;
502
503 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
504 gh->proto_discr = GSM48_PDISC_MM;
505 gh->msg_type = GSM48_MT_MM_INFO;
506
507 if (net->name_long) {
508 name_len = strlen(net->name_long);
509 /* 10.5.3.5a */
510 ptr8 = msgb_put(msg, 3);
511 ptr8[0] = GSM48_IE_NAME_LONG;
512 ptr8[1] = name_len*2 +1;
513 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
514
515 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
516 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +0000517 ptr16[i] = htons(net->name_long[i]);
Harald Weltedb253af2008-12-30 17:56:55 +0000518
519 /* FIXME: Use Cell Broadcast, not UCS-2, since
520 * UCS-2 is only supported by later revisions of the spec */
521 }
522
523 if (net->name_short) {
524 name_len = strlen(net->name_short);
525 /* 10.5.3.5a */
526 ptr8 = (u_int8_t *) msgb_put(msg, 3);
527 ptr8[0] = GSM48_IE_NAME_LONG;
528 ptr8[1] = name_len*2 + 1;
529 ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
530
Harald Weltee872cb12009-01-01 00:33:37 +0000531 ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
Harald Weltedb253af2008-12-30 17:56:55 +0000532 for (i = 0; i < name_len; i++)
Harald Welte179f0642008-12-31 23:59:18 +0000533 ptr16[i] = htons(net->name_short[i]);
Harald Weltedb253af2008-12-30 17:56:55 +0000534 }
535
536#if 0
537 /* Section 10.5.3.9 */
538 cur_t = time(NULL);
539 cur_time = gmtime(cur_t);
540 ptr8 = msgb_put(msg, 8);
541 ptr8[0] = GSM48_IE_NET_TIME_TZ;
542 ptr8[1] = to_bcd8(cur_time->tm_year % 100);
543 ptr8[2] = to_bcd8(cur_time->tm_mon);
544 ptr8[3] = to_bcd8(cur_time->tm_mday);
545 ptr8[4] = to_bcd8(cur_time->tm_hour);
546 ptr8[5] = to_bcd8(cur_time->tm_min);
547 ptr8[6] = to_bcd8(cur_time->tm_sec);
548 /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
549 tz15min = (cur_time->tm_gmtoff)/(60*15);
550 ptr8[6] = to_bcd8(tz15min);
551 if (tz15min < 0)
552 ptr8[6] |= 0x80;
553#endif
554
555 return gsm48_sendmsg(msg);
556}
557
Harald Welte4b634542008-12-27 01:55:51 +0000558static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
559{
Harald Welte4b634542008-12-27 01:55:51 +0000560 DEBUGP(DMM, "-> CM SERVICE ACK\n");
Harald Welte65e74cc2008-12-29 01:55:35 +0000561 return gsm48_tx_simple(lchan, GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_ACC);
Harald Welte4b634542008-12-27 01:55:51 +0000562}
563
564static int gsm48_rx_mm_serv_req(struct msgb *msg)
565{
566 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +0000567 u_int8_t serv_type = gh->data[0] & 0x0f;
Harald Welte4b634542008-12-27 01:55:51 +0000568
Harald Welte65e74cc2008-12-29 01:55:35 +0000569 DEBUGP(DMM, "<- CM SERVICE REQUEST serv_type=0x%02x\n", serv_type);
Harald Weltebcae43f2008-12-27 21:45:37 +0000570
Harald Welte4b634542008-12-27 01:55:51 +0000571 return gsm48_tx_mm_serv_ack(msg->lchan);
572}
573
Harald Welte52b1f982008-12-23 20:25:15 +0000574static int gsm0408_rcv_mm(struct msgb *msg)
575{
576 struct gsm48_hdr *gh = msgb_l3(msg);
577 int rc;
578
579 switch (gh->msg_type & 0xbf) {
580 case GSM48_MT_MM_LOC_UPD_REQUEST:
Holger Freyther429e7762008-12-30 13:28:30 +0000581 DEBUGP(DMM, "LOCATION UPDATING REQUEST\n");
Harald Welte231ad4f2008-12-27 11:15:38 +0000582 rc = mm_rx_loc_upd_req(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000583 break;
584 case GSM48_MT_MM_ID_RESP:
Harald Welte231ad4f2008-12-27 11:15:38 +0000585 rc = mm_rx_id_resp(msg);
586 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000587 case GSM48_MT_MM_CM_SERV_REQ:
Harald Welte4b634542008-12-27 01:55:51 +0000588 rc = gsm48_rx_mm_serv_req(msg);
589 break;
Harald Welte231ad4f2008-12-27 11:15:38 +0000590 case GSM48_MT_MM_STATUS:
591 DEBUGP(DMM, "MM STATUS: FIXME parse error cond.\n");
592 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000593 case GSM48_MT_MM_CM_REEST_REQ:
Harald Welte231ad4f2008-12-27 11:15:38 +0000594 case GSM48_MT_MM_TMSI_REALL_COMPL:
595 case GSM48_MT_MM_AUTH_RESP:
596 case GSM48_MT_MM_IMSI_DETACH_IND:
Harald Welte52b1f982008-12-23 20:25:15 +0000597 fprintf(stderr, "Unimplemented GSM 04.08 MM msg type 0x%02x\n",
598 gh->msg_type);
599 break;
600 default:
601 fprintf(stderr, "Unknown GSM 04.08 MM msg type 0x%02x\n",
602 gh->msg_type);
603 break;
604 }
605
606 return rc;
607}
608static int gsm0408_rcv_rr(struct msgb *msg)
609{
610 struct gsm48_hdr *gh = msgb_l3(msg);
611
612 switch (gh->msg_type) {
613 case GSM48_MT_RR_CLSM_CHG:
614 DEBUGP(DRR, "CLASSMARK CHANGE\n");
615 /* FIXME: what to do ?!? */
616 break;
Harald Weltefc977a82008-12-27 10:19:37 +0000617 case GSM48_MT_RR_GPRS_SUSP_REQ:
618 DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
619 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000620 case GSM48_MT_RR_PAG_RESP:
621 default:
622 fprintf(stderr, "Unimplemented GSM 04.08 msg type 0x%02x\n",
623 gh->msg_type);
624 break;
625 }
626
627 return 0;
628}
629
Harald Welte4bc90a12008-12-27 16:32:52 +0000630/* Call Control */
631
Harald Welte4bc90a12008-12-27 16:32:52 +0000632static int gsm48_cc_tx_status(struct gsm_lchan *lchan)
633{
634 struct msgb *msg = gsm48_msgb_alloc();
635 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
636 u_int8_t *cause, *call_state;
637
Harald Welte65e74cc2008-12-29 01:55:35 +0000638 gh->proto_discr = GSM48_PDISC_CC;
639
Harald Welte4bc90a12008-12-27 16:32:52 +0000640 msg->lchan = lchan;
641
Harald Welte4bc90a12008-12-27 16:32:52 +0000642 gh->msg_type = GSM48_MT_CC_STATUS;
643
644 cause = msgb_put(msg, 3);
645 cause[0] = 2;
646 cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
647 cause[2] = 0x80 | 30; /* response to status inquiry */
648
649 call_state = msgb_put(msg, 1);
650 call_state[0] = 0xc0 | 0x00;
651
Harald Welte65e74cc2008-12-29 01:55:35 +0000652 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +0000653}
654
Harald Welte6f4b7532008-12-29 00:39:37 +0000655static int gsm48_tx_simple(struct gsm_lchan *lchan,
656 u_int8_t pdisc, u_int8_t msg_type)
Harald Welte4bc90a12008-12-27 16:32:52 +0000657{
658 struct msgb *msg = gsm48_msgb_alloc();
659 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
660
661 msg->lchan = lchan;
662
Harald Welte6f4b7532008-12-29 00:39:37 +0000663 gh->proto_discr = pdisc;
Harald Welte4bc90a12008-12-27 16:32:52 +0000664 gh->msg_type = msg_type;
665
Harald Welte65e74cc2008-12-29 01:55:35 +0000666 return gsm48_sendmsg(msg);
Harald Welte4bc90a12008-12-27 16:32:52 +0000667}
668
669static int gsm48_cc_rx_status_enq(struct msgb *msg)
670{
671 return gsm48_cc_tx_status(msg->lchan);
672}
673
674static int gsm48_cc_rx_setup(struct msgb *msg)
675{
Harald Welte6f4b7532008-12-29 00:39:37 +0000676 return gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC,
677 GSM48_MT_CC_CALL_CONF);
Harald Welte4bc90a12008-12-27 16:32:52 +0000678}
679
Harald Welte65e74cc2008-12-29 01:55:35 +0000680int gsm48_cc_tx_setup(struct gsm_lchan *lchan)
681{
682 struct msgb *msg = gsm48_msgb_alloc();
683 struct gsm48_hdr *gh;
684 struct gsm_call *call = &lchan->call;
685
686 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 8);
687
688 call->type = GSM_CT_MT;
689 msg->lchan = lchan;
690
691 gh->proto_discr = GSM48_PDISC_CC;
692 gh->msg_type = GSM48_MT_CC_SETUP;
693 gh->data[0] = 0x34;
694 gh->data[1] = 0x00;
695 gh->data[2] = 0x5c;
696 gh->data[3] = 0x04;
697 gh->data[4] = 0xb9;
698 gh->data[5] = 0x83;
699 gh->data[6] = 0x32;
700 gh->data[7] = 0x24;
701
702 DEBUGP(DCC, "Sending SETUP\n");
703
704 return gsm48_sendmsg(msg);
705}
706
Harald Welte4bc90a12008-12-27 16:32:52 +0000707static int gsm0408_rcv_cc(struct msgb *msg)
708{
709 struct gsm48_hdr *gh = msgb_l3(msg);
710 u_int8_t msg_type = gh->msg_type & 0xbf;
711 struct gsm_call *call = &msg->lchan->call;
Holger Freyther2eafef52008-12-29 06:42:17 +0000712 struct gsm_network *network = msg->lchan->ts->trx->bts->network;
Harald Welte4bc90a12008-12-27 16:32:52 +0000713 int rc = 0;
714
715 switch (msg_type) {
716 case GSM48_MT_CC_CALL_CONF:
717 /* Response to SETUP */
718 DEBUGP(DCC, "CALL CONFIRM\n");
719 break;
720 case GSM48_MT_CC_RELEASE_COMPL:
721 /* Answer from MS to RELEASE */
722 DEBUGP(DCC, "RELEASE COMPLETE (state->NULL)\n");
Holger Freytherb7193e42008-12-29 17:44:08 +0000723 if (network->call_state_changed)
724 (*network->call_state_changed)(msg->lchan, call->state);
Harald Welte4bc90a12008-12-27 16:32:52 +0000725 call->state = GSM_CSTATE_NULL;
726 break;
727 case GSM48_MT_CC_ALERTING:
728 DEBUGP(DCC, "ALERTING\n");
729 break;
730 case GSM48_MT_CC_CONNECT:
731 DEBUGP(DCC, "CONNECT\n");
732 /* MT: need to respond with CONNECT_ACK */
Harald Welte6f4b7532008-12-29 00:39:37 +0000733 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC,
734 GSM48_MT_CC_CONNECT_ACK);
Harald Welte4bc90a12008-12-27 16:32:52 +0000735 break;
736 case GSM48_MT_CC_CONNECT_ACK:
737 /* MO: Answer to CONNECT */
738 call->state = GSM_CSTATE_ACTIVE;
739 DEBUGP(DCC, "CONNECT_ACK (state->ACTIVE)\n");
740 break;
741 case GSM48_MT_CC_RELEASE:
742 DEBUGP(DCC, "RELEASE\n");
743 /* need to respond with RELEASE_COMPLETE */
744 break;
745 case GSM48_MT_CC_STATUS_ENQ:
746 rc = gsm48_cc_rx_status_enq(msg);
747 break;
748 case GSM48_MT_CC_DISCONNECT:
749 /* Section 5.4.3.2 */
750 DEBUGP(DCC, "DISCONNECT (state->RELEASE_REQ)\n");
751 call->state = GSM_CSTATE_RELEASE_REQ;
752 /* FIXME: clear the network connection */
Harald Welte6f4b7532008-12-29 00:39:37 +0000753 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC,
754 GSM48_MT_CC_RELEASE);
Harald Welte4bc90a12008-12-27 16:32:52 +0000755 break;
756 case GSM48_MT_CC_SETUP:
757 call->type = GSM_CT_MO;
758 call->state = GSM_CSTATE_INITIATED;
759 call->transaction_id = gh->proto_discr & 0xf0;
760 DEBUGP(DCC, "SETUP(tid=0x%02x)\n", call->transaction_id);
Harald Welte6f4b7532008-12-29 00:39:37 +0000761 rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC,
762 GSM48_MT_CC_CONNECT);
Harald Welte4bc90a12008-12-27 16:32:52 +0000763 /* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
764 break;
765 case GSM48_MT_CC_EMERG_SETUP:
766 DEBUGP(DCC, "EMERGENCY SETUP\n");
767 /* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
768 break;
769 default:
770 fprintf(stderr, "Unimplemented GSM 04.08 msg type 0x%02x\n",
771 msg_type);
772 break;
773 }
774
775 return rc;
776}
777
Harald Welte52b1f982008-12-23 20:25:15 +0000778/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
779int gsm0408_rcvmsg(struct msgb *msg)
780{
781 struct gsm48_hdr *gh = msgb_l3(msg);
782 u_int8_t pdisc = gh->proto_discr & 0x0f;
Harald Welte8470bf22008-12-25 23:28:35 +0000783 int rc = 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000784
785 switch (pdisc) {
786 case GSM48_PDISC_CC:
787 rc = gsm0408_rcv_cc(msg);
788 break;
789 case GSM48_PDISC_MM:
790 rc = gsm0408_rcv_mm(msg);
791 break;
792 case GSM48_PDISC_RR:
793 rc = gsm0408_rcv_rr(msg);
794 break;
Harald Weltebcae43f2008-12-27 21:45:37 +0000795 case GSM48_PDISC_SMS:
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000796 rc = gsm0411_rcv_sms(msg);
Harald Weltebcae43f2008-12-27 21:45:37 +0000797 break;
Harald Welte52b1f982008-12-23 20:25:15 +0000798 case GSM48_PDISC_MM_GPRS:
Harald Weltebcae43f2008-12-27 21:45:37 +0000799 case GSM48_PDISC_SM_GPRS:
Harald Welte52b1f982008-12-23 20:25:15 +0000800 fprintf(stderr, "Unimplemented GSM 04.08 discriminator 0x%02d\n",
801 pdisc);
802 break;
803 default:
804 fprintf(stderr, "Unknown GSM 04.08 discriminator 0x%02d\n",
805 pdisc);
806 break;
807 }
808
809 return rc;
810}
Harald Welte8470bf22008-12-25 23:28:35 +0000811
812enum chreq_type {
813 CHREQ_T_EMERG_CALL,
814 CHREQ_T_CALL_REEST_TCH_F,
815 CHREQ_T_CALL_REEST_TCH_H,
816 CHREQ_T_CALL_REEST_TCH_H_DBL,
817 CHREQ_T_SDCCH,
818 CHREQ_T_TCH_F,
819 CHREQ_T_VOICE_CALL_TCH_H,
820 CHREQ_T_DATA_CALL_TCH_H,
821 CHREQ_T_LOCATION_UPD,
822 CHREQ_T_PAG_R_ANY,
823 CHREQ_T_PAG_R_TCH_F,
824 CHREQ_T_PAG_R_TCH_FH,
825};
826
827/* Section 9.1.8 / Table 9.9 */
828struct chreq {
829 u_int8_t val;
830 u_int8_t mask;
831 enum chreq_type type;
832};
833
834/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
835static const struct chreq chreq_type_neci1[] = {
836 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
837 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
838 { 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
839 { 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
840 { 0xe0, 0xe0, CHREQ_T_SDCCH },
841 { 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
842 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
843 { 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
844 { 0x10, 0xf0, CHREQ_T_SDCCH },
845 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
846 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
847 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
848};
849
850/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
851static const struct chreq chreq_type_neci0[] = {
852 { 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
853 { 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
854 { 0xe0, 0xe0, CHREQ_T_TCH_F },
855 { 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
856 { 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
857 { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
858 { 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
859 { 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
860};
861
862static const enum gsm_chan_t ctype_by_chreq[] = {
863 [CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_F,
864 [CHREQ_T_CALL_REEST_TCH_F] = GSM_LCHAN_TCH_F,
865 [CHREQ_T_CALL_REEST_TCH_H] = GSM_LCHAN_TCH_H,
866 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_LCHAN_TCH_H,
867 [CHREQ_T_SDCCH] = GSM_LCHAN_SDCCH,
868 [CHREQ_T_TCH_F] = GSM_LCHAN_TCH_F,
869 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
870 [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
871 [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
872 [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
873 [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
874 [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
875};
876
Harald Weltee14a57c2008-12-29 04:08:28 +0000877static const enum gsm_chreq_reason_t reason_by_chreq[] = {
878 [CHREQ_T_EMERG_CALL] = GSM_CHREQ_REASON_EMERG,
879 [CHREQ_T_CALL_REEST_TCH_F] = GSM_CHREQ_REASON_CALL,
880 [CHREQ_T_CALL_REEST_TCH_H] = GSM_CHREQ_REASON_CALL,
881 [CHREQ_T_CALL_REEST_TCH_H_DBL] = GSM_CHREQ_REASON_CALL,
882 [CHREQ_T_SDCCH] = GSM_CHREQ_REASON_OTHER,
883 [CHREQ_T_TCH_F] = GSM_CHREQ_REASON_OTHER,
884 [CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
885 [CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
886 [CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
887 [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
888 [CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
889 [CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
890};
891
Harald Welte8470bf22008-12-25 23:28:35 +0000892enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
893{
894 int i;
895 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
896
897 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
898 const struct chreq *chr = &chreq_type_neci0[i];
899 if ((ra & chr->mask) == chr->val)
900 return ctype_by_chreq[chr->type];
901 }
902 fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
903 return GSM_LCHAN_SDCCH;
904}
Harald Weltee14a57c2008-12-29 04:08:28 +0000905
906enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
907{
908 int i;
909 /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
910
911 for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
912 const struct chreq *chr = &chreq_type_neci0[i];
913 if ((ra & chr->mask) == chr->val)
914 return reason_by_chreq[chr->type];
915 }
916 fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
917 return GSM_CHREQ_REASON_OTHER;
918}