diff options
Diffstat (limited to 'openbsc/src/libtrau')
-rw-r--r-- | openbsc/src/libtrau/Makefile.am | 6 | ||||
-rw-r--r-- | openbsc/src/libtrau/rtp_proxy.c | 46 | ||||
-rw-r--r-- | openbsc/src/libtrau/subchan_demux.c | 321 | ||||
-rw-r--r-- | openbsc/src/libtrau/trau_frame.c | 286 | ||||
-rw-r--r-- | openbsc/src/libtrau/trau_mux.c | 26 |
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; } |