split gsm_data.c in gsm_data_shared.c and gsm_data.c

This facilitates the use of gsm_data.c from osmo-bts
diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
index 9d0e2db..368f788 100644
--- a/openbsc/src/ipaccess/ipaccess-config.c
+++ b/openbsc/src/ipaccess/ipaccess-config.c
@@ -896,8 +896,8 @@
 	if (!gsmnet)
 		exit(1);
 
-	bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_NANOBTS, HARDCODED_TSC,
-				HARDCODED_BSIC);
+	bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_NANOBTS, HARDCODED_TSC,
+				     HARDCODED_BSIC);
 	/* ip.access supports up to 4 chained TRX */
 	gsm_bts_trx_alloc(bts);
 	gsm_bts_trx_alloc(bts);
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index 37a1e2f..971cdf7 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -1442,8 +1442,8 @@
 		return CMD_WARNING;
 	} else if (bts_nr == gsmnet->num_bts) {
 		/* allocate a new one */
-		bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_UNKNOWN,
-				    HARDCODED_TSC, HARDCODED_BSIC);
+		bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_UNKNOWN,
+					     HARDCODED_TSC, HARDCODED_BSIC);
 	} else
 		bts = gsm_bts_num(gsmnet, bts_nr);
 
diff --git a/openbsc/src/libcommon/Makefile.am b/openbsc/src/libcommon/Makefile.am
index ed74b44..a832b75 100644
--- a/openbsc/src/libcommon/Makefile.am
+++ b/openbsc/src/libcommon/Makefile.am
@@ -4,4 +4,4 @@
 
 noinst_LIBRARIES = libcommon.a
 
-libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c socket.c talloc_ctx.c
+libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c gsm_data_shared.c socket.c talloc_ctx.c
diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c
index a85eb84..268137f 100644
--- a/openbsc/src/libcommon/gsm_data.c
+++ b/openbsc/src/libcommon/gsm_data.c
@@ -48,72 +48,6 @@
 	ts->e1_link.e1_ts_ss = e1_ts_ss;
 }
 
