chan: Store the to be assigned channel type in the GSM Network.

Store the mapping from request to channel type in the GSM Network
struct as there is some policy involved with handling the request.

E.g. in a half rate network we don't want emergy calls to be getting
a TCH/F, or we want to have a different policy for early/late assignment
of phone calls. Update the table when creating the network and when
the neci is changed.
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 4827dd0..047c768 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -1188,8 +1188,8 @@
 
 	/* determine channel type (SDCCH/TCH_F/TCH_H) based on
 	 * request reference RA */
-	lctype = get_ctype_by_chreq(bts, rqd_ref->ra, bts->network->neci);
-	chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra, bts->network->neci);
+	lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
+	chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
 
 	counter_inc(bts->network->stats.chreq.total);
 
diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c
index 44cef0a..71e4aed 100644
--- a/openbsc/src/bs11_config.c
+++ b/openbsc/src/bs11_config.c
@@ -872,3 +872,8 @@
 
 	exit(0);
 }
+
+/* dummy to be able to compile */
+void gsm_net_update_ctype(struct gsm_network *net)
+{
+}
diff --git a/openbsc/src/bsc_vty.c b/openbsc/src/bsc_vty.c
index f56440e..d9c248f 100644
--- a/openbsc/src/bsc_vty.c
+++ b/openbsc/src/bsc_vty.c
@@ -1129,6 +1129,7 @@
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
 
 	gsmnet->neci = atoi(argv[0]);
+	gsm_net_update_ctype(gsmnet);
 	return CMD_SUCCESS;
 }
 
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index 72de3b4..bb01746 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -132,13 +132,36 @@
 	[CHREQ_T_RESERVED_IGNORE]	= GSM_CHREQ_REASON_OTHER,
 };
 
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
+/* verify that the two tables match */
+static_assert(sizeof(ctype_by_chreq) ==
+	      sizeof(((struct gsm_network *) NULL)->ctype_by_chreq), assert_size);
+
+/*
+ * Update channel types for request based on policy. E.g. in the
+ * case of a TCH/H network/bsc use TCH/H for the emergency calls,
+ * for early assignment assign a SDCCH and some other options.
+ */
+void gsm_net_update_ctype(struct gsm_network *network)
+{
+	/* copy over the data */
+	memcpy(network->ctype_by_chreq, ctype_by_chreq, sizeof(ctype_by_chreq));
+
+	/*
+	 * Use TCH/H for emergency calls when this cell allows TCH/H. Maybe it
+	 * is better to iterate over the BTS/TRX and check if no TCH/F is available
+	 * and then set it to TCH/H.
+	 */
+	if (network->neci)
+		network->ctype_by_chreq[CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_H;
+}
+
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *network, u_int8_t ra)
 {
 	int i;
 	int length;
 	const struct chreq *chreq;
 
-	if (neci) {
+	if (network->neci) {
 		chreq = chreq_type_neci1;
 		length = ARRAY_SIZE(chreq_type_neci1);
 	} else {
@@ -150,13 +173,13 @@
 	for (i = 0; i < length; i++) {
 		const struct chreq *chr = &chreq[i];
 		if ((ra & chr->mask) == chr->val)
-			return ctype_by_chreq[chr->type];
+			return network->ctype_by_chreq[chr->type];
 	}
 	LOGP(DRR, LOGL_ERROR, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
 	return GSM_LCHAN_SDCCH;
 }
 
-enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
+enum gsm_chreq_reason_t get_reason_by_chreq(u_int8_t ra, int neci)
 {
 	int i;
 	int length;
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index f71527d..29b6d07 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -305,6 +305,8 @@
 
 	net->mncc_recv = mncc_recv;
 
+	gsm_net_update_ctype(net);
+
 	return net;
 }