Merge branch 'jolly/mncc'

Merge the interface changes to the MNCC protocol
diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h
index ffc247b..ffac7fd 100644
--- a/openbsc/include/openbsc/mncc.h
+++ b/openbsc/include/openbsc/mncc.h
@@ -95,7 +95,9 @@
 
 #define GSM_TCHF_FRAME		0x0300
 #define GSM_TCHF_FRAME_EFR	0x0301
-#define GSM_TCHF_BAD_FRAME	0x03ff
+#define GSM_TCHH_FRAME		0x0302
+#define GSM_TCH_FRAME_AMR	0x0303
+#define GSM_BAD_FRAME		0x03ff
 
 #define MNCC_SOCKET_HELLO	0x0400
 
@@ -161,7 +163,7 @@
 	unsigned char	data[0];
 };
 
-#define MNCC_SOCK_VERSION	2
+#define MNCC_SOCK_VERSION	4
 struct gsm_mncc_hello {
 	uint32_t	msg_type;
 	uint32_t	version;
@@ -189,4 +191,12 @@
 
 int mncc_sock_init(struct gsm_network *gsmnet);
 
+#define mncc_is_data_frame(msg_type) \
+	(msg_type == GSM_TCHF_FRAME \
+		|| msg_type == GSM_TCHF_FRAME_EFR \
+		|| msg_type == GSM_TCHH_FRAME \
+		|| msg_type == GSM_TCH_FRAME_AMR \
+		|| msg_type == GSM_BAD_FRAME)
+
+
 #endif
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index cd2a0b5..df93433 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -2952,6 +2952,7 @@
 		return tch_recv_mncc(net, data->callref, 1);
 	case GSM_TCHF_FRAME:
 	case GSM_TCHF_FRAME_EFR:
+	case GSM_TCHH_FRAME:
 		/* Find callref */
 		trans = trans_find_by_callref(net, data->callref);
 		if (!trans) {
@@ -2963,11 +2964,12 @@
 			LOGP(DMNCC, LOGL_NOTICE, "TCH frame for trans without conn\n");
 			return 0;
 		}
-		if (trans->conn->lchan->type != GSM_LCHAN_TCH_F) {
+		if (trans->conn->lchan->type != GSM_LCHAN_TCH_F
+		 && trans->conn->lchan->type != GSM_LCHAN_TCH_H) {
 			/* This should be LOGL_ERROR or NOTICE, but
 			 * unfortuantely it happens for a couple of frames at
 			 * the beginning of every RTP connection */
-			LOGP(DMNCC, LOGL_DEBUG, "TCH frame for lchan != TCH_F\n");
+			LOGP(DMNCC, LOGL_DEBUG, "TCH frame for lchan != TCH_F/TCH_H\n");
 			return 0;
 		}
 		bts = trans->conn->lchan->ts->trx->bts;
diff --git a/openbsc/src/libmsc/mncc.c b/openbsc/src/libmsc/mncc.c
index b484772..73db5f0 100644
--- a/openbsc/src/libmsc/mncc.c
+++ b/openbsc/src/libmsc/mncc.c
@@ -84,7 +84,11 @@
 	{"MNCC_FRAME_DROP",	0x0202},
 	{"MNCC_LCHAN_MODIFY",	0x0203},
 
-	{"GSM_TCH_FRAME",	0x0300},
+	{"GSM_TCHF_FRAME",	0x0300},
+	{"GSM_TCHF_FRAME_EFR",	0x0301},
+	{"GSM_TCHH_FRAME",	0x0302},
+	{"GSM_TCH_FRAME_AMR",	0x0303},
+	{"GSM_BAD_FRAME",	0x03ff},
 
 	{NULL, 0} };
 
diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c
index be35454..a5a463b 100644
--- a/openbsc/src/libmsc/mncc_builtin.c
+++ b/openbsc/src/libmsc/mncc_builtin.c
@@ -273,8 +273,8 @@
 	return 0;
 }
 