-static const struct value_string pchan_names[] = {
-	{ GSM_PCHAN_NONE,	"NONE" },
-	{ GSM_PCHAN_CCCH,	"CCCH" },
-	{ GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" },
-	{ GSM_PCHAN_TCH_F,	"TCH/F" },
-	{ GSM_PCHAN_TCH_H,	"TCH/H" },
-	{ GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" },
-	{ GSM_PCHAN_PDCH,	"PDCH" },
-	{ GSM_PCHAN_TCH_F_PDCH,	"TCH/F_PDCH" },
-	{ GSM_PCHAN_UNKNOWN,	"UNKNOWN" },
-	{ 0,			NULL }
-};
-
-const char *gsm_pchan_name(enum gsm_phys_chan_config c)
-{
-	return get_value_string(pchan_names, c);
-}
-
-enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
-{
-	return get_string_value(pchan_names, name);
-}
-
-static const struct value_string lchant_names[] = {
-	{ GSM_LCHAN_NONE,	"NONE" },
-	{ GSM_LCHAN_SDCCH,	"SDCCH" },
-	{ GSM_LCHAN_TCH_F,	"TCH/F" },
-	{ GSM_LCHAN_TCH_H,	"TCH/H" },
-	{ GSM_LCHAN_UNKNOWN,	"UNKNOWN" },
-	{ 0,			NULL }
-};
-
-const char *gsm_lchant_name(enum gsm_chan_t c)
-{
-	return get_value_string(lchant_names, c);
-}
-
-static const struct value_string lchan_s_names[] = {
-	{ LCHAN_S_NONE,		"NONE" },
-	{ LCHAN_S_ACT_REQ,	"ACTIVATION REQUESTED" },
-	{ LCHAN_S_ACTIVE,	"ACTIVE" },
-	{ LCHAN_S_INACTIVE,	"INACTIVE" },
-	{ LCHAN_S_REL_REQ,	"RELEASE REQUESTED" },
-	{ LCHAN_S_REL_ERR,	"RELEASE DUE ERROR" },
-	{ 0,			NULL }
-};
-
-const char *gsm_lchans_name(enum gsm_lchan_state s)
-{
-	return get_value_string(lchan_s_names, s);
-}
-
-static const struct value_string chreq_names[] = {
-	{ GSM_CHREQ_REASON_EMERG,	"EMERGENCY" },
-	{ GSM_CHREQ_REASON_PAG,		"PAGING" },
-	{ GSM_CHREQ_REASON_CALL,	"CALL" },
-	{ GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" },
-	{ GSM_CHREQ_REASON_OTHER,	"OTHER" },
-	{ 0,				NULL }
-};
-
-const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
-{
-	return get_value_string(chreq_names, c);
-}
-
 static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
 {
 	struct gsm_bts_model *model;
@@ -136,124 +70,6 @@
 	return 0;
 }
 
-
-struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
-{
-	struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
-	int k;
-
-	if (!trx)
-		return NULL;
-
-	trx->bts = bts;
-	trx->nr = bts->num_trx++;
-	trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
-
-	for (k = 0; k < TRX_NR_TS; k++) {
-		struct gsm_bts_trx_ts *ts = &trx->ts[k];
-		int l;
-		
-		ts->trx = trx;
-		ts->nr = k;
-		ts->pchan = GSM_PCHAN_NONE;
-		ts->tsc = -1;
-
-		ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
-		ts->hopping.arfcns.data = ts->hopping.arfcns_data;
-		ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);
-		ts->hopping.ma.data = ts->hopping.ma_data;
-
-		for (l = 0; l < TS_MAX_LCHAN; l++) {
-			struct gsm_lchan *lchan;
-			lchan = &ts->lchan[l];
-
-			lchan->ts = ts;
-			lchan->nr = l;
-			lchan->type = GSM_LCHAN_NONE;
-		}
-	}
-
-	if (trx->nr != 0)
-		trx->nominal_power = bts->c0->nominal_power;
-
-	llist_add_tail(&trx->list, &bts->trx_list);
-
-	return trx;
-}
-
-static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
-static const uint8_t bts_cell_timer_default[] =
-				{ 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
-
-struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
-			      uint8_t tsc, uint8_t bsic)
-{
-	struct gsm_bts *bts = talloc_zero(net, struct gsm_bts);
-	struct gsm_bts_model *model = bts_model_find(type);
-	int i;
-
-	if (!bts)
-		return NULL;
-
-	if (!model && type != GSM_BTS_TYPE_UNKNOWN) {
-		talloc_free(bts);
-		return NULL;
-	}
-
-	bts->network = net;
-	bts->nr = net->num_bts++;
-	bts->type = type;
-	bts->model = model;
-	bts->tsc = tsc;
-	bts->bsic = bsic;
-	bts->num_trx = 0;
-	INIT_LLIST_HEAD(&bts->trx_list);
-	bts->ms_max_power = 15;	/* dBm */
-
-	bts->neigh_list_manual_mode = 0;
-	bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
-	bts->si_common.cell_sel_par.rxlev_acc_min = 0;
-	bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
-	bts->si_common.neigh_list.data_len =
-				sizeof(bts->si_common.data.neigh_list);
-	bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list;
-	bts->si_common.si5_neigh_list.data_len =
-				sizeof(bts->si_common.data.si5_neigh_list);
-	bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
-	bts->si_common.cell_alloc.data_len =
-				sizeof(bts->si_common.data.cell_alloc);
-	bts->si_common.rach_control.re = 1; /* no re-establishment */
-	bts->si_common.rach_control.tx_integer = 9;  /* 12 slots spread - 217/115 slots delay */
-	bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
-	bts->si_common.rach_control.t2 = 4; /* no emergency calls */
-
-	for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
-		bts->gprs.nsvc[i].bts = bts;
-		bts->gprs.nsvc[i].id = i;
-	}
-	memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
-		sizeof(bts->gprs.nse.timer));
-	memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
-		sizeof(bts->gprs.cell.timer));
-
-	/* create our primary TRX */
-	bts->c0 = gsm_bts_trx_alloc(bts);
-	if (!bts->c0) {
-		talloc_free(bts);
-		return NULL;
-	}
-	bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
-
-	bts->rach_b_thresh = -1;
-	bts->rach_ldavg_slots = -1;
-	bts->paging.free_chans_need = -1;
-	INIT_LLIST_HEAD(&bts->abis_queue);
-
-	llist_add_tail(&bts->list, &net->bts_list);
-
-	return bts;
-}
-
 struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_code,
 				     int (*mncc_recv)(struct gsm_network *, struct msgb *))
 {
@@ -371,50 +187,6 @@
 	return NULL;
 }
 
-struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num)
-{
-	struct gsm_bts_trx *trx;
-
-	if (num >= bts->num_trx)
-		return NULL;
-
-	llist_for_each_entry(trx, &bts->trx_list, list) {
-		if (trx->nr == num)
-			return trx;
-	}
-
-	return NULL;
-}
-
-static char ts2str[255];
-
-char *gsm_trx_name(struct gsm_bts_trx *trx)
-{
-	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
-		 trx->bts->nr, trx->nr);
-
-	return ts2str;
-}
-
-
-char *gsm_ts_name(struct gsm_bts_trx_ts *ts)
-{
-	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
-		 ts->trx->bts->nr, ts->trx->nr, ts->nr);
-
-	return ts2str;
-}
-
-char *gsm_lchan_name(struct gsm_lchan *lchan)
-{
-	struct gsm_bts_trx_ts *ts = lchan->ts;
-
-	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
-		 ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
-
-	return ts2str;
-}
-
 static const struct value_string bts_types[] = {
 	{ GSM_BTS_TYPE_UNKNOWN,	"unknown" },
 	{ GSM_BTS_TYPE_BS11,	"bs11" },
@@ -489,23 +261,6 @@
 	return get_value_string(auth_policy_names, policy);
 }
 
-void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts)
-{
-	raid->mcc = bts->network->country_code;
-	raid->mnc = bts->network->network_code;
-	raid->lac = bts->location_area_code;
-	raid->rac = bts->gprs.rac;
-}
-
-int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts)
-{
-	struct gprs_ra_id raid;
-
-	gprs_ra_id_by_bts(&raid, bts);
-
-	return gsm48_construct_ra(buf, &raid);
-}
-
 static const struct value_string rrlp_mode_names[] = {
 	{ RRLP_MODE_NONE,	"none" },
 	{ RRLP_MODE_MS_BASED,	"ms-based" },
@@ -602,3 +357,66 @@
 
 	return 0;
 }
