working state up to location update and classmark inquiry

diff --git a/include/openbsc/abis_rsl.h b/include/openbsc/abis_rsl.h
index cbbb797..219fdd3 100644
--- a/include/openbsc/abis_rsl.h
+++ b/include/openbsc/abis_rsl.h
@@ -244,6 +244,45 @@
 #endif
 } __attribute__ ((packed));
 
+/* Chapter 9.3.26 */
+#define RSL_ERRCLS_NORMAL		0x00
+#define RSL_ERRCLS_RESOURCE_UNAVAIL	0x20
+#define RSL_ERRCLS_SERVICE_UNAVAIL	0x30
+#define RSL_ERRCLS_SERVICE_UNIMPL	0x40
+#define RSL_ERRCLS_INVAL_MSG		0x50
+#define RSL_ERRCLS_PROTO_ERROR		0x60
+#define RSL_ERRCLS_INTERWORKING		0x70
+
+#define RSL_ERR_RADIO_IF_FAIL		0x00
+#define RSL_ERR_RADIO_LINK_FAIL		0x01
+#define RSL_ERR_HANDOVER_ACC_FAIL	0x02
+#define RSL_ERR_TALKER_ACC_FAIL		0x03
+#define RSL_ERR_OM_INTERVENTION		0x07
+#define RSL_ERR_EQUIPMENT_FAIL		0x20
+#define RSL_ERR_RR_UNAVAIL		0x21
+#define RSL_ERR_TERR_CH_FAIL		0x22
+#define RSL_ERR_CCCH_OVERLOAD		0x23
+#define RSL_ERR_ACCH_OVERLOAD		0x24
+#define RSL_ERR_PROCESSOR_OVERLOAD	0x25
+#define RSL_ERR_RES_UNAVAIL		0x2f
+#define RSL_ERR_TRANSC_UNAVAIL		0x30
+#define RSL_ERR_SERV_OPT_UNAVAIL	0x3f
+#define RSL_ERR_ENCR_UNIMPL		0x40
+#define RSL_ERR_SEV_OPT_UNIMPL		0x4f
+#define RSL_ERR_RCH_ALR_ACTV_ALLOC	0x50
+#define RSL_ERR_INVALID_MESSAGE		0x5f
+#define RSL_ERR_MSG_DISCR		0x60
+#define RSL_ERR_MSG_TYPE		0x61
+#define RSL_ERR_MSG_SEQA		0x62
+#define RSL_ERR_IE_ERROR		0x63
+#define RSL_ERR_MAND_IE_ERROR		0x64
+#define RSL_ERR_OPT_IE_ERROR		0x65
+#define RSL_ERR_IE_NONEXIST		0x66
+#define RSL_ERR_IE_LENGTH		0x67
+#define RSL_ERR_IE_CONTENT		0x68
+#define RSL_ERR_PROTO			0x6f
+#define RSL_ERR_INTERWORKING		0x7f
+
 /* Chapter 9.3.30 */
 #define RSL_SYSTEM_INFO_8	0x00
 #define RSL_SYSTEM_INFO_1	0x01
diff --git a/include/openbsc/debug.h b/include/openbsc/debug.h
index 02ae699..b95b1a7 100644
--- a/include/openbsc/debug.h
+++ b/include/openbsc/debug.h
@@ -17,6 +17,6 @@
 #define DEBUGP(xss, fmt, args...) 
 #endif
 
-void debugp(int subsys, char *file, int line, const char *format, ...);
+void debugp(unsigned int subsys, char *file, int line, const char *format, ...);
 
 #endif /* _DEBUG_H */
diff --git a/include/openbsc/tlv.h b/include/openbsc/tlv.h
index 4c00772..38ca811 100644
--- a/include/openbsc/tlv.h
+++ b/include/openbsc/tlv.h
@@ -6,6 +6,7 @@
 
 #define TLV_GROSS_LEN(x)	(x+2)
 #define TLV16_GROSS_LEN(x)	((2*x)+2)
+#define TL16V_GROSS_LEN(x)	(x+3)
 
 static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
 				const u_int8_t *val)
@@ -25,12 +26,29 @@
 	return buf + len*2;
 }
 
+static inline u_int8_t *tl16v_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
+				const u_int8_t *val)
+{
+	*buf++ = tag;
+	*buf++ = len >> 8;
+	*buf++ = len & 0xff;
+	memcpy(buf, val, len);
+	return buf + len*2;
+}
+
 static inline u_int8_t *msgb_tlv16_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int16_t *val)
 {
 	u_int8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
 	return tlv16_put(buf, tag, len, val);
 }
 
