Merge branch 'zecke/feature/location-control'

Merge the code from the On-Waves branch. Use the internal RF control
interface to switch the TRXs on/off. This code has the necessary delays
to not crash the nanoBTS. Introduce signals for re-connection of the
BSC on the A-link.
diff --git a/openbsc/include/openbsc/osmo_bsc_rf.h b/openbsc/include/openbsc/osmo_bsc_rf.h
index d3e2cab..c0ab6b2 100644
--- a/openbsc/include/openbsc/osmo_bsc_rf.h
+++ b/openbsc/include/openbsc/osmo_bsc_rf.h
@@ -56,5 +56,6 @@
 enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_bts(struct gsm_bts *bts);
 enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts);
 struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net);
+void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd);
 
 #endif
diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h
index fd13ac7..39319f1 100644
--- a/openbsc/include/openbsc/signal.h
+++ b/openbsc/include/openbsc/signal.h
@@ -219,6 +219,7 @@
 enum signal_msc {
 	S_MSC_LOST,
 	S_MSC_CONNECTED,
+	S_MSC_AUTHENTICATED,
 };
 
 struct osmo_msc_data;
diff --git a/openbsc/src/libbsc/bsc_rf_ctrl.c b/openbsc/src/libbsc/bsc_rf_ctrl.c
index 2f39f43..89a0246 100644
--- a/openbsc/src/libbsc/bsc_rf_ctrl.c
+++ b/openbsc/src/libbsc/bsc_rf_ctrl.c
@@ -239,6 +239,11 @@
 
 static int enter_grace(struct osmo_bsc_rf *rf)
 {
+	if (osmo_timer_pending(&rf->grace_timeout)) {
+		LOGP(DLINP, LOGL_NOTICE, "RF Grace timer is pending. Not restarting.\n");
+		return 0;
+	}
+
 	rf->grace_timeout.cb = grace_timeout;
 	rf->grace_timeout.data = rf;
 	osmo_timer_schedule(&rf->grace_timeout, rf->gsm_network->bsc_data->mid_call_timeout, 0);
@@ -298,9 +303,7 @@
 	case RF_CMD_D_OFF:
 	case RF_CMD_ON:
 	case RF_CMD_OFF:
-		conn->rf->last_request = buf[0];
-		if (!osmo_timer_pending(&conn->rf->delay_cmd))
-			osmo_timer_schedule(&conn->rf->delay_cmd, 1, 0);
+		osmo_bsc_rf_schedule_lock(conn->rf, buf[0]);
 		break;
 	default:
 		conn->rf->last_state_command = "Unknown command";
@@ -444,3 +447,9 @@
 	return rf;
 }
 
+void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd)
+{
+	rf->last_request = cmd;
+	if (!osmo_timer_pending(&rf->delay_cmd))
+		osmo_timer_schedule(&rf->delay_cmd, 1, 0);
+}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
index 8f0db7e..e4c6fea 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_ctrl.c
@@ -1,4 +1,5 @@
 /* (C) 2011 by Daniel Willmann <daniel@totalueberwachung.de>
+ * (C) 2011 by Holger Hans Peter Freyther
  * (C) 2011 by On-Waves
  * All Rights Reserved
  *
@@ -388,19 +389,19 @@
 {
 	int locked = atoi(cmd->value);
 	struct gsm_network *net = cmd->node;
-	struct gsm_bts *bts;
 	if (!net) {
 		cmd->reply = "net not found.";
 		return CTRL_CMD_ERROR;
 	}
 
-	llist_for_each_entry(bts, &net->bts_list, list) {
-		struct gsm_bts_trx *trx;
-		llist_for_each_entry(trx, &bts->trx_list, list) {
-			gsm_trx_lock_rf(trx, locked);
-		}
+	if (!net->bsc_data->rf_ctrl) {
+		cmd->reply = "RF Ctrl is not enabled in the BSC Configuration";
+		return CTRL_CMD_ERROR;
 	}
 
+	osmo_bsc_rf_schedule_lock(net->bsc_data->rf_ctrl,
+			locked == 1 ? '0' : '1');
+
 	cmd->reply = talloc_asprintf(cmd, "%u", locked);
 	if (!cmd->reply) {
 		cmd->reply = "OOM.";
@@ -420,6 +421,27 @@
 	return 0;
 }
 
+static int msc_signal_handler(unsigned int subsys, unsigned int signal,
+			void *handler_data, void *signal_data)
+{
+	struct msc_signal_data *msc;
+	struct gsm_network *net;
+	struct gsm_bts *bts;
+
+	if (subsys != SS_MSC)
+		return 0;
+	if (signal != S_MSC_AUTHENTICATED)
+		return 0;
+
+	msc = signal_data;
+
+	net = msc->data->network;
+	llist_for_each_entry(bts, &net->bts_list, list)
+		generate_location_state_trap(bts, msc->data->msc_con);	
+
+	return 0;
+}
+
 int bsc_ctrl_cmds_install(struct gsm_network *net)
 {
 	int rc;
@@ -436,10 +458,14 @@
 	rc = osmo_signal_register_handler(SS_MSC, &msc_connection_status_trap_cb, net);
 	if (rc)
 		goto end;
+	rc = osmo_signal_register_handler(SS_MSC, msc_signal_handler, NULL);
+	if (rc)
+		goto end;
 	rc = ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_bts_connection_status);
 	if (rc)
 		goto end;
 	rc = osmo_signal_register_handler(SS_L_INPUT, &bts_connection_status_trap_cb, net);
+
 end:
 	return rc;
 }
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
index a979681..5517d30 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
@@ -422,12 +422,16 @@
 
 static void send_id_get_response(struct osmo_msc_data *data, int fd)
 {
+	struct msc_signal_data sig;
 	struct msgb *msg;
 
 	msg = bsc_msc_id_get_resp(data->bsc_token);
 	if (!msg)
 		return;
 	msc_queue_write(data->msc_con, msg, IPAC_PROTO_IPACCESS);
+
+	sig.data = data;
+	osmo_signal_dispatch(SS_MSC, S_MSC_AUTHENTICATED, &sig);
 }
 
 int osmo_bsc_msc_init(struct osmo_msc_data *data)