no reasonable commit message possible. tons of changes of the last 2 days

diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c
index 4165b78..397f131 100644
--- a/src/gsm_04_08.c
+++ b/src/gsm_04_08.c
@@ -2,6 +2,7 @@
  * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
 
 /* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ *
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -26,13 +27,15 @@
 #include <string.h>
 #include <errno.h>
 
-#include "msgb.h"
-#include "debug.h"
-#include "gsm_data.h"
-#include "gsm_subscriber.h"
-#include "gsm_04_08.h"
+#include <openbsc/msgb.h>
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/gsm_04_08.h>
+#include <openbsc/abis_rsl.h>
 
-#define GSM0408_ALLOC_SIZE	1024
+#define GSM48_ALLOC_SIZE	1024
+#define GSM48_ALLOC_HEADROOM	128
 
 struct gsm_lai {
 	u_int16_t mcc;
@@ -79,8 +82,8 @@
 	lai48->digits[1] = bcd[2];
 
 	to_bcd(bcd, mnc);
-	lai48->digits[2] |= bcd[2] << 4;
-	lai48->digits[3] = bcd[0] | (bcd[1] << 4);
+	lai48->digits[1] |= bcd[2] << 4;
+	lai48->digits[2] = bcd[0] | (bcd[1] << 4);
 	
 	lai48->lac = lac;
 }
@@ -98,11 +101,17 @@
 	buf[5] = tmsi_bcd[3];
 }
 
+static struct msgb *gsm48_msgb_alloc(void)
+{
+	return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM);
+}
+
 static int gsm0408_sendmsg(struct msgb *msg)
 {
-	/* FIXME: set data pointer to beginning of L3 data object */
+	if (msg->lchan)
+		msg->trx = msg->lchan->ts->trx;
 
-	return rsl_data_request(msg);
+	return rsl_data_request(msg, 0);
 }
 
 static int gsm0408_rcv_cc(struct msgb *msg)
@@ -138,15 +147,17 @@
 			gh->msg_type);
 		break;
 	}
+
+	return 0;
 }
 
 /* Chapter 9.2.14 : Send LOCATION UPDATE REJECT */
-int gsm0408_loc_upd_rej(struct gsm_bts_link *bts_link, u_int8_t cause)
+int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
 {
-	struct msgb *msg = msgb_alloc(GSM0408_ALLOC_SIZE);
+	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
 	
-	msg->bts_link = bts_link;
+	msg->lchan = lchan;
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
 	gh->proto_discr = GSM48_PDISC_MM;
@@ -159,15 +170,15 @@
 }
 
 /* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
-int gsm0408_loc_upd_acc(struct gsm_bts_link *bts_link, u_int8_t *tmsi)
+int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int8_t *tmsi)
 {
-	struct gsm_bts *bts = bts_link->bts;
-	struct msgb *msg = msgb_alloc(GSM0408_ALLOC_SIZE);
+	struct gsm_bts *bts = lchan->ts->trx->bts;
+	struct msgb *msg = gsm48_msgb_alloc();
 	struct gsm48_hdr *gh;
 	struct gsm48_loc_area_id *lai;
 	u_int8_t *mid;
 	
-	msg->bts_link = bts_link;
+	msg->lchan = lchan;
 
 	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 	gh->proto_discr = GSM48_PDISC_MM;
@@ -185,15 +196,18 @@
 	return gsm0408_sendmsg(msg);
 }
 
-
 /* Chapter 9.2.15 */
 static int mm_loc_upd_req(struct msgb *msg)
 {
+	struct gsm48_hdr *gh = msgb_l3(msg);
 	struct gsm_bts *bts = msg->bts_link->bts;
 	struct gsm48_loc_upd_req *lu;
 	struct gsm_subscriber *subscr;
+	u_int8_t mi_type;
 
-	u_int8_t mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
+ 	lu = (struct gsm48_loc_upd_req *) gh->data;
+
+	mi_type = lu->mi[0] & GSM_MI_TYPE_MASK;
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_IMSI:
@@ -220,12 +234,14 @@
 
 	if (!subscr) {
 		/* 0x16 is congestion */
-		gsm0408_loc_upd_rej(msg->bts_link, 0x16);
+		gsm0408_loc_upd_rej(msg->lchan, 0x16);
 		return -EINVAL;
 	}
 
+	msg->lchan->subscr = subscr;
 	subscr_update(subscr, bts);
-	return gsm0408_loc_upd_acc(msg->bts_link, subscr->tmsi);
+
+	return gsm0408_loc_upd_acc(msg->lchan, subscr->tmsi);
 }
 
 static int gsm0408_rcv_mm(struct msgb *msg)
