chan_alloc: Support allocating TCH/F of a dynamic TCH/F + PDCH

This code simply enables the channel allocator to understand the
dynamic TCH/F / PDCH channel type as used by ip.access nanoBTS.

It does not actually try to switch the dynamic mode, but instead
sends signals to a (not yet present) dynamic switching algorithm.
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index c8e358d..a986bb3 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -152,6 +152,7 @@
 	[GSM_PCHAN_TCH_H] = 2,
 	[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
 	/* FIXME: what about dynamic TCH_F_TCH_H ? */
+	[GSM_PCHAN_TCH_F_PDCH] = 1,
 };
 
 static struct gsm_lchan *
@@ -167,7 +168,14 @@
 		ts = &trx->ts[j];
 		if (!ts_is_usable(ts))
 			continue;
-		if (ts->pchan != pchan)
+		/* ip.access dynamic TCH/F + PDCH combination */
+		if (ts->pchan == GSM_PCHAN_TCH_F_PDCH &&
+		    pchan == GSM_PCHAN_TCH_F) {
+			/* we can only consider such a dynamic channel
+			 * if the PDCH is currently inactive */
+			if (ts->flags & TS_F_PDCH_MODE)
+				continue;
+		} else if (ts->pchan != pchan)
 			continue;
 		/* check if all sub-slots are allocated yet */
 		for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) {
@@ -177,6 +185,7 @@
 				return lc;
 		}
 	}
+
 	return NULL;
 }
 
@@ -269,6 +278,11 @@
 		lchan->conn.release_timer.data = lchan;
 		bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT);
 
+	} else {
+		struct challoc_signal_data sig;
+		sig.bts = bts;
+		sig.type = type;
+		dispatch_signal(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig);
 	}
 
 	return lchan;
@@ -277,8 +291,10 @@
 /* Free a logical channel */
 void lchan_free(struct gsm_lchan *lchan)
 {
+	struct challoc_signal_data sig;
 	int i;
 
+	sig.type = lchan->type;
 	lchan->type = GSM_LCHAN_NONE;
 	if (lchan->conn.subscr) {
 		subscr_put(lchan->conn.subscr);
@@ -306,6 +322,10 @@
 
 	lchan->conn.silent_call = 0;
 
+	sig.lchan = lchan;
+	sig.bts = lchan->ts->trx->bts;
+	dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig);
+
 	/* FIXME: ts_free() the timeslot, if we're the last logical
 	 * channel using it */
 }