summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2020-03-07 20:30:01 +0100
committerHarald Welte <laforge@osmocom.org>2020-03-09 19:35:49 +0100
commita42563b684f98e82f29c764e97b5f5467eb3f213 (patch)
tree622054c36457d9dc74886a1a95cf7426120ed550
parent61a06f4d36cf40c97bb6c08daccc84fe2beefe94 (diff)
virt_phy: implement GSMTAP_CHANNEL_VOICE
GSMTAP_CHANNEL_VOICE is the mechanism by which GSMTAP can [finally!] be used to transport circuit-switched voice codec payload, and not just signalling. Original patch by Neels Hofmeyr, heavily extended by Harald Welte. Change-Id: Id72cf23b7c6587efae4cdaa7b50ab4d85b8c8d22
-rw-r--r--src/host/virt_phy/configure.ac2
-rw-r--r--src/host/virt_phy/src/gsmtapl1_if.c59
-rw-r--r--src/host/virt_phy/src/virt_prim_traffic.c16
3 files changed, 63 insertions, 14 deletions
diff --git a/src/host/virt_phy/configure.ac b/src/host/virt_phy/configure.ac
index a2c2bf65..fbff2c11 100644
--- a/src/host/virt_phy/configure.ac
+++ b/src/host/virt_phy/configure.ac
@@ -12,6 +12,8 @@ AC_PROG_CC
AC_PROG_INSTALL
dnl checks for libraries
+dnl TODO: insert libosmocore version with GSMTAP_CHANNEL_VOICE: PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
+dnl (at time of writing not released yet)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm)
diff --git a/src/host/virt_phy/src/gsmtapl1_if.c b/src/host/virt_phy/src/gsmtapl1_if.c
index 30f88ff4..3fa69c4f 100644
--- a/src/host/virt_phy/src/gsmtapl1_if.c
+++ b/src/host/virt_phy/src/gsmtapl1_if.c
@@ -26,6 +26,7 @@
#include <osmocom/gsm/rsl.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/core/msgb.h>
#include <stddef.h>
#include <stdlib.h>
@@ -48,6 +49,29 @@ static char *pseudo_lchan_name(uint16_t arfcn, uint8_t ts, uint8_t ss, uint8_t s
return lname;
}
+/* Return gsmtap_um_voice_type or -1 on error */
+static int get_um_voice_type(enum gsm48_chan_mode tch_mode, uint8_t rsl_chantype)
+{
+ switch (tch_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ switch (rsl_chantype) {
+ case RSL_CHAN_Bm_ACCHs:
+ return GSMTAP_UM_VOICE_FR;
+ case RSL_CHAN_Lm_ACCHs:
+ return GSMTAP_UM_VOICE_HR;
+ default:
+ return -1;
+ }
+ break;
+ case GSM48_CMODE_SPEECH_EFR:
+ return GSMTAP_UM_VOICE_EFR;
+ case GSM48_CMODE_SPEECH_AMR:
+ return GSMTAP_UM_VOICE_AMR;
+ default:
+ return -1;
+ }
+}
+
/**
* Replace l11 header of given msgb by a gsmtap header and send it over the virt um.
*/
@@ -74,12 +98,25 @@ void gsmtapl1_tx_to_virt_um_inst(struct l1_model_ms *ms, uint32_t fn, uint8_t tn
rsl_chantype = RSL_CHAN_OSMO_PDCH;
timeslot = tn;
subslot = 0;
- gsmtap_chan = chantype_rsl2gsmtap(rsl_chantype, 0);
+ gsmtap_chan = chantype_rsl2gsmtap2(rsl_chantype, 0, false);
+ break;
+ case L1CTL_TRAFFIC_REQ:
+ ul = (struct l1ctl_info_ul *)l1h->data;
+ rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
+ gsmtap_chan = chantype_rsl2gsmtap2(rsl_chantype, 0, true);
+ /* the first byte indicates the type of voice codec (gsmtap_um_voice_type);
+ * let's first strip any data in front of the l2 header, then push this extra
+ * byte to the front and finally adjust the l2h pointer */
+ msgb_pull_to_l2(msg);
+ msgb_push_u8(msg, get_um_voice_type(ms->state.tch_mode, rsl_chantype));
+ msg->l2h = msg->data;
+ data = msgb_l2(msg);
+ data_len = msgb_l2len(msg);
break;
default:
ul = (struct l1ctl_info_ul *)l1h->data;
rsl_dec_chan_nr(ul->chan_nr, &rsl_chantype, &subslot, &timeslot);
- gsmtap_chan = chantype_rsl2gsmtap(rsl_chantype, ul->link_id);
+ gsmtap_chan = chantype_rsl2gsmtap2(rsl_chantype, ul->link_id, false);
break;
}
@@ -219,13 +256,7 @@ static void l1ctl_from_virt_um(struct l1ctl_sock_client *lsc, struct msgb *msg,
switch (gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH & 0xff) {
case GSMTAP_CHANNEL_TCH_H:
case GSMTAP_CHANNEL_TCH_F:
-#if 0
- /* TODO: handle voice */
- if (!facch && !tch_acch) {
- l1ctl_tx_traffic_ind(msg, arfcn, link_id, chan_nr, fn,
- snr, signal_dbm, 0, 0);
- }
-#endif
+ /* This is TCH signalling, for voice frames see GSMTAP_CHANNEL_VOICE */
case GSMTAP_CHANNEL_SDCCH4:
case GSMTAP_CHANNEL_SDCCH8:
/* only forward messages on dedicated channels to l2, if
@@ -235,6 +266,16 @@ static void l1ctl_from_virt_um(struct l1ctl_sock_client *lsc, struct msgb *msg,
l1ctl_tx_data_ind(ms, msg, arfcn, link_id, chan_nr, fn, snr_db, signal_dbm, 0, 0);
}
break;
+ case GSMTAP_CHANNEL_VOICE_F:
+ case GSMTAP_CHANNEL_VOICE_H:
+ /* only forward messages on dedicated channels to l2, if
+ * the timeslot and subslot is fitting */
+ if (ms->state.dedicated.tn == timeslot
+ && ms->state.dedicated.subslot == subslot) {
+ l1ctl_tx_traffic_ind(ms, msg, arfcn, link_id, chan_nr, fn,
+ snr_db, signal_dbm, 0, 0);
+ }
+ break;
case GSMTAP_CHANNEL_CBCH51:
/* only pass CBCH data if the user application actually indicated that a CBCH
* is present */
diff --git a/src/host/virt_phy/src/virt_prim_traffic.c b/src/host/virt_phy/src/virt_prim_traffic.c
index 5f6b273b..3d2b2b15 100644
--- a/src/host/virt_phy/src/virt_prim_traffic.c
+++ b/src/host/virt_phy/src/virt_prim_traffic.c
@@ -84,7 +84,8 @@ void l1ctl_tx_traffic_ind(struct l1_model_ms *ms, struct msgb *msg, uint16_t arf
struct msgb *l1ctl_msg = NULL;
struct l1ctl_traffic_ind * l1ti;
struct l1ctl_info_dl * l1dl;
- uint8_t *frame, frame_len;
+ uint8_t *frame;
+ int frame_len;
uint8_t rsl_chan_type, subchan, timeslot;
l1ctl_msg = l1ctl_msgb_alloc(L1CTL_TRAFFIC_IND);
l1dl = (struct l1ctl_info_dl *) msgb_put(l1ctl_msg, sizeof(*l1dl));
@@ -101,11 +102,16 @@ void l1ctl_tx_traffic_ind(struct l1_model_ms *ms, struct msgb *msg, uint16_t arf
l1dl->num_biterr = 0; /* no biterrors */
l1dl->fire_crc = 0;
- /* TODO: traffic decoding and decryption */
-
- frame_len = msgb_length(msg);
+ /* The first byte indicates the type of voice frame (enum gsmtap_um_voice_type),
+ * which we simply ignore here and pass on the frame without that byte.
+ * TODO: Check for consistency with ms->state.tch_mode ? */
+ frame_len = msgb_length(msg) - 1;
+ if (frame_len < 0) {
+ msgb_free(l1ctl_msg);
+ return;
+ }
frame = (uint8_t *) msgb_put(l1ctl_msg, frame_len);
- memcpy(frame, msgb_data(msg), frame_len);
+ memcpy(frame, msgb_data(msg)+1, frame_len);
DEBUGPMS(DL1P, ms, "Tx L1CTL_TRAFFIC_IND (chan_nr=0x%02x, link_id=0x%02x)\n", chan_nr, link_id);
l1ctl_sap_tx_to_l23_inst(ms, l1ctl_msg);