Add basic support for CBCH / SMS-CB (Cell Brroadcast)

We can now configure the pyisical channel types for CBCH either in the
CCCH+SDCCH4 or in the SDCCH8 chanel combination.

Depending on whether a CBCH exists on the BTS, we also generate the SI4
with matching CBCH channel description to notify the phones of the
existance of the CBCH.

There is now a VTY command how a SMS-CB message can be sent to a given
BTS.

We do not yet have any logic at all for actual scheduling of multiple
CBCH RSL messages towards one or multiple BTSs yet, though.
diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c
index 97827f2..29b9b19 100644
--- a/openbsc/src/libbsc/system_information.c
+++ b/openbsc/src/libbsc/system_information.c
@@ -555,11 +555,34 @@
 	return sizeof(*si3) + rc;
 }
 
+/* return the gsm_lchan for the CBCH (if it exists at all) */
+static struct gsm_lchan *bts_get_cbch(struct gsm_bts *bts)
+{
+	struct gsm_lchan *lchan = NULL;
+	struct gsm_bts_trx *trx = bts->c0;
+
+	if (trx->ts[0].pchan == GSM_PCHAN_CCCH_SDCCH4_CBCH)
+		lchan = &trx->ts[0].lchan[2];
+	else {
+		int i;
+		for (i = 0; i < 8; i++) {
+			if (trx->ts[i].pchan == GSM_PCHAN_SDCCH8_SACCH8C_CBCH) {
+				lchan = &trx->ts[i].lchan[2];
+				break;
+			}
+		}
+	}
+
+	return lchan;
+}
+
 static int generate_si4(uint8_t *output, struct gsm_bts *bts)
 {
 	int rc;
 	struct gsm48_system_information_type_4 *si4 =
 		(struct gsm48_system_information_type_4 *) output;
+	struct gsm_lchan *cbch_lchan;
+	uint8_t *restoct = si4->data;
 
 	/* length of all IEs present except SI4 rest octets and l2_plen */
 	int l2_plen = sizeof(*si4) - 1;
@@ -577,15 +600,25 @@
 	si4->rach_control = bts->si_common.rach_control;
 
 	/* Optional: CBCH Channel Description + CBCH Mobile Allocation */
+	cbch_lchan = bts_get_cbch(bts);
+	if (cbch_lchan) {
+		struct gsm48_chan_desc cd;
+		gsm48_lchan2chan_desc(&cd, cbch_lchan);
+		tv_fixed_put(si4->data, GSM48_IE_CBCH_CHAN_DESC, 4,
+			     (uint8_t *) &cd);
+		l2_plen += 4 + 1;
+		restoct += 4 + 1;
+		/* we don't use hopping and thus don't need a CBCH MA */
+	}
 
 	si4->header.l2_plen = (l2_plen << 2) | 1;
 
 	/* SI4 Rest Octets (10.5.2.35), containing
 		Optional Power offset, GPRS Indicator,
 		Cell Identity, LSA ID, Selection Parameter */
-	rc = rest_octets_si4(si4->data, &si_info);
+	rc = rest_octets_si4(restoct, &si_info);
 
-	return sizeof(*si4) + rc;
+	return l2_plen + 1 + rc;
 }
 
 static int generate_si5(uint8_t *output, struct gsm_bts *bts)