RBS2000: Automatically connect/start/configure/enable most MOs
diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h
index 83a4ee6..5e2b7ae 100644
--- a/openbsc/include/openbsc/signal.h
+++ b/openbsc/include/openbsc/signal.h
@@ -84,6 +84,7 @@
 	S_NM_TEST_REP,		/* GSM 12.21 Test Report */
 	S_NM_STATECHG_OPER,	/* Operational State changed*/
 	S_NM_STATECHG_ADM,	/* Administrative State changed */
+	S_NM_OM2K_CONF_RES,	/* OM2K Configuration Result */
 };
 
 /* SS_LCHAN signals */
@@ -187,6 +188,14 @@
 	struct abis_om2k_mo *om2k_mo;
 };
 
+struct nm_om2k_signal_data {
+	struct gsm_bts *bts;
+	void *obj;
+	struct abis_om2k_mo *om2k_mo;
+
+	uint8_t accordance_ind;
+};
+
 struct nm_nack_signal_data {
 	struct msgb *msg;
 	uint8_t mt;
diff --git a/openbsc/src/libbsc/abis_om2000.c b/openbsc/src/libbsc/abis_om2000.c
index 6b83a98..a5f5d4f 100644
--- a/openbsc/src/libbsc/abis_om2000.c
+++ b/openbsc/src/libbsc/abis_om2000.c
@@ -1400,11 +1400,14 @@
 {
 	struct abis_om2k_hdr *o2h = msgb_l2(msg);
 	uint16_t msg_type = ntohs(o2h->msg_type);
+	struct nm_om2k_signal_data nsd;
 	struct tlv_parsed tp;
 	uint8_t acc;
 	unsigned int log_level;
 	int ret;
 
+	memset(&nsd, 0, sizeof(nsd));
+
 	abis_om2k_msg_tlv_parse(&tp, o2h);
 	if (!TLVP_PRESENT(&tp, OM2K_DEI_ACCORDANCE_IND))
 		return -EIO;
@@ -1427,6 +1430,12 @@
 		get_value_string(om2k_msgcode_vals, msg_type),
 		get_value_string(om2k_accordance_strings, acc));
 
+	nsd.bts = bts;
+	nsd.obj = mo2obj(bts, &o2h->mo);
+	nsd.om2k_mo = &o2h->mo;
+	nsd.accordance_ind = acc;
+	dispatch_signal(SS_NM, S_NM_OM2K_CONF_RES, &nsd);
+
 	return ret;
 }
 
@@ -1490,42 +1499,42 @@
 		rc = abis_om2k_cal_time_resp(bts);
 		break;
 	case OM2K_MSGT_FAULT_REP:
-		process_mo_state(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_FAULT_REP_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_NEGOT_REQ:
 		rc = om2k_rx_negot_req(msg);
 		break;
 	case OM2K_MSGT_START_RES:
-		process_mo_state(bts, msg);
 		rc = om2k_rx_start_res(msg);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_OP_INFO_ACK:
 		rc = om2k_rx_op_info_ack(msg);
 		break;
 	case OM2K_MSGT_IS_CONF_RES:
-		process_conf_res(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_IS_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_CON_CONF_RES:
-		process_conf_res(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CON_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_TX_CONF_RES:
-		process_conf_res(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TX_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_RX_CONF_RES:
-		process_conf_res(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RX_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_TS_CONF_RES:
-		process_conf_res(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TS_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_TF_CONF_RES:
-		process_conf_res(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TF_CONF_RES_ACK);
+		process_conf_res(bts, msg);
 		break;
 	case OM2K_MSGT_CONNECT_COMPL:
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_RESET_CMD);
@@ -1534,16 +1543,16 @@
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_START_REQ);
 		break;
 	case OM2K_MSGT_ENABLE_RES:
-		process_mo_state(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_ENABLE_RES_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_DISABLE_RES:
-		process_mo_state(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_DISABLE_RES_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_TEST_RES:
-		process_mo_state(bts, msg);
 		rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TEST_RES_ACK);
+		process_mo_state(bts, msg);
 		break;
 	case OM2K_MSGT_STATUS_RESP:
 		process_mo_state(bts, msg);
diff --git a/openbsc/src/libbsc/bts_ericsson_rbs2000.c b/openbsc/src/libbsc/bts_ericsson_rbs2000.c
index 6480d34..1b64b36 100644
--- a/openbsc/src/libbsc/bts_ericsson_rbs2000.c
+++ b/openbsc/src/libbsc/bts_ericsson_rbs2000.c
@@ -161,13 +161,12 @@
 	case OM2K_MO_CLS_IS:
 		if (nsd->new_state->availability == OM2K_MO_S_ENABLED) {
 			/* IS is enabled, we can proceed with TRXC/RX/TX/TS */
+			break;
 		}
-		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
-		    nsd->new_state->availability == OM2K_MO_S_DISABLED)
+		if (nsd->new_state->operational != NM_OPSTATE_ENABLED)
 			break;
 		/* IS has started, we can configure + enable it */
 		abis_om2k_tx_is_conf_req(nsd->bts);
-		abis_om2k_tx_enable_req(nsd->bts, nsd->om2k_mo);
 		break;
 	case OM2K_MO_CLS_TF:
 		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
@@ -176,12 +175,10 @@
 		if (nsd->new_state->availability == OM2K_MO_S_STARTED) {
 			/* TF has started, configure + enable it */
 			abis_om2k_tx_is_conf_req(nsd->bts);
-			abis_om2k_tx_enable_req(nsd->bts, nsd->om2k_mo);
 		}
 		break;
 	case OM2K_MO_CLS_TRXC:
-		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
-		    nsd->new_state->availability != OM2K_MO_S_STARTED)
+		if (nsd->new_state->availability != OM2K_MO_S_STARTED)
 			break;
 		/* TRXC is started, connect the TX and RX objects */
 		memcpy(&mo, nsd->om2k_mo, sizeof(mo));
@@ -196,7 +193,6 @@
 			break;
 		/* RX is started, configure + enable it */
 		abis_om2k_tx_rx_conf_req(nsd->obj);
-		abis_om2k_tx_enable_req(nsd->bts, nsd->om2k_mo);
 		break;
 	case OM2K_MO_CLS_TX:
 		if (nsd->new_state->operational != NM_OPSTATE_ENABLED ||
@@ -204,6 +200,18 @@
 			break;
 		/* RX is started, configure + enable it */
 		abis_om2k_tx_tx_conf_req(nsd->obj);
+		break;
+	}
+}
+
+static void nm_conf_res(struct nm_om2k_signal_data *nsd)
+{
+	switch (nsd->om2k_mo->class) {
+	case OM2K_MO_CLS_IS:
+	case OM2K_MO_CLS_TF:
+	case OM2K_MO_CLS_RX:
+	case OM2K_MO_CLS_TX:
+		/* If configuration was a success, enable it */
 		abis_om2k_tx_enable_req(nsd->bts, nsd->om2k_mo);
 		break;
 	}
@@ -219,6 +227,10 @@
 	case S_NM_STATECHG_OPER:
 	case S_NM_STATECHG_ADM:
 		nm_statechg_evt(signal, signal_data);
+		break;
+	case S_NM_OM2K_CONF_RES:
+		nm_conf_res(signal_data);
+		break;
 	default:
 		break;
 	}