+
+struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type,
+					uint8_t tsc, uint8_t bsic)
+{
+	struct gsm_bts_model *model = bts_model_find(type);
+	struct gsm_bts *bts;
+
+	if (!model && type != GSM_BTS_TYPE_UNKNOWN) {
+		talloc_free(bts);
+		return NULL;
+	}
+
+	bts = gsm_bts_alloc(net);
+	if (!bts)
+		return NULL;
+
+	bts->network = net;
+	bts->nr = net->num_bts++;
+	bts->type = type;
+	bts->model = model;
+	bts->tsc = tsc;
+	bts->bsic = bsic;
+
+	bts->neigh_list_manual_mode = 0;
+	bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
+	bts->si_common.cell_sel_par.rxlev_acc_min = 0;
+	bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
+	bts->si_common.neigh_list.data_len =
+				sizeof(bts->si_common.data.neigh_list);
+	bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list;
+	bts->si_common.si5_neigh_list.data_len =
+				sizeof(bts->si_common.data.si5_neigh_list);
+	bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
+	bts->si_common.cell_alloc.data_len =
+				sizeof(bts->si_common.data.cell_alloc);
+	bts->si_common.rach_control.re = 1; /* no re-establishment */
+	bts->si_common.rach_control.tx_integer = 9;  /* 12 slots spread - 217/115 slots delay */
+	bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
+	bts->si_common.rach_control.t2 = 4; /* no emergency calls */
+
+	llist_add_tail(&bts->list, &net->bts_list);
+
+	INIT_LLIST_HEAD(&bts->abis_queue);
+
+	return bts;
+}
+
+void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts)
+{
+	raid->mcc = bts->network->country_code;
+	raid->mnc = bts->network->network_code;
+	raid->lac = bts->location_area_code;
+	raid->rac = bts->gprs.rac;
+}
+
+int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts)
+{
+	struct gprs_ra_id raid;
+
+	gprs_ra_id_by_bts(&raid, bts);
+
+	return gsm48_construct_ra(buf, &raid);
+}
diff --git a/openbsc/src/libcommon/gsm_data_shared.c b/openbsc/src/libcommon/gsm_data_shared.c
new file mode 100644
index 0000000..a58935f
--- /dev/null
+++ b/openbsc/src/libcommon/gsm_data_shared.c
@@ -0,0 +1,229 @@
+/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <netinet/in.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/abis_nm.h>
+#include <osmocom/core/statistics.h>
+
+#include <openbsc/gsm_data_shared.h>
+
+static const struct value_string pchan_names[] = {
+	{ GSM_PCHAN_NONE,	"NONE" },
+	{ GSM_PCHAN_CCCH,	"CCCH" },
+	{ GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" },
+	{ GSM_PCHAN_TCH_F,	"TCH/F" },
+	{ GSM_PCHAN_TCH_H,	"TCH/H" },
+	{ GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" },
+	{ GSM_PCHAN_PDCH,	"PDCH" },
+	{ GSM_PCHAN_TCH_F_PDCH,	"TCH/F_PDCH" },
+	{ GSM_PCHAN_UNKNOWN,	"UNKNOWN" },
+	{ 0,			NULL }
+};
+
+const char *gsm_pchan_name(enum gsm_phys_chan_config c)
+{
+	return get_value_string(pchan_names, c);
+}
+
+enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
+{
+	return get_string_value(pchan_names, name);
+}
+
+static const struct value_string lchant_names[] = {
+	{ GSM_LCHAN_NONE,	"NONE" },
+	{ GSM_LCHAN_SDCCH,	"SDCCH" },
+	{ GSM_LCHAN_TCH_F,	"TCH/F" },
+	{ GSM_LCHAN_TCH_H,	"TCH/H" },
+	{ GSM_LCHAN_UNKNOWN,	"UNKNOWN" },
+	{ 0,			NULL }
+};
+
+const char *gsm_lchant_name(enum gsm_chan_t c)
+{
+	return get_value_string(lchant_names, c);
+}
+
+static const struct value_string lchan_s_names[] = {
+	{ LCHAN_S_NONE,		"NONE" },
+	{ LCHAN_S_ACT_REQ,	"ACTIVATION REQUESTED" },
+	{ LCHAN_S_ACTIVE,	"ACTIVE" },
+	{ LCHAN_S_INACTIVE,	"INACTIVE" },
+	{ LCHAN_S_REL_REQ,	"RELEASE REQUESTED" },
+	{ LCHAN_S_REL_ERR,	"RELEASE DUE ERROR" },
+	{ 0,			NULL }
+};
+
+const char *gsm_lchans_name(enum gsm_lchan_state s)
+{
+	return get_value_string(lchan_s_names, s);
+}
+
+static const struct value_string chreq_names[] = {
+	{ GSM_CHREQ_REASON_EMERG,	"EMERGENCY" },
+	{ GSM_CHREQ_REASON_PAG,		"PAGING" },
+	{ GSM_CHREQ_REASON_CALL,	"CALL" },
+	{ GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" },
+	{ GSM_CHREQ_REASON_OTHER,	"OTHER" },
+	{ 0,				NULL }
+};
+
+const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
+{
+	return get_value_string(chreq_names, c);
+}
+
+struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
+{
+	struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
+	int k;
+
+	if (!trx)
+		return NULL;
+
+	trx->bts = bts;
+	trx->nr = bts->num_trx++;
+	trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
+
+	for (k = 0; k < TRX_NR_TS; k++) {
+		struct gsm_bts_trx_ts *ts = &trx->ts[k];
+		int l;
+
+		ts->trx = trx;
+		ts->nr = k;
+		ts->pchan = GSM_PCHAN_NONE;
+		ts->tsc = -1;
+
+		ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
+		ts->hopping.arfcns.data = ts->hopping.arfcns_data;
+		ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);
+		ts->hopping.ma.data = ts->hopping.ma_data;
+
+		for (l = 0; l < TS_MAX_LCHAN; l++) {
+			struct gsm_lchan *lchan;
+			lchan = &ts->lchan[l];
+
+			lchan->ts = ts;
+			lchan->nr = l;
+			lchan->type = GSM_LCHAN_NONE;
+		}
+	}
+
+	if (trx->nr != 0)
+		trx->nominal_power = bts->c0->nominal_power;
+
+	llist_add_tail(&trx->list, &bts->trx_list);
+
+	return trx;
+}
+
+static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
+static const uint8_t bts_cell_timer_default[] =
+				{ 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
+
+struct gsm_bts *gsm_bts_alloc(void *ctx)
+{
+	struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
+	int i;
+
+	if (!bts)
+		return NULL;
+
+	bts->num_trx = 0;
+	INIT_LLIST_HEAD(&bts->trx_list);
+	bts->ms_max_power = 15;	/* dBm */
+
+	for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
+		bts->gprs.nsvc[i].bts = bts;
+		bts->gprs.nsvc[i].id = i;
+	}
+	memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
+		sizeof(bts->gprs.nse.timer));
+	memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
+		sizeof(bts->gprs.cell.timer));
+
+	/* create our primary TRX */
+	bts->c0 = gsm_bts_trx_alloc(bts);
+	if (!bts->c0) {
+		talloc_free(bts);
+		return NULL;
+	}
+	bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
+
+	bts->rach_b_thresh = -1;
+	bts->rach_ldavg_slots = -1;
+	bts->paging.free_chans_need = -1;
+
+	return bts;
+}
+
+struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num)
+{
+	struct gsm_bts_trx *trx;
+
+	if (num >= bts->num_trx)
+		return NULL;
+
+	llist_for_each_entry(trx, &bts->trx_list, list) {
+		if (trx->nr == num)
+			return trx;
+	}
+
+	return NULL;
+}
+
+static char ts2str[255];
+
+char *gsm_trx_name(struct gsm_bts_trx *trx)
+{
+	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
+		 trx->bts->nr, trx->nr);
+
+	return ts2str;
+}
+
+
+char *gsm_ts_name(struct gsm_bts_trx_ts *ts)
+{
+	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
+		 ts->trx->bts->nr, ts->trx->nr, ts->nr);
+
+	return ts2str;
+}
+
+char *gsm_lchan_name(struct gsm_lchan *lchan)
+{
+	struct gsm_bts_trx_ts *ts = lchan->ts;
+
+	snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
+		 ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
+
+	return ts2str;
+}
diff --git a/openbsc/src/utils/bs11_config.c b/openbsc/src/utils/bs11_config.c
index aa8c55d..41acd69 100644
--- a/openbsc/src/utils/bs11_config.c
+++ b/openbsc/src/utils/bs11_config.c
@@ -882,8 +882,8 @@
 		fprintf(stderr, "Unable to allocate gsm network\n");
 		exit(1);
 	}
-	g_bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_BS11, HARDCODED_TSC,
-				HARDCODED_BSIC);
+	g_bts = gsm_bts_alloc_register(gsmnet, GSM_BTS_TYPE_BS11, HARDCODED_TSC,
+					HARDCODED_BSIC);
 
 	rc = rs232_setup(serial_port, delay_ms, g_bts);
 	if (rc < 0) {