+static inline u_int8_t *msgb_tl16v_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
+					const u_int8_t *val)
+{
+	u_int8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
+	return tl16v_put(buf, tag, len, val);
+}
+
 static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag, 
 				u_int8_t val)
 {
diff --git a/src/abis_nm.c b/src/abis_nm.c
index e1a641b..52a5a52 100644
--- a/src/abis_nm.c
+++ b/src/abis_nm.c
@@ -122,7 +122,7 @@
 	struct abis_om_fom_hdr *foh =
 			(struct abis_om_fom_hdr *) oh->data;
 
-	fill_om_hdr(oh, len);
+	fill_om_hdr(oh, len+sizeof(*foh));
 	foh->msg_type = msg_type;
 	foh->obj_class = obj_class;
 	foh->obj_inst.bts_nr = bts_nr;
@@ -183,6 +183,7 @@
 	int rc;
 	struct abis_om_hdr *oh = msgb_l2(msg);
 	unsigned int l2_len = msg->tail - (u_int8_t *)msgb_l2(msg);
+	unsigned int hlen = sizeof(*oh) + sizeof(struct abis_om_fom_hdr);
 
 	/* Various consistency checks */
 	if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
@@ -195,14 +196,15 @@
 			oh->sequence);
 		return -EINVAL;
 	}
-	if (oh->length + sizeof(*oh) > l2_len) {
+#if 0
+	if (oh->length + hlen > l2_len) {
 		fprintf(stderr, "ABIS OML truncated message (%u > %u)\n",
 			oh->length + sizeof(*oh), l2_len);
 		return -EINVAL;
 	}
-	if (oh->length + sizeof(*oh) < l2_len)
-		fprintf(stderr, "ABIS OML message with extra trailer?!?\n");
-
+	if (oh->length + hlen < l2_len)
+		fprintf(stderr, "ABIS OML message with extra trailer?!? (oh->len=%d, sizeof_oh=%d l2_len=%d\n", oh->length, sizeof(*oh), l2_len);
+#endif
 	msg->l3h = (unsigned char *)oh + sizeof(*oh);
 
 	switch (oh->mdisc) {
@@ -295,7 +297,7 @@
 	struct abis_om_hdr *oh;
 	struct abis_nm_channel *ch;
 	u_int8_t *tei_attr;
-	u_int8_t len = 2 + sizeof(*ch);
+	u_int8_t len = sizeof(*ch) + 2;
 	struct msgb *msg = nm_msgb_alloc();
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
@@ -320,7 +322,7 @@
 	struct msgb *msg = nm_msgb_alloc();
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, sizeof(*ch), NM_MT_CONN_TERR_SIGN,
+	fill_om_fom_hdr(oh, sizeof(*oh), NM_MT_CONN_TERR_SIGN,
 			NM_OC_RADIO_CARRIER, bts->bts_nr, trx->nr, 0xff);
 	
 	ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
@@ -370,9 +372,10 @@
 	u_int16_t arfcn = htons(ts->trx->arfcn);
 	u_int8_t zero = 0x00;
 	struct msgb *msg = nm_msgb_alloc();
+	u_int8_t len = 4 + 2 + 2 + 2 + 2 +3;
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, sizeof(*oh), NM_MT_SET_CHAN_ATTR,
+	fill_om_fom_hdr(oh, len, NM_MT_SET_CHAN_ATTR,
 			NM_OC_BASEB_TRANSC, bts->bts_nr,
 			ts->trx->nr, ts->nr);
 	/* FIXME: don't send ARFCN list, hopping sequence, mAIO, ...*/
@@ -407,7 +410,7 @@
 	struct msgb *msg = nm_msgb_alloc();
 
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
-	fill_om_fom_hdr(oh, sizeof(*oh), msg_type, NM_OC_SITE_MANAGER,
+	fill_om_fom_hdr(oh, 0, msg_type, NM_OC_SITE_MANAGER,
 			0xff, 0xff, 0xff);
 
 	return abis_nm_sendmsg(bts, msg);
diff --git a/src/abis_rsl.c b/src/abis_rsl.c
index 257b118..df34929 100644
--- a/src/abis_rsl.c
+++ b/src/abis_rsl.c
@@ -247,7 +247,7 @@
 	ch->msg_type = RSL_MT_SACCH_FILL;
 
 	msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
-	msgb_tlv_put(msg, RSL_IE_L3_INFO, len, data);
+	msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
 
 	msg->trx = bts->c0;
 
@@ -275,11 +275,13 @@
 	msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(*chan_mode),
 		     (u_int8_t *) chan_mode);
 	msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
-		     (u_int8_t *) &chan_ident);
+		     (u_int8_t *) chan_ident);
 	/* FIXME: this shoould be optional */
+#if 0
 	msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
 		     (u_int8_t *) &encr_info);
 	msgb_tv_put(msg, RSL_IE_BS_POWER, bs_power);
+#endif
 	msgb_tv_put(msg, RSL_IE_MS_POWER, ms_power);
 	msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
 
