aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abis_rsl.c13
-rw-r--r--src/e1_config.c1
-rw-r--r--src/e1_input.c1
-rw-r--r--src/gsm_04_08.c2
-rw-r--r--src/trau_mux.c103
5 files changed, 106 insertions, 14 deletions
diff --git a/src/abis_rsl.c b/src/abis_rsl.c
index 753a66609..d9a39b8b4 100644
--- a/src/abis_rsl.c
+++ b/src/abis_rsl.c
@@ -476,10 +476,21 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
/* FIXME: what to do with data calls ? */
cm.dtx_dtu = 0x00;
switch (lchan->type) {
+ /* todo more modes */
case GSM_LCHAN_TCH_F:
cm.spd_ind = RSL_CMOD_SPD_SPEECH;
cm.chan_rt = RSL_CMOD_CRT_TCH_Bm;
- cm.chan_rate = RSL_CMOD_SP_GSM2;
+ switch(lchan->tch_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ cm.chan_rate = RSL_CMOD_SP_GSM1;
+ break;
+ case GSM48_CMODE_SPEECH_EFR:
+ cm.chan_rate = RSL_CMOD_SP_GSM2;
+ break;
+ default:
+ DEBUGP(DRSL, "Unimplemented channel modification\n");
+ return -1;
+ }
break;
default:
DEBUGP(DRSL, "Unimplemented channel modification\n");
diff --git a/src/e1_config.c b/src/e1_config.c
index ffc7e46cc..fc23b55e1 100644
--- a/src/e1_config.c
+++ b/src/e1_config.c
@@ -5,6 +5,7 @@
#include <openbsc/gsm_data.h>
#include <openbsc/e1_input.h>
+#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
#include <openbsc/misdn.h>
diff --git a/src/e1_input.c b/src/e1_input.c
index 7fbf1797a..c3c7c7597 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -49,6 +49,7 @@
#include <openbsc/abis_rsl.h>
#include <openbsc/linuxlist.h>
#include <openbsc/subchan_demux.h>
+#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
#define NUM_E1_TS 32
diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c
index 849ef4888..07e7a4683 100644
--- a/src/gsm_04_08.c
+++ b/src/gsm_04_08.c
@@ -42,6 +42,7 @@
#include <openbsc/chan_alloc.h>
#include <openbsc/paging.h>
#include <openbsc/signal.h>
+#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
#define GSM48_ALLOC_SIZE 1024
@@ -635,6 +636,7 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
DEBUGP(DRR, "-> CHANNEL MODE MODIFY mode=0x%02x\n", mode);
+ lchan->tch_mode = mode;
msg->lchan = lchan;
gh->proto_discr = GSM48_PDISC_RR;
gh->msg_type = GSM48_MT_RR_CHAN_MODE_MODIF;
diff --git a/src/trau_mux.c b/src/trau_mux.c
index 2616785c0..96f858992 100644
--- a/src/trau_mux.c
+++ b/src/trau_mux.c
@@ -36,7 +36,15 @@ struct map_entry {
struct gsm_e1_subslot src, dst;
};
+struct upqueue_entry {
+ struct llist_head list;
+ struct gsm_network *net;
+ struct gsm_e1_subslot src;
+ u_int32_t callref;
+};
+
static LLIST_HEAD(ss_map);
+static LLIST_HEAD(ss_upqueue);
/* map one particular subslot to another subslot */
int trau_mux_map(const struct gsm_e1_subslot *src,
@@ -52,8 +60,8 @@ int trau_mux_map(const struct gsm_e1_subslot *src,
dst->e1_nr, dst->e1_ts, dst->e1_ts_ss);
/* make sure to get rid of any stale old mappings */
- trau_mux_unmap(src);
- trau_mux_unmap(dst);
+ trau_mux_unmap(src, 0);
+ trau_mux_unmap(dst, 0);
memcpy(&me->src, src, sizeof(me->src));
memcpy(&me->dst, dst, sizeof(me->dst));
@@ -75,14 +83,26 @@ int trau_mux_map_lchan(const struct gsm_lchan *src,
/* unmap one particular subslot from another subslot */
-int trau_mux_unmap(const struct gsm_e1_subslot *ss)
+int trau_mux_unmap(const struct gsm_e1_subslot *ss, u_int32_t callref)
{
struct map_entry *me, *me2;
-
- llist_for_each_entry_safe(me, me2, &ss_map, list) {
- if (!memcmp(&me->src, ss, sizeof(*ss)) ||
- !memcmp(&me->dst, ss, sizeof(*ss))) {
- llist_del(&me->list);
+ struct upqueue_entry *ue, *ue2;
+
+ if (ss)
+ llist_for_each_entry_safe(me, me2, &ss_map, list) {
+ if (!memcmp(&me->src, ss, sizeof(*ss)) ||
+ !memcmp(&me->dst, ss, sizeof(*ss))) {
+ llist_del(&me->list);
+ return 0;
+ }
+ }
+ llist_for_each_entry_safe(ue, ue2, &ss_upqueue, list) {
+ if (ue->callref == callref) {
+ llist_del(&ue->list);
+ return 0;
+ }
+ if (ss && !memcmp(&ue->src, ss, sizeof(*ss))) {
+ llist_del(&ue->list);
return 0;
}
}
@@ -104,6 +124,19 @@ lookup_trau_mux_map(const struct gsm_e1_subslot *src)
return NULL;
}
+/* look-up an enty in the TRAU upqueue */
+struct upqueue_entry *
+lookup_trau_upqueue(const struct gsm_e1_subslot *src)
+{
+ struct upqueue_entry *ue;
+
+ llist_for_each_entry(ue, &ss_upqueue, list) {
+ if (!memcmp(&ue->src, src, sizeof(*src)))
+ return ue;
+ }
+ return NULL;
+}
+
/* we get called by subchan_demux */
int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
const u_int8_t *trau_bits, int num_bits)
@@ -114,6 +147,11 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
struct subch_mux *mx;
int rc;
+ /* decode TRAU, change it to downlink, re-encode */
+ rc = decode_trau_frame(&tf, trau_bits);
+ if (rc)
+ return rc;
+
if (!dst_e1_ss)
return -EINVAL;
@@ -121,11 +159,6 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
if (!mx)
return -EINVAL;
- /* decode TRAU, change it to downlink, re-encode */
- rc = decode_trau_frame(&tf, trau_bits);
- if (rc)
- return rc;
-
trau_frame_up2down(&tf);
encode_trau_frame(trau_bits_out, &tf);
@@ -133,3 +166,47 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
TRAU_FRAME_BITS);
}
+
+/* add receiver instance for lchan and callref */
+int trau_recv_lchan(struct gsm_lchan *lchan, u_int32_t callref)
+{
+ struct gsm_e1_subslot *src_ss;
+ struct upqueue_entry *ue = malloc(sizeof(*ue));
+
+ if (!ue)
+ return -ENOMEM;
+
+ src_ss = &lchan->ts->e1_link;
+
+ DEBUGP(DCC, "Setting up TRAU receiver (e1=%u,ts=%u,ss=%u) "
+ "and (callref 0x%x)\n",
+ src_ss->e1_nr, src_ss->e1_ts, src_ss->e1_ts_ss,
+ callref);
+
+ /* make sure to get rid of any stale old mappings */
+ trau_mux_unmap(src_ss, callref);
+
+ memcpy(&ue->src, src_ss, sizeof(ue->src));
+ ue->net = lchan->ts->trx->bts->network;
+ ue->callref = callref;
+ llist_add(&ue->list, &ss_upqueue);
+
+ return 0;
+}
+
+int trau_send_lchan(struct gsm_lchan *lchan, struct decoded_trau_frame *tf)
+{
+ u_int8_t trau_bits_out[TRAU_FRAME_BITS];
+ struct gsm_e1_subslot *dst_e1_ss = &lchan->ts->e1_link;
+ struct subch_mux *mx;
+
+ mx = e1inp_get_mux(dst_e1_ss->e1_nr, dst_e1_ss->e1_ts);
+ if (!mx)
+ return -EINVAL;
+
+ encode_trau_frame(trau_bits_out, tf);
+
+ /* and send it to the muxer */
+ return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
+ TRAU_FRAME_BITS);
+}