-/* receiving a TCH/F frame from the BSC code */
-static int mncc_rcv_tchf(struct gsm_call *call, int msg_type,
+/* receiving a (speech) traffic frame from the BSC code */
+static int mncc_rcv_data(struct gsm_call *call, int msg_type,
 			 struct gsm_data_frame *dfr)
 {
 	struct gsm_trans *remote_trans;
@@ -339,16 +339,14 @@
 		DEBUGP(DMNCC, "(call %x) Call created.\n", call->callref);
 	}
 
-	switch (msg_type) {
-	case GSM_TCHF_FRAME:
-	case GSM_TCHF_FRAME_EFR:
-		break;
-	default:
-		DEBUGP(DMNCC, "(call %x) Received message %s\n", call->callref,
-			get_mncc_name(msg_type));
-		break;
+	if (mncc_is_data_frame(msg_type)) {
+		rc = mncc_rcv_data(call, msg_type, arg);
+		goto out_free;
 	}
 
+	DEBUGP(DMNCC, "(call %x) Received message %s\n", call->callref,
+		get_mncc_name(msg_type));
+
 	switch(msg_type) {
 	case MNCC_SETUP_IND:
 		rc = mncc_setup_ind(call, msg_type, arg);
@@ -408,10 +406,6 @@
 			call->callref, data->cause.value);
 		rc = mncc_tx_to_cc(net, MNCC_RETRIEVE_REJ, data);
 		break;
-	case GSM_TCHF_FRAME:
-	case GSM_TCHF_FRAME_EFR:
-		rc = mncc_rcv_tchf(call, msg_type, arg);
-		break;
 	default:
 		LOGP(DMNCC, LOGL_NOTICE, "(call %x) Message unhandled\n", callref);
 		break;
diff --git a/openbsc/src/libmsc/mncc_sock.c b/openbsc/src/libmsc/mncc_sock.c
index cf4bca8..dd0a44f 100644
--- a/openbsc/src/libmsc/mncc_sock.c
+++ b/openbsc/src/libmsc/mncc_sock.c
@@ -54,8 +54,7 @@
 	if (net->mncc_state->conn_bfd.fd < 0) {
 		LOGP(DMNCC, LOGL_ERROR, "mncc_sock receives %s for external CC app "
 			"but socket is gone\n", get_mncc_name(msg_type));
-		if (msg_type != GSM_TCHF_FRAME &&
-		    msg_type != GSM_TCHF_FRAME_EFR) {
+		if (!mncc_is_data_frame(msg_type)) {
 			/* release the request */
 			struct gsm_mncc mncc_out;
 			memset(&mncc_out, 0, sizeof(mncc_out));
diff --git a/openbsc/src/libtrau/rtp_proxy.c b/openbsc/src/libtrau/rtp_proxy.c
index 94a5b2f..143bfa0 100644
--- a/openbsc/src/libtrau/rtp_proxy.c
+++ b/openbsc/src/libtrau/rtp_proxy.c
@@ -183,6 +183,15 @@
 			return -EINVAL;
 		}
 		break;
+	case RTP_PT_GSM_HALF:
+		msg_type = GSM_TCHH_FRAME;
+		if (payload_len != RTP_LEN_GSM_HALF) {
+			DEBUGPC(DLMUX, "received RTP half rate frame with "
+				"payload length != %d (len = %d)\n",
+				RTP_LEN_GSM_HALF, payload_len);
+			return -EINVAL;
+		}
+		break;
 	default:
 		DEBUGPC(DLMUX, "received RTP frame with unknown payload "
 			"type %d\n", rtph->payload_type);
@@ -250,6 +259,11 @@
 		payload_len = RTP_LEN_GSM_EFR;
 		duration = RTP_GSM_DURATION;
 		break;
+	case GSM_TCHH_FRAME:
+		payload_type = RTP_PT_GSM_HALF;
+		payload_len = RTP_LEN_GSM_HALF;
+		duration = RTP_GSM_DURATION;
+		break;
 	default:
 		DEBUGPC(DLMUX, "unsupported message type %d\n",
 			frame->msg_type);
diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c
index 7b9bac0..fd1895f 100644
--- a/openbsc/src/libtrau/trau_mux.c
+++ b/openbsc/src/libtrau/trau_mux.c
@@ -314,7 +314,7 @@
 	return msg;
 
 bad_frame:
-	frame->msg_type = GSM_TCHF_BAD_FRAME;
+	frame->msg_type = GSM_BAD_FRAME;
 
 	return msg;
 }
diff --git a/openbsc/tests/trau/trau_test.c b/openbsc/tests/trau/trau_test.c
index f8a48db..b95f1e8 100644
--- a/openbsc/tests/trau/trau_test.c
+++ b/openbsc/tests/trau/trau_test.c
@@ -57,7 +57,7 @@
 	msg = trau_decode_efr(1, &tf);
 	OSMO_ASSERT(msg != NULL);
 	frame = (struct gsm_data_frame *)msg->data;
-	OSMO_ASSERT(frame->msg_type == GSM_TCHF_BAD_FRAME);
+	OSMO_ASSERT(frame->msg_type == GSM_BAD_FRAME);
 	msgb_free(msg);
 }