@@ -313,9 +315,9 @@
 	return rsl_chan_activate(ts->trx->bts, chan_nr, 0x01, &cm, &ci, 0x01, 0x0f, 0x00);
 }
 
-int rsl_chan_activate_sdcch(struct gsm_bts_trx_ts *ts)
+int rsl_chan_activate_sdcch4(struct gsm_bts_trx_ts *ts, int subslot)
 {
-	u_int8_t chan_nr = rsl_enc_chan_nr(RSL_CHAN_SDCCH4_ACCH, 0, ts->nr);
+	u_int8_t chan_nr = rsl_enc_chan_nr(RSL_CHAN_SDCCH4_ACCH, subslot, ts->nr);
 	u_int16_t arfcn = ts->trx->arfcn;
 	struct rsl_ie_chan_mode cm;
 	struct rsl_ie_chan_ident ci;
@@ -393,6 +395,7 @@
 }
 #endif
 
+/* Chapter 8.5.6 */
 int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val)
 {
 	struct msgb *msg = rsl_msgb_alloc();
@@ -437,6 +440,17 @@
 	return abis_rsl_sendmsg(msg);
 }
 
+/* Chapter 8.4.2: Channel Activate Acknowledge */
+static int rsl_rx_chan_act_ack(struct msgb *msg)
+{
+	struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
+
+	/* BTS has confirmed channel activation, we now need
+	 * to assign the activated channel to the MS */
+
+
+}
+
 static int abis_rsl_rx_dchan(struct msgb *msg)
 {
 	struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg);
@@ -447,6 +461,7 @@
 	switch (rslh->c.msg_type) {
 	case RSL_MT_CHAN_ACTIV_ACK:
 		DEBUGP(DRSL, "rsl_rx_dchan: Channel Activate ACK\n");
+		rc = rsl_rx_chan_act_ack(msg);
 		break;
 	case RSL_MT_CHAN_ACTIV_NACK:
 		DEBUGP(DRSL, "rsl_rx_dchan: Channel Activate NACK\n");
@@ -479,17 +494,34 @@
 	return rc;
 }
 
+static int rsl_rx_error_rep(struct msgb *msg)
+{
+	struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
+	u_int8_t cause_len;
+
+	if (rslh->data[0] != RSL_IE_CAUSE)
+		return -EINVAL;
+
+	cause_len = rslh->data[1];
+	printf(stdout, "RSL ERROR REPORT, Cause ");
+	hexdump(&rslh->data[2], cause_len);
+
+	return 0;
+}
+
 static int abis_rsl_rx_trx(struct msgb *msg)
 {
-	struct abis_rsl_common_hdr *rslh = msgb_l2(msg)	;
+	struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
 	int rc = 0;
 
 	switch (rslh->msg_type) {
+	case RSL_MT_ERROR_REPORT:
+		rc = rsl_rx_error_rep(msg);
+		break;
 	case RSL_MT_RF_RES_IND:
 		/* interference on idle channels of TRX */
 	case RSL_MT_OVERLOAD:
 		/* indicate CCCH / ACCH / processor overload */ 
-	case RSL_MT_ERROR_REPORT:
 		fprintf(stderr, "Unimplemented Abis RSL TRX message type 0x%02x\n",
 			rslh->msg_type);
 		break;
@@ -504,7 +536,7 @@
 /* MS has requested a channel on the RACH */
 static int rsl_rx_chan_rqd(struct msgb *msg)
 {
-	struct gsm_bts *bts = msg->bts_link->bts;
+	struct gsm_bts *bts = msg->trx->bts;
 	struct abis_rsl_dchan_hdr *rqd_hdr = msgb_l2(msg);
 	struct gsm48_req_ref *rqd_ref;
 	struct gsm48_imm_ass ia;
@@ -546,8 +578,8 @@
 		arfcn, ts_number, subch, lchan->type);
 
 	/* send CHANNEL ACTIVATION on RSL to BTS */
-	if (lchan->ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C)
-		rsl_chan_activate_sdcch(lchan->ts);
+	if (lchan->ts->pchan == GSM_PCHAN_CCCH_SDCCH4)
+		rsl_chan_activate_sdcch4(lchan->ts, subch);
 	else
 		rsl_chan_activate_tch_f(lchan->ts);
 
@@ -557,7 +589,7 @@
 	ia.proto_discr = GSM48_PDISC_RR;
 	ia.msg_type = GSM48_MT_RR_IMM_ASS;
 	ia.page_mode = GSM48_PM_NORMAL;
-	ia.chan_desc.chan_nr = rsl_enc_chan_nr(lchan->ts->pchan, subch, ts_number);
+	ia.chan_desc.chan_nr = rsl_enc_chan_nr(RSL_CHAN_SDCCH4_ACCH, subch, ts_number);
 	ia.chan_desc.h0.h = 0;
 	ia.chan_desc.h0.arfcn_high = arfcn >> 8;
 	ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
@@ -618,13 +650,13 @@
 	case RSL_MT_DATA_IND:
 		DEBUGP(DRLL, "DATA INDICATION\n");
 		/* FIXME: Verify L3 info element */
-		msg->l3h = &rllh->data[2];
+		msg->l3h = &rllh->data[3];
 		rc = gsm0408_rcvmsg(msg);
 		break;
 	case RSL_MT_EST_IND:
 		DEBUGP(DRLL, "ESTABLISH INDICATION\n");
 		/* FIXME: Verify L3 info element */
-		msg->l3h = &rllh->data[2];
+		msg->l3h = &rllh->data[3];
 		rc = gsm0408_rcvmsg(msg);
 		break;
 	case RSL_MT_ERROR_IND:
diff --git a/src/bsc_hack.c b/src/bsc_hack.c
index b0d7265..384f25d 100644
--- a/src/bsc_hack.c
+++ b/src/bsc_hack.c
@@ -31,6 +31,7 @@
 #include <openbsc/select.h>
 #include <openbsc/abis_rsl.h>
 #include <openbsc/abis_nm.h>
+#include <openbsc/debug.h>
 
 /* global pointer to the gsm network data structure */
 static struct gsm_network *gsmnet;
@@ -252,6 +253,15 @@
 	/* begin DB transmission */
 	abis_nm_db_transmission(bts, 1);
 
+	/* end DB transmission */
+	abis_nm_db_transmission(bts, 0);
+
+	/* Reset BTS Site manager resource */
+	abis_nm_reset_resource(bts);
+
+	/* begin DB transmission */
+	abis_nm_db_transmission(bts, 1);
+
 	abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
 	abis_nm_raw_msg(bts, sizeof(msg_2), msg_2); /* set BTS attr */
 	abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
@@ -533,7 +543,7 @@
 	set_system_infos(bts);
 
 	/* FIXME: defer this until the channels are used */
-	activate_traffic_channels(&bts->trx[0]);
+	//activate_traffic_channels(&bts->trx[0]);
 }
 
 static void mi_cb(int event, struct gsm_bts *bts)
@@ -570,13 +580,18 @@
 	return 0;
 }
 
