src: port openBSC over libosmo-abis

This is a big patch that ports openBSC over libosmo-abis.
Sorry, the changes that are included here are all dependent
of libosmo-abis, splitting them into smaller pieces would
leave the repository in some intermediate state, which is
not desired.

The main changes are:

- The directory libabis/ has been removed as it now lives in
  libosmo-abis.

- new configuration file format for nanoBTS and HSL femto, we
  need to define the virtual e1_line and attach it to the OML
  link.

- all the existing BTS drivers (nanoBTS, hsl femto, Nokia site,
  BS11 and rbs2000) now use the new libosmo-abis framework.

- use r232 input driver available in libosmo-abis for bs11_config.

- use ipa_msg_recv instead of old ipaccess_read_msg function.

- delete definition of gsm_e1_subslot and input_signal_data.
  These structures now lives in libosmo-abis.

Most of this patch are deletions of libabis/ which has been
moved to libosmo-abis.

This patch also modifies openBSC to use all the new definitions
available in libosmocore and libosmo-abis. In order to do that,
we have replaced the following:

- DINP, DMI, DMIB and DMUX by their respective DL* correspondences.
- SS_GLOBAL by SS_L_GLOBAL
- SS_INPUT by SS_L_INPUT
- S_GLOBAL_SHUTDOWN by S_L_GLOBAL_SHUTDOWN
- SS_INPUT by SS_L_INPUT
- S_INP_* by S_L_INP_* sub-signals
- E1INP_NODE by L_E1INP_NODE vty node

This patch has been tested with:
- one nanoBTS
- the HSL femto with the examples available under libosmo-abis
- BS11 with both dahdi and misdn drivers.
diff --git a/openbsc/src/libtrau/Makefile.am b/openbsc/src/libtrau/Makefile.am
index 6b70a9a..802c455 100644
--- a/openbsc/src/libtrau/Makefile.am
+++ b/openbsc/src/libtrau/Makefile.am
@@ -1,7 +1,7 @@
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
-AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
-AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOABIS_LIBS) $(COVERAGE_LDFLAGS)
 
 noinst_LIBRARIES = libtrau.a
 