@@ -279,7 +295,7 @@
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
 	u_int8_t pdisc = gh->proto_discr & 0x0f;
-	int rc;
+	int rc = 0;
 	
 	switch (pdisc) {
 	case GSM48_PDISC_CC:
@@ -304,3 +320,82 @@
 
 	return rc;
 }
+
+enum chreq_type {
+	CHREQ_T_EMERG_CALL,
+	CHREQ_T_CALL_REEST_TCH_F,
+	CHREQ_T_CALL_REEST_TCH_H,
+	CHREQ_T_CALL_REEST_TCH_H_DBL,
+	CHREQ_T_SDCCH,
+	CHREQ_T_TCH_F,
+	CHREQ_T_VOICE_CALL_TCH_H,
+	CHREQ_T_DATA_CALL_TCH_H,
+	CHREQ_T_LOCATION_UPD,
+	CHREQ_T_PAG_R_ANY,
+	CHREQ_T_PAG_R_TCH_F,
+	CHREQ_T_PAG_R_TCH_FH,
+};
+
+/* Section 9.1.8 / Table 9.9 */
+struct chreq {
+	u_int8_t val;
+	u_int8_t mask;
+	enum chreq_type type;
+};
+
+/* If SYSTEM INFORMATION TYPE 4 NECI bit == 1 */
+static const struct chreq chreq_type_neci1[] = {
+	{ 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
+	{ 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_F },
+	{ 0x68, 0xfc, CHREQ_T_CALL_REEST_TCH_H },
+	{ 0x6c, 0xfc, CHREQ_T_CALL_REEST_TCH_H_DBL },
+	{ 0xe0, 0xe0, CHREQ_T_SDCCH },
+	{ 0x40, 0xf0, CHREQ_T_VOICE_CALL_TCH_H },
+	{ 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
+	{ 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
+	{ 0x10, 0xf0, CHREQ_T_SDCCH },
+	{ 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
+	{ 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
+	{ 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
+};
+
+/* If SYSTEM INFORMATION TYPE 4 NECI bit == 0 */
+static const struct chreq chreq_type_neci0[] = {
+	{ 0xa0, 0xe0, CHREQ_T_EMERG_CALL },
+	{ 0xc0, 0xe0, CHREQ_T_CALL_REEST_TCH_H },
+	{ 0xe0, 0xe0, CHREQ_T_TCH_F },
+	{ 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
+	{ 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
+	{ 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
+	{ 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
+	{ 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
+};
+
+static const enum gsm_chan_t ctype_by_chreq[] = {
+	[CHREQ_T_EMERG_CALL]		= GSM_LCHAN_TCH_F,
+	[CHREQ_T_CALL_REEST_TCH_F]	= GSM_LCHAN_TCH_F,
+	[CHREQ_T_CALL_REEST_TCH_H]	= GSM_LCHAN_TCH_H,
+	[CHREQ_T_CALL_REEST_TCH_H_DBL]	= GSM_LCHAN_TCH_H,
+	[CHREQ_T_SDCCH]			= GSM_LCHAN_SDCCH,
+	[CHREQ_T_TCH_F]			= GSM_LCHAN_TCH_F,
+	[CHREQ_T_VOICE_CALL_TCH_H]	= GSM_LCHAN_TCH_H,
+	[CHREQ_T_DATA_CALL_TCH_H]	= GSM_LCHAN_TCH_H,
+	[CHREQ_T_LOCATION_UPD]		= GSM_LCHAN_SDCCH,
+	[CHREQ_T_PAG_R_ANY]		= GSM_LCHAN_SDCCH,
+	[CHREQ_T_PAG_R_TCH_F]		= GSM_LCHAN_TCH_F,
+	[CHREQ_T_PAG_R_TCH_FH]		= GSM_LCHAN_TCH_F,
+};
+
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
+{
+	int i;
+	/* FIXME: determine if we set NECI = 0 in the BTS SI4 */
+
+	for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
+		const struct chreq *chr = &chreq_type_neci0[i];
+		if ((ra & chr->mask) == chr->val)
+			return ctype_by_chreq[chr->type];
+	}
+	fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
+	return GSM_LCHAN_SDCCH;
+}