-void debugp(int subsys, char *file, int line, const char *format, ...)
+static unsigned int debug_mask = 0xffffffff & ~DMI;
+
+void debugp(unsigned int subsys, char *file, int line, const char *format, ...)
 {
 	char *timestr;
 	va_list ap;
 	time_t tm;
 	FILE *outfd = stderr;
 
+	if (!(debug_mask & subsys))
+		return;
+
 	va_start(ap, format);
 	
 	tm = time(NULL);
diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c
index 397f131..212b4ad 100644
--- a/src/gsm_04_08.c
+++ b/src/gsm_04_08.c
@@ -200,7 +200,7 @@
 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 gsm_bts *bts = msg->trx->bts;
 	struct gsm48_loc_upd_req *lu;
 	struct gsm_subscriber *subscr;
 	u_int8_t mi_type;
diff --git a/src/gsm_data.c b/src/gsm_data.c
index e5ba906..61f8682 100644
--- a/src/gsm_data.c
+++ b/src/gsm_data.c
@@ -76,6 +76,8 @@
 		}
 
 		bts->num_trx = 1;	/* FIXME */
+		bts->c0 = &bts->trx[0];
+		bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
 	}
 	return net;
 }
diff --git a/src/misdn.c b/src/misdn.c
index 366580c..dfc3a65 100644
--- a/src/misdn.c
+++ b/src/misdn.c
@@ -72,7 +72,7 @@
 #define TEI_OML		25
 #define TEI_RSL		1
 
-static void hexdump(unsigned char *buf, int len)
+void hexdump(unsigned char *buf, int len)
 {
 	int i;
 	for (i = 0; i < len; i++) {
@@ -169,9 +169,6 @@
 	case DL_DATA_IND:
 		DEBUGP(DMI, "got DL_DATA_IND\n");
 
-		/* FIXME: this stinks */
-		msg->trx = e1h->bts->c0;
-
 		msg->l2h = msg->data + MISDN_HEADER_LEN;
 		
 		fprintf(stdout, "RX: ");
@@ -243,6 +240,7 @@
 			     sizeof(e1h->l2addr));
 		msgb_free(msg);
 		usleep(100000);
+		//sleep(1);
 	}
 
 	return ret;
diff --git a/src/msgb.c b/src/msgb.c
index 249fed9..f039be0 100644
--- a/src/msgb.c
+++ b/src/msgb.c
@@ -30,6 +30,7 @@
 
 	if (!msg)
 		return NULL;
+	memset(msg, 0, sizeof(*msg)+size);
 
 	msg->data_len = size;
 	msg->len = 0;