IPA_Emulation: Send ASP_IPA_EVENT_UP even in client mode
diff --git a/library/IPA_Emulation.ttcn b/library/IPA_Emulation.ttcn
index fc42dba..6af572c 100644
--- a/library/IPA_Emulation.ttcn
+++ b/library/IPA_Emulation.ttcn
@@ -320,6 +320,7 @@
 		     IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
 	g_mode := IPA_MODE_CLIENT;
 	f_connect(remote_host, remote_port, local_host, local_port, ccm_pars);
+	f_send_IPA_EVT(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_UP));
 	ScanEvents();
 }
 
diff --git a/library/Osmocom_CTRL_Functions.ttcn b/library/Osmocom_CTRL_Functions.ttcn
new file mode 100644
index 0000000..8bd6025
--- /dev/null
+++ b/library/Osmocom_CTRL_Functions.ttcn
@@ -0,0 +1,60 @@
+module Osmocom_CTRL_Functions {
+	import from Osmocom_CTRL_Types all;
+	import from IPA_Emulation all;
+
+	private function f_gen_rand_id() return CtrlId {
+		return int2str(float2int(rnd()*999999999.0));
+	}
+
+	/* perform a given GET Operation */
+	function f_ctrl_get(IPA_CTRL_PT pt, CtrlVariable variable) return CtrlValue {
+		timer T := 2.0;
+		var CtrlMessage rx;
+		var CtrlId id := f_gen_rand_id();
+		pt.send(ts_CtrlMsgGet(id, variable));
+		T.start;
+		alt {
+		[] pt.receive(tr_CtrlMsgGetRepl(id, variable)) -> value rx { }
+		[] pt.receive(tr_CtrlMsgError) -> value rx {
+			setverdict(fail, "Error in CTRL GET ", variable, ": ", rx.err.reason);
+			}
+		[] T.timeout {
+			setverdict(fail, "Timeout waiting for CTRL GET REPLY ", variable);
+			}
+		}
+		return rx.resp.val;
+	}
+
+	/* perform a given SET Operation */
+	function f_ctrl_set(IPA_CTRL_PT pt, CtrlVariable variable, CtrlValue val) {
+		timer T := 2.0;
+		var CtrlMessage rx;
+		var CtrlId id := f_gen_rand_id();
+		pt.send(ts_CtrlMsgSet(id, variable, val));
+		T.start;
+		alt {
+		[] pt.receive(tr_CtrlMsgSetRepl(id, variable, val)) { }
+		[] pt.receive(tr_CtrlMsgError) -> value rx {
+			setverdict(fail, "Error in CTRL GET ", variable, ": ", rx.err.reason);
+			}
+		[] T.timeout {
+			setverdict(fail, "Timeout waiting for CTRL SET REPLY ", variable);
+			}
+		}
+	}
+
+	/* Expect a matching TRAP */
+	function f_ctrl_exp_trap(IPA_CTRL_PT pt, template CtrlVariable variable,
+				 template CtrlValue val := ?) return CtrlValue {
+		timer T := 2.0;
+		var CtrlMessage rx;
+		T.start;
+		alt {
+		[] pt.receive(tr_CtrlMsgTrap(variable, val)) -> value rx {}
+		[] T.timeout {
+			setverdict(fail, "Timeout waiting for TRAP ", variable);
+			}
+		}
+		return rx.trap.val;
+	}
+}
diff --git a/library/Osmocom_CTRL_Types.ttcn b/library/Osmocom_CTRL_Types.ttcn
index db5012c..87ef6d2 100644
--- a/library/Osmocom_CTRL_Types.ttcn
+++ b/library/Osmocom_CTRL_Types.ttcn
@@ -6,8 +6,8 @@
 	variant "TEXT_CODING(,convert=upper_case,'((GET)|(SET)|(TRAP))',case_insensitive)"
 };
 
-type charstring CtrlReplyToken ("REPLY") with {
-	variant "TEXT_CODING(,convert=upper_case,'(REPLY)',case_insensitive)"
+type charstring CtrlReplyVerb ("GET_REPLY", "SET_REPLY") with {
+	variant "TEXT_CODING(,convert=upper_case,'((GET_REPLY)|(SET_REPLY))',case_insensitive)"
 };
 
 type charstring CtrlId	(pattern "\d#(1,9)");
@@ -26,13 +26,11 @@
 };
 
 type record CtrlResponse {
-	CtrlVerb	verb,
-	CtrlReplyToken	repl,
+	CtrlReplyVerb	verb,
 	CtrlId		id,
 	CtrlVariable	variable,
 	CtrlValue	val
 } with {
-	variant "TEXT_CODING(,,'* REPLY *',case_insensitive)"
 	variant "SEPARATOR(' ',)"
 };
 
@@ -66,4 +64,57 @@
 	with { extension "prototype(convert) decode(TEXT)"};
 
 
+template CtrlMessage ts_CtrlMsgGet(CtrlId id, CtrlVariable variable) := {
+	cmd := {
+		verb := "GET",
+		id := id,
+		variable := variable,
+		val := omit
+	}
+};
+
+template CtrlMessage ts_CtrlMsgSet(CtrlId id, CtrlVariable variable, CtrlValue val) := {
+	cmd := {
+		verb := "SET",
+		id := id,
+		variable := variable,
+		val := omit
+	}
+}
+
+template CtrlMessage tr_CtrlMsgGetRepl(template CtrlId id, template CtrlVariable variable := ?) := {
+	resp := {
+		verb := "GET_REPLY",
+		id := id,
+		variable := variable,
+		val := ?
+	}
+}
+
+template CtrlMessage tr_CtrlMsgSetRepl(template CtrlId id, template CtrlVariable variable := ?,
+			   template CtrlValue val := ?) := {
+	resp := {
+		verb := "SET_REPLY",
+		id := id,
+		variable := variable,
+		val := val
+	}
+}
+
+template CtrlMessage tr_CtrlMsgTrap(template CtrlVariable variable := ?,
+			template CtrlValue val := ?) := {
+	trap := {
+		variable := variable,
+		val := val
+	}
+}
+
+template CtrlMessage tr_CtrlMsgError(template CtrlId id := ?, template CtrlReason reason := ?) := {
+	err := {
+		id := id,
+		reason := reason
+	}
+}
+
+
 } with { encode "TEXT" }