aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libtrau
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@gnumonks.org>2011-08-17 22:44:07 +0200
committerHarald Welte <laforge@gnumonks.org>2011-08-19 22:38:35 +0200
commited5cacb240b846c106f0fc6a3ab8e8721f4c70a5 (patch)
treeba6bffbf0c95ecc0c50b5335bed77f3a2b29120f /openbsc/src/libtrau
parent7abecfcfc9ef94c1367cd88ac858b79d20f75db0 (diff)
src: port openBSC over libosmo-abis0.9.15
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.
Diffstat (limited to 'openbsc/src/libtrau')
-rw-r--r--openbsc/src/libtrau/Makefile.am6
-rw-r--r--openbsc/src/libtrau/rtp_proxy.c46
-rw-r--r--openbsc/src/libtrau/subchan_demux.c321
-rw-r--r--openbsc/src/libtrau/trau_frame.c286
-rw-r--r--openbsc/src/libtrau/trau_mux.c26
5 files changed, 46 insertions, 639 deletions
diff --git a/openbsc/src/libtrau/Makefile.am b/openbsc/src/libtrau/Makefile.am
index 6b70a9acc..802c455b1 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 4c5f12eb5..2aa3a1e71 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -111,25 +111,25 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
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 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
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 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
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 @@ static int rtp_decode(struct msgb *msg, uint32_t callref, struct msgb **data)
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 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
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 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
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 @@ static int rtcp_mangle(struct msgb *msg, struct rtp_socket *rs)
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 @@ static int rtp_socket_write(struct rtp_socket *rs, struct rtp_sub_socket *rss)
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 @@ struct rtp_socket *rtp_socket_create(void)
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 @@ struct rtp_socket *rtp_socket_create(void)
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 @@ out_rtp_socket:
close(rs->rtp.bfd.fd);
out_free:
talloc_free(rs);
- DEBUGPC(DMUX, "failed\n");
+ DEBUGPC(DLMUX, "failed\n");
return NULL;
}
@@ -604,7 +604,7 @@ int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip)
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 @@ int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip)
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 @@ int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port)
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 @@ int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port)
/* 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_proxy(struct rtp_socket *this, struct rtp_socket *other)
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 @@ static void free_tx_queue(struct rtp_sub_socket *rss)
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 740d2caaf..000000000
--- 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 8fbaf8606..000000000
--- 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 ab2787956..6a6b7c58d 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 @@ int trau_mux_map(const struct gsm_e1_subslot *src,
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 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
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 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
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 @@ int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame)
}
break;
default:
- DEBUGPC(DMUX, "unsupported message type %d\n",
+ DEBUGPC(DLMUX, "unsupported message type %d\n",
frame->msg_type);
return -EINVAL;
}