-libtrau_a_SOURCES = rtp_proxy.c subchan_demux.c trau_frame.c trau_mux.c trau_upqueue.c
+libtrau_a_SOURCES = rtp_proxy.c trau_mux.c trau_upqueue.c
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index 4c5f12e..2aa3a1e 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -111,25 +111,25 @@
 	int x_len;
 
 	if (msg->len < 12) {
-		DEBUGPC(DMUX, "received RTP frame too short (len = %d)\n",
+		DEBUGPC(DLMUX, "received RTP frame too short (len = %d)\n",
 			msg->len);
 		return -EINVAL;
 	}
 	if (rtph->version != RTP_VERSION) {
-		DEBUGPC(DMUX, "received RTP version %d not supported.\n",
+		DEBUGPC(DLMUX, "received RTP version %d not supported.\n",
 			rtph->version);
 		return -EINVAL;
 	}
 	payload = msg->data + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2);
 	payload_len = msg->len - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2);
 	if (payload_len < 0) {
-		DEBUGPC(DMUX, "received RTP frame too short (len = %d, "
+		DEBUGPC(DLMUX, "received RTP frame too short (len = %d, "
 			"csrc count = %d)\n", msg->len, rtph->csrc_count);
 		return -EINVAL;
 	}
 	if (rtph->extension) {
 		if (payload_len < sizeof(struct rtp_x_hdr)) {
-			DEBUGPC(DMUX, "received RTP frame too short for "
+			DEBUGPC(DLMUX, "received RTP frame too short for "
 				"extension header\n");
 			return -EINVAL;
 		}
@@ -138,20 +138,20 @@
 		payload += x_len;
 		payload_len -= x_len;
 		if (payload_len < 0) {
-			DEBUGPC(DMUX, "received RTP frame too short, "
+			DEBUGPC(DLMUX, "received RTP frame too short, "
 				"extension header exceeds frame length\n");
 			return -EINVAL;
 		}
 	}
 	if (rtph->padding) {
 		if (payload_len < 0) {
-			DEBUGPC(DMUX, "received RTP frame too short for "
+			DEBUGPC(DLMUX, "received RTP frame too short for "
 				"padding length\n");
 			return -EINVAL;
 		}
 		payload_len -= payload[payload_len - 1];
 		if (payload_len < 0) {
-			DEBUGPC(DMUX, "received RTP frame with padding "
+			DEBUGPC(DLMUX, "received RTP frame with padding "
 				"greater than payload\n");
 			return -EINVAL;
 		}
@@ -161,7 +161,7 @@
 	case RTP_PT_GSM_FULL:
 		msg_type = GSM_TCHF_FRAME;
 		if (payload_len != 33) {
-			DEBUGPC(DMUX, "received RTP full rate frame with "
+			DEBUGPC(DLMUX, "received RTP full rate frame with "
 				"payload length != 32 (len = %d)\n",
 				payload_len);
 			return -EINVAL;
@@ -171,7 +171,7 @@
 		msg_type = GSM_TCHF_FRAME_EFR;
 		break;
 	default:
-		DEBUGPC(DMUX, "received RTP frame with unknown payload "
+		DEBUGPC(DLMUX, "received RTP frame with unknown payload "
 			"type %d\n", rtph->payload_type);
 		return -EINVAL;
 	}
@@ -235,7 +235,7 @@
 		duration = 160;
 		break;
 	default:
-		DEBUGPC(DMUX, "unsupported message type %d\n",
+		DEBUGPC(DLMUX, "unsupported message type %d\n",
 			frame->msg_type);
 		return -EINVAL;
 	}
@@ -254,7 +254,7 @@
 		if (abs(frame_diff) > 1) {
 			long int frame_diff_excess = frame_diff - 1;
 
-			LOGP(DMUX, LOGL_NOTICE,
+			LOGP(DLMUX, LOGL_NOTICE,
 				"Correcting frame difference of %ld frames\n", frame_diff_excess);
 			rs->transmit.sequence += frame_diff_excess;
 			rs->transmit.timestamp += frame_diff_excess * duration;
@@ -355,7 +355,7 @@
 	while ((void *)rtph + sizeof(*rtph) <= (void *)msg->data + msg->len) {
 		old_len = (ntohs(rtph->length) + 1) * 4;
 		if ((void *)rtph + old_len > (void *)msg->data + msg->len) {
-			DEBUGPC(DMUX, "received RTCP packet too short for "
+			DEBUGPC(DLMUX, "received RTCP packet too short for "
 				"length element\n");
 			return -EINVAL;
 		}
@@ -471,7 +471,7 @@
 
 	written = write(rss->bfd.fd, msg->data, msg->len);
 	if (written < msg->len) {
-		LOGP(DMIB, LOGL_ERROR, "short write");
+		LOGP(DLMIB, LOGL_ERROR, "short write");
 		msgb_free(msg);
 		return -EIO;
 	}
@@ -523,7 +523,7 @@
 	int rc;
 	struct rtp_socket *rs;
 
-	DEBUGP(DMUX, "rtp_socket_create(): ");
+	DEBUGP(DLMUX, "rtp_socket_create(): ");
 
 	rs = talloc_zero(tall_bsc_ctx, struct rtp_socket);
 	if (!rs)
@@ -550,7 +550,7 @@
 	if (rc < 0)
 		goto out_rtcp_socket;
 
-	DEBUGPC(DMUX, "success\n");
+	DEBUGPC(DLMUX, "success\n");
 
 	rc = rtp_socket_bind(rs, INADDR_ANY);
 	if (rc < 0)
@@ -568,7 +568,7 @@
 	close(rs->rtp.bfd.fd);
 out_free:
 	talloc_free(rs);
-	DEBUGPC(DMUX, "failed\n");
+	DEBUGPC(DLMUX, "failed\n");
 	return NULL;
 }
 
@@ -604,7 +604,7 @@
 	struct in_addr ia;
 
 	ia.s_addr = htonl(ip);
-	DEBUGP(DMUX, "rtp_socket_bind(rs=%p, IP=%s): ", rs,
+	DEBUGP(DLMUX, "rtp_socket_bind(rs=%p, IP=%s): ", rs,
 		inet_ntoa(ia));
 
 	/* try to bind to a consecutive pair of ports */
@@ -619,12 +619,12 @@
 			break;
 	}
 	if (rc < 0) {
-		DEBUGPC(DMUX, "failed\n");
+		DEBUGPC(DLMUX, "failed\n");
 		return rc;
 	}
 
 	ia.s_addr = rs->rtp.sin_local.sin_addr.s_addr;
-	DEBUGPC(DMUX, "BOUND_IP=%s, BOUND_PORT=%u\n",
+	DEBUGPC(DLMUX, "BOUND_IP=%s, BOUND_PORT=%u\n",
 		inet_ntoa(ia), ntohs(rs->rtp.sin_local.sin_port));
 	return ntohs(rs->rtp.sin_local.sin_port);
 }
@@ -655,7 +655,7 @@
 	struct in_addr ia;
 
 	ia.s_addr = htonl(ip);
-	DEBUGP(DMUX, "rtp_socket_connect(rs=%p, ip=%s, port=%u)\n",
+	DEBUGP(DLMUX, "rtp_socket_connect(rs=%p, ip=%s, port=%u)\n",
 		rs, inet_ntoa(ia), port);
 
 	rc = rtp_sub_socket_connect(&rs->rtp, ip, port);
@@ -668,7 +668,7 @@
 /* bind two RTP/RTCP sockets together */
 int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other)
 {
-	DEBUGP(DMUX, "rtp_socket_proxy(this=%p, other=%p)\n",
+	DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, other=%p)\n",
 		this, other);
 
 	this->rx_action = RTP_PROXY;
@@ -684,7 +684,7 @@
 int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net,
 			uint32_t callref)
 {
-	DEBUGP(DMUX, "rtp_socket_proxy(this=%p, callref=%u)\n",
+	DEBUGP(DLMUX, "rtp_socket_proxy(this=%p, callref=%u)\n",
 		this, callref);
 
 	if (callref) {
@@ -707,7 +707,7 @@
 
 int rtp_socket_free(struct rtp_socket *rs)
 {
-	DEBUGP(DMUX, "rtp_socket_free(rs=%p)\n", rs);
+	DEBUGP(DLMUX, "rtp_socket_free(rs=%p)\n", rs);
 
 	/* make sure we don't leave references dangling to us */
 	if (rs->rx_action == RTP_PROXY &&
diff --git a/openbsc/src/libtrau/subchan_demux.c b/openbsc/src/libtrau/subchan_demux.c
deleted file mode 100644
index 740d2ca..0000000
--- a/openbsc/src/libtrau/subchan_demux.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/* A E1 sub-channel (de)multiplexer with TRAU frame sync */
-
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include <openbsc/subchan_demux.h>
-#include <openbsc/trau_frame.h>
-#include <openbsc/debug.h>
-#include <osmocom/core/talloc.h>
-#include <openbsc/gsm_data.h>
-
-void *tall_tqe_ctx;
-
-static inline void append_bit(struct demux_subch *sch, uint8_t bit)
-{
-	sch->out_bitbuf[sch->out_idx++] = bit;
-}
-
-#define SYNC_HDR_BITS	16
-static const uint8_t nullbytes[SYNC_HDR_BITS];
-
-/* check if we have just completed the 16 bit zero sync header,
- * in accordance with GSM TS 08.60 Chapter 4.8.1 */
-static int sync_hdr_complete(struct demux_subch *sch, uint8_t bit)
-{
-	if (bit == 0)
-		sch->consecutive_zeros++;
-	else
-		sch->consecutive_zeros = 0;
-
-	if (sch->consecutive_zeros >= SYNC_HDR_BITS) {
-		sch->consecutive_zeros = 0;
-		return 1;
-	}
-
-	return 0;
-}
-
-/* resynchronize to current location */
-static void resync_to_here(struct demux_subch *sch)
-{
-	memset(sch->out_bitbuf, 0, SYNC_HDR_BITS);
-
-	/* set index in a way that we can continue receiving bits after
-	 * the end of the SYNC header */
-	sch->out_idx = SYNC_HDR_BITS;
-	sch->in_sync = 1;
-}
-
-int subch_demux_init(struct subch_demux *dmx)
-{
-	int i;
-
-	dmx->chan_activ = 0;
-	for (i = 0; i < NR_SUBCH; i++) {
-		struct demux_subch *sch = &dmx->subch[i];
-		sch->out_idx = 0;
-		memset(sch->out_bitbuf, 0xff, sizeof(sch->out_bitbuf));
-	}
-	return 0;
-}
-
-/* input some arbitrary (modulo 4) number of bytes of a 64k E1 channel,
- * split it into the 16k subchannels */
-int subch_demux_in(struct subch_demux *dmx, uint8_t *data, int len)
-{
-	int i, c;
-
-	/* we avoid partially filled bytes in outbuf */
-	if (len % 4)
-		return -EINVAL;
-
-	for (i = 0; i < len; i++) {
-		uint8_t inbyte = data[i];
-
-		for (c = 0; c < NR_SUBCH; c++) {
-			struct demux_subch *sch = &dmx->subch[c];
-			uint8_t inbits;
-			uint8_t bit;
-
-			/* ignore inactive subchannels */
-			if (!(dmx->chan_activ & (1 << c)))
-				continue;
-
-			inbits = inbyte >> (c << 1);
-
-			/* two bits for each subchannel */
-			if (inbits & 0x01)
-				bit = 1;
-			else
-				bit = 0;
-			append_bit(sch, bit);
-
-			if (sync_hdr_complete(sch, bit))
-				resync_to_here(sch);
-
-			if (inbits & 0x02)
-				bit = 1;
-			else
-				bit = 0;
-			append_bit(sch, bit);
-
-			if (sync_hdr_complete(sch, bit))
-				resync_to_here(sch);
-
-			/* FIXME: verify the first bit in octet 2, 4, 6, ...
-			 * according to TS 08.60 4.8.1 */
-
-			/* once we have reached TRAU_FRAME_BITS, call
-			 * the TRAU frame handler callback function */
-			if (sch->out_idx >= TRAU_FRAME_BITS) {
-				if (sch->in_sync) {
-					dmx->out_cb(dmx, c, sch->out_bitbuf,
-					    sch->out_idx, dmx->data);
-					sch->in_sync = 0;
-				}
-				sch->out_idx = 0;
-			}
-		}
-	}
-	return i;
-}
-
-int subch_demux_activate(struct subch_demux *dmx, int subch)
-{
-	if (subch >= NR_SUBCH)
-		return -EINVAL;
-
-	dmx->chan_activ |= (1 << subch);
-	return 0;
-}
-
-int subch_demux_deactivate(struct subch_demux *dmx, int subch)
-{
-	if (subch >= NR_SUBCH)
-		return -EINVAL;
-
-	dmx->chan_activ &= ~(1 << subch);
-	return 0;
-}
-
-/* MULTIPLEXER */
-
-static int alloc_add_idle_frame(struct subch_mux *mx, int sch_nr)
-{
-	/* allocate and initialize with idle pattern */
-	return subchan_mux_enqueue(mx, sch_nr, trau_idle_frame(),
-				   TRAU_FRAME_BITS);
-}
-
-/* return the requested number of bits from the specified subchannel */
-static int get_subch_bits(struct subch_mux *mx, int subch,
-			  uint8_t *bits, int num_requested)
-{
-	struct mux_subch *sch = &mx->subch[subch];
-	int num_bits = 0;
-
-	while (num_bits < num_requested) {
-		struct subch_txq_entry *txe;
-		int num_bits_left;
-		int num_bits_thistime;
-
-		/* make sure we have a valid entry at top of tx queue.
-		 * if not, add an idle frame */
-		if (llist_empty(&sch->tx_queue))
-			alloc_add_idle_frame(mx, subch);
-	
-		if (llist_empty(&sch->tx_queue))
-			return -EIO;
-
-		txe = llist_entry(sch->tx_queue.next, struct subch_txq_entry, list);
-		num_bits_left = txe->bit_len - txe->next_bit;
-
-		if (num_bits_left < num_requested)
-			num_bits_thistime = num_bits_left;
-		else
-			num_bits_thistime = num_requested;
-
-		/* pull the bits from the txe */
-		memcpy(bits + num_bits, txe->bits + txe->next_bit, num_bits_thistime);
-		txe->next_bit += num_bits_thistime;
-
-		/* free the tx_queue entry if it is fully consumed */
-		if (txe->next_bit >= txe->bit_len) {
-			llist_del(&txe->list);
-			talloc_free(txe);
-		}
-
-		/* increment global number of bits dequeued */
-		num_bits += num_bits_thistime;
-	}
-
-	return num_requested;
-}
-
-/* compact an array of 8 single-bit bytes into one byte of 8 bits */
-static uint8_t compact_bits(const uint8_t *bits)
-{
-	uint8_t ret = 0;
-	int i;
-
-	for (i = 0; i < 8; i++)
-		ret |= (bits[i] ? 1 : 0) << i;
-
-	return ret;
-}
-
-/* obtain a single output byte from the subchannel muxer */
-static int mux_output_byte(struct subch_mux *mx, uint8_t *byte)
-{
-	uint8_t bits[8];
-	int rc;
-
-	/* combine two bits of every subchan */
-	rc = get_subch_bits(mx, 0, &bits[0], 2);
-	rc = get_subch_bits(mx, 1, &bits[2], 2);
-	rc = get_subch_bits(mx, 2, &bits[4], 2);
-	rc = get_subch_bits(mx, 3, &bits[6], 2);
-
-	*byte = compact_bits(bits);
-
-	return rc;
-}
-
-/* Request the output of some muxed bytes from the subchan muxer */
-int subchan_mux_out(struct subch_mux *mx, uint8_t *data, int len)
-{
-	int i;
-
-	for (i = 0; i < len; i++) {
-		int rc;
-		rc = mux_output_byte(mx, &data[i]);
-		if (rc < 0)
-			break;
-	}
-	return i;
-}
-
-static int llist_len(struct llist_head *head)
-{
-	struct llist_head *entry;
-	int i = 0;
-
-	llist_for_each(entry, head)
-		i++;
-
-	return i;
-}
-
-/* evict the 'num_evict' number of oldest entries in the queue */
-static void tx_queue_evict(struct mux_subch *sch, int num_evict)
-{
-	struct subch_txq_entry *tqe;
-	int i;
-
-	for (i = 0; i < num_evict; i++) {
-		if (llist_empty(&sch->tx_queue))
-			return;
-
-		tqe = llist_entry(sch->tx_queue.next, struct subch_txq_entry, list);
-		llist_del(&tqe->list);
-		talloc_free(tqe);
-	}
-}
-
-/* enqueue some data into the tx_queue of a given subchannel */
-int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const uint8_t *data,
-			int len)
-{
-	struct mux_subch *sch = &mx->subch[s_nr];
-	int list_len = llist_len(&sch->tx_queue);
-	struct subch_txq_entry *tqe = talloc_zero_size(tall_tqe_ctx,
-							sizeof(*tqe) + len);
-	if (!tqe)
-		return -ENOMEM;
-
-	tqe->bit_len = len;
-	memcpy(tqe->bits, data, len);
-
-	if (list_len > 2)
-		tx_queue_evict(sch, list_len-2);
-
-	llist_add_tail(&tqe->list, &sch->tx_queue);
-
-	return 0;
-}
-
-/* initialize one subchannel muxer instance */
-int subchan_mux_init(struct subch_mux *mx)
-{
-	int i;
-
-	memset(mx, 0, sizeof(*mx));
-	for (i = 0; i < NR_SUBCH; i++) {
-		struct mux_subch *sch = &mx->subch[i];
-		INIT_LLIST_HEAD(&sch->tx_queue);
-	}
-
-	return 0;
-}
diff --git a/openbsc/src/libtrau/trau_frame.c b/openbsc/src/libtrau/trau_frame.c
deleted file mode 100644
index 8fbaf86..0000000
--- a/openbsc/src/libtrau/trau_frame.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* TRAU frame handling according to GSM TS 08.60 */
-
-/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include <openbsc/trau_frame.h>
-#include <openbsc/subchan_demux.h>
-#include <openbsc/debug.h>
-
-static uint32_t get_bits(const uint8_t *bitbuf, int offset, int num)
-{
-	int i;
-	uint32_t ret = 0;
-
-	for (i = offset; i < offset + num; i++) {
-		ret = ret << 1;
-		if (bitbuf[i])
-			ret |= 1;
-	}
-	return ret;
-}
-
-/* Decode according to 3.1.1 */
-static void decode_fr(struct decoded_trau_frame *fr, const uint8_t *trau_bits)
-{
-	int i;
-	int d_idx = 0;
-
-	/* C1 .. C15 */
-	memcpy(fr->c_bits+0, trau_bits+17, 15);
-	/* C16 .. C21 */
-	memcpy(fr->c_bits+15, trau_bits+310, 6);
-	/* T1 .. T4 */
-	memcpy(fr->t_bits+0, trau_bits+316, 4);
-	/* D1 .. D255 */
-	for (i = 32; i < 304; i+= 16) {
-		memcpy(fr->d_bits + d_idx, trau_bits+i+1, 15);
-		d_idx += 15;
-	}
-	/* D256 .. D260 */
-	memcpy(fr->d_bits + d_idx, trau_bits + 305, 5);
-}
-
-/* Decode according to 3.1.2 */
-static void decode_amr(struct decoded_trau_frame *fr, const uint8_t *trau_bits)
-{
-	int i;
-	int d_idx = 0;
-
-	/* C1 .. C15 */
-	memcpy(fr->c_bits+0, trau_bits+17, 15);
-	/* C16 .. C25 */
-	memcpy(fr->c_bits+15, trau_bits+33, 10);
-	/* T1 .. T4 */
-	memcpy(fr->t_bits+0, trau_bits+316, 4);
-	/* D1 .. D5 */
-	memcpy(fr->d_bits, trau_bits+43, 5);
-	/* D6 .. D245 */
-	for (i = 48; i < 304; i += 16) {
-		memcpy(fr->d_bits + d_idx, trau_bits+i+1, 15);
-		d_idx += 15;
-	}
-	/* D246 .. D256 */
-	memcpy(fr->d_bits + d_idx, trau_bits + 305, 11);
-}
-
-int decode_trau_frame(struct decoded_trau_frame *fr, const uint8_t *trau_bits)
-{
-	uint8_t cbits5 = get_bits(trau_bits, 17, 5);
-
-	switch (cbits5) {
-	case TRAU_FT_FR_UP:
-	case TRAU_FT_FR_DOWN:
-	case TRAU_FT_IDLE_UP:
-	case TRAU_FT_IDLE_DOWN:
-	case TRAU_FT_EFR:
-		decode_fr(fr, trau_bits);
-		break;
-	case TRAU_FT_AMR:
-		decode_amr(fr, trau_bits);
-		break;
-	case TRAU_FT_OM_UP:
-	case TRAU_FT_OM_DOWN:
-	case TRAU_FT_DATA_UP:
-	case TRAU_FT_DATA_DOWN:
-	case TRAU_FT_D145_SYNC:
-	case TRAU_FT_EDATA:
-		LOGP(DMUX, LOGL_NOTICE, "can't decode unimplemented TRAU "
-			"Frame Type 0x%02x\n", cbits5);
-		return -1;
-		break;
-	default:
-		LOGP(DMUX, LOGL_NOTICE, "can't decode unknown TRAU "
-			"Frame Type 0x%02x\n", cbits5);
-		return -1;
-		break;
-	}
-
-	return 0;
-}
-
-const uint8_t ft_fr_down_bits[] = { 1, 1, 1, 0, 0 };
-const uint8_t ft_idle_down_bits[] = { 0, 1, 1, 1, 0 };
-
-/* modify an uplink TRAU frame so we can send it downlink */
-int trau_frame_up2down(struct decoded_trau_frame *fr)
-{
-	uint8_t cbits5 = get_bits(fr->c_bits, 0, 5);
-
-	switch (cbits5) {
-	case TRAU_FT_FR_UP:
-		memcpy(fr->c_bits, ft_fr_down_bits, 5);
-		/* clear time alignment */
-		memset(fr->c_bits+5, 0, 6);
-		/* FIXME: SP / BFI in case of DTx */
-		/* C12 .. C21 are spare and coded as '1' */
-		memset(fr->c_bits+11, 0x01, 10);
-		break;
-	case TRAU_FT_EFR:
-		/* clear time alignment */
-		memset(fr->c_bits+5, 0, 6);
-		/* set UFE appropriately */
-		fr->c_bits[11] = 1; /* C12 (UFE), good frame (TODO) */
-		/* C13 .. C15 are spare and coded as '1' */
-		memset(fr->c_bits+12, 0x01, 3);
-		/* SP / BFI in case of DTx */
-		fr->c_bits[15] = 1; /* C16 (SP), no DTX (TODO) */
-		/* C17 .. C21 are spare and coded as '1' */
-		memset(fr->c_bits+16, 0x01, 5);
-		break;
-	case TRAU_FT_IDLE_UP:
-		memcpy(fr->c_bits, ft_idle_down_bits, 5);
-		/* clear time alignment */
-		memset(fr->c_bits+5, 0, 6);
-		/* FIXME: SP / BFI in case of DTx */
-		/* C12 .. C21 are spare and coded as '1' */
-		memset(fr->c_bits+11, 0x01, 10);
-		break;
-	case TRAU_FT_FR_DOWN:
-	case TRAU_FT_IDLE_DOWN:
-	case TRAU_FT_OM_DOWN:
-	case TRAU_FT_DATA_DOWN:
-		/* we cannot convert a downlink to a downlink frame */
-		return -EINVAL;
-		break;
-	case TRAU_FT_AMR:
-	case TRAU_FT_OM_UP:
-	case TRAU_FT_DATA_UP:
-	case TRAU_FT_D145_SYNC:
-	case TRAU_FT_EDATA:
-		LOGP(DMUX, LOGL_NOTICE, "unimplemented TRAU Frame Type "
-			"0x%02x\n", cbits5);
-		return -1;
-		break;
-	default:
-		LOGP(DMUX, LOGL_NOTICE, "unknown TRAU Frame Type "
-			"0x%02x\n", cbits5);
-		return -1;
-		break;
-	}
-
-	return 0;
-
-}
-
-static void encode_fr(uint8_t *trau_bits, const struct decoded_trau_frame *fr)
-{
-	int i;
-	int d_idx = 0;
-
-	trau_bits[16] = 1;
-	/* C1 .. C15 */
-	memcpy(trau_bits+17, fr->c_bits+0, 15);
-	/* D1 .. D255 */
-	for (i = 32; i < 304; i+= 16) {
-		trau_bits[i] = 1;
-		memcpy(trau_bits+i+1, fr->d_bits + d_idx, 15);
-		d_idx += 15;
-	}
-	/* D256 .. D260 */
-	trau_bits[304] = 1;
-	memcpy(trau_bits + 305, fr->d_bits + d_idx, 5);
-	/* C16 .. C21 */
-	memcpy(trau_bits+310, fr->c_bits+15, 6);
-
-	/* FIXME: handle timing adjustment */
-
-	/* T1 .. T4 */
-	memcpy(trau_bits+316, fr->t_bits+0, 4);
-}
-
-
-int encode_trau_frame(uint8_t *trau_bits, const struct decoded_trau_frame *fr)
-{
-	uint8_t cbits5 = get_bits(fr->c_bits, 0, 5);
-	
-	/* 16 bits of sync header */
-	memset(trau_bits, 0, 16);
-
-	switch (cbits5) {
-	case TRAU_FT_FR_UP:
-	case TRAU_FT_FR_DOWN:
-	case TRAU_FT_IDLE_UP:
-	case TRAU_FT_IDLE_DOWN:
-	case TRAU_FT_EFR:
-		encode_fr(trau_bits, fr);
-		break;
-	case TRAU_FT_AMR:
-	case TRAU_FT_OM_UP:
-	case TRAU_FT_OM_DOWN:
-	case TRAU_FT_DATA_UP:
-	case TRAU_FT_DATA_DOWN:
-	case TRAU_FT_D145_SYNC:
-	case TRAU_FT_EDATA:
-		LOGP(DMUX, LOGL_NOTICE, "unimplemented TRAU Frame Type "
-			"0x%02x\n", cbits5);
-		return -1;
-		break;
-	default:
-		LOGP(DMUX, LOGL_NOTICE, "unknown TRAU Frame Type "
-			"0x%02x\n", cbits5);
-		return -1;
-		break;
-	}
-
-	return 0;
-}
-
-static struct decoded_trau_frame fr_idle_frame = {
-	.c_bits = { 0, 1, 1, 1, 0 },	/* IDLE DOWNLINK 3.5.5 */
-	.t_bits = { 1, 1, 1, 1 },
-};
-static uint8_t encoded_idle_frame[TRAU_FRAME_BITS];
-static int dbits_initted = 0;
-
-uint8_t *trau_idle_frame(void)
-{
-	/* only initialize during the first call */
-	if (!dbits_initted) {
-		/* set all D-bits to 1 */
-		memset(&fr_idle_frame.d_bits, 0x01, 260);
-
-		memset(&fr_idle_frame.c_bits, 0x01, 25); /* spare are set to 1 */
-		/* set Downlink Idle Speech Frame pattern */
-		fr_idle_frame.c_bits[0] = 0; /* C1 */
-		fr_idle_frame.c_bits[1] = 1; /* C2 */
-		fr_idle_frame.c_bits[2] = 1; /* C3 */
-		fr_idle_frame.c_bits[3] = 1; /* C4 */
-		fr_idle_frame.c_bits[4] = 0; /* C5 */
-		/* set no Time Alignment pattern */
-		fr_idle_frame.c_bits[5] = 0; /* C6 */
-		fr_idle_frame.c_bits[6] = 0; /* C7 */
-		fr_idle_frame.c_bits[7] = 0; /* C8 */
-		fr_idle_frame.c_bits[8] = 0; /* C9 */
-		fr_idle_frame.c_bits[9] = 0; /* C10 */
-		fr_idle_frame.c_bits[10] = 0; /* C11 */
-		/* already set to 1, but maybe we need to modify it in the future */
-		fr_idle_frame.c_bits[11] = 1; /* C12 (UFE), good frame */
-		fr_idle_frame.c_bits[15] = 1; /* C16 (SP), no DTX */
-
-		encode_fr(encoded_idle_frame, &fr_idle_frame);
-		dbits_initted = 1; /* set it to 1 to not call it again */
-	}
-	return encoded_idle_frame;
-}
diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c
index ab27879..6a6b7c5 100644
--- a/openbsc/src/libtrau/trau_mux.c
+++ b/openbsc/src/libtrau/trau_mux.c
@@ -23,10 +23,10 @@
 #include <string.h>
 
 #include <openbsc/gsm_data.h>
-#include <openbsc/trau_frame.h>
+#include <osmocom/abis/trau_frame.h>
 #include <openbsc/trau_mux.h>
-#include <openbsc/subchan_demux.h>
-#include <openbsc/e1_input.h>
+#include <osmocom/abis/subchan_demux.h>
+#include <osmocom/abis/e1_input.h>
 #include <openbsc/debug.h>
 #include <osmocom/core/talloc.h>
 
@@ -70,7 +70,7 @@
 
 	me = talloc(tall_map_ctx, struct map_entry);
 	if (!me) {
-		LOGP(DMIB, LOGL_FATAL, "Out of memory\n");
+		LOGP(DLMIB, LOGL_FATAL, "Out of memory\n");
 		return -ENOMEM;
 	}
 
@@ -186,7 +186,7 @@
 		if (!ue->callref)
 			return -EINVAL;
 		if (memcmp(tf.c_bits, c_bits_check, sizeof(c_bits_check)))
-			DEBUGPC(DMUX, "illegal trau (C1-C5) %s\n",
+			DEBUGPC(DLMUX, "illegal trau (C1-C5) %s\n",
 				osmo_hexdump(tf.c_bits, sizeof(c_bits_check)));
 		msg = msgb_alloc(sizeof(struct gsm_data_frame) + 33,
 				 "GSM-DATA");
@@ -232,6 +232,20 @@
 				   TRAU_FRAME_BITS);
 }
 
+/* callback when a TRAU frame was received */
+int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len,
+	     void *_priv)
+{
+	struct e1inp_ts *e1i_ts = _priv;
+	struct gsm_e1_subslot src_ss;
+
+	src_ss.e1_nr = e1i_ts->line->num;
+	src_ss.e1_ts = e1i_ts->num;
+	src_ss.e1_ts_ss = ch;
+
+	return trau_mux_input(&src_ss, data, len);
+}
+
 /* add receiver instance for lchan and callref */
 int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref)
 {
@@ -301,7 +315,7 @@
 		}
 		break;
 	default:
-		DEBUGPC(DMUX, "unsupported message type %d\n",
+		DEBUGPC(DLMUX, "unsupported message type %d\n",
 			frame->msg_type);
 		return -EINVAL;
 	}