/* dual-faced port that wraps an Unixdomain port and encodes/decodes L1CTL
 * (C) 2017-2019 Harald Welte <laforge@gnumonks.org>
 * contributions by sysmocom - s.f.m.c. GmbH
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

module L1CTL_PortType {
	import from L1CTL_Types all;
	import from UD_PortType all;
	import from UD_Types all;
	import from Osmocom_Types all;
	import from Osmocom_Types all;
	import from GSM_Types all;
	import from GSM_RR_Types all;
	import from L1CTL_PortType_CtrlFunct all;

	type record L1CTL_connect {
		charstring	path
	}

	type record L1CTL_connect_result {
		UD_Result_code	result_code optional,
		charstring	err optional
	}

	modulepar {
		charstring	m_l1ctl_sock_path := "/tmp/osmocom_l2";
	}

	function f_L1CTL_getMsgLen(in octetstring stream, inout ro_integer args) return integer {
		var integer stream_len := lengthof(stream);
		var integer len;
		if (stream_len < 2) {
			return -1;
		}
		len := 2 + oct2int(substr(stream, 0, 2));
		return len;
	}

	function f_L1CTL_FBSB(L1CTL_PT pt, Arfcn arfcn, L1ctlCcchMode ccch_mode := CCCH_MODE_COMBINED, integer rxlev_exp := 57) {
		timer T := 15.0;
		for (var integer i := 0; i < 10; i := i+1) {
			var L1ctlDlMessage dl;
			pt.send(ts_L1CTL_FBSB_REQ(arfcn, valueof(t_L1CTL_FBSB_F_ALL), 0, ccch_mode, rxlev_exp));
			T.start
			alt {
			[] pt.receive(tr_L1CTL_FBSB_CONF(0)) { return; };
			[i >= 9] pt.receive(tr_L1CTL_FBSB_CONF(?)) -> value dl {
				setverdict(fail, "FBSB Failed with non-zero return code ", dl.payload.fbsb_conf.result);
				mtc.stop;
				};
			[] pt.receive(tr_L1CTL_FBSB_CONF(?)) {
				f_sleep(1.0);
				}
			[] pt.receive { repeat; };
			[] T.timeout {
				setverdict(fail, "Timeout in FBSB") 
				mtc.stop;
				};
			}
		}
	}

	function f_L1CTL_CCCH_MODE(L1CTL_PT pt, L1ctlCcchMode ccch_mode) {
		timer T := 2.0;
		pt.send(ts_L1CTL_CCCH_MODE_REQ(ccch_mode));
		T.start;
		alt {
		[] pt.receive(tr_L1CTL_CCCH_MODE_CONF) { }
		[] pt.receive { repeat; }
		[] T.timeout {
			setverdict(fail, "Timeout in CCH_MODE");
			mtc.stop;
			}
		}
	}

	function f_L1CTL_RACH(L1CTL_PT pt, uint8_t ra, uint8_t combined := 1, uint16_t offset := 0) return GsmFrameNumber {
		var L1ctlDlMessage rc;
		var GsmFrameNumber fn;
		timer T := 2.0;
		T.start
		pt.send(ts_L1CTL_RACH_REQ(ra, combined, offset))
		alt {
			[] pt.receive(tr_L1CTL_RACH_CONF) -> value rc { fn := rc.dl_info.frame_nr };
			[] pt.receive { repeat; };
			[] T.timeout {
				setverdict(fail, "Timeout in RACH");
				mtc.stop;
				}
		}
		return fn;
	}

	function f_L1CTL_EXT_RACH(
		L1CTL_PT pt, uint16_t ra11, L1ctlRachSynchSeq seq,
		uint8_t combined := 1, uint16_t offset := 0
	) return GsmFrameNumber {
		var L1ctlDlMessage rc;
		var GsmFrameNumber fn;
		timer T := 2.0;

		T.start;
		pt.send(ts_L1CTL_EXT_RACH_REQ(ra11, seq, combined, offset));
		alt {
			[] pt.receive(tr_L1CTL_RACH_CONF) -> value rc { fn := rc.dl_info.frame_nr };
			[] pt.receive { repeat; };
			[] T.timeout {
				setverdict(fail, "Timeout in extended RACH");
				mtc.stop;
				}
		}

		return fn;
	}

	function f_L1CTL_PARAM(L1CTL_PT pt, uint8_t ta, uint8_t tx_power) {
		pt.send(ts_L1CTL_PAR_REQ(ta, tx_power));
	}

	function f_L1CTL_WAIT_IMM_ASS(L1CTL_PT pt, uint8_t ra, GsmFrameNumber rach_fn) return ImmediateAssignment {
		var L1ctlDlMessage dl;
		var GsmRrMessage rr;
		timer T := 10.0;
		T.start;
		alt {
			[] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
				rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
				log("PCH/AGCH DL RR: ", rr);
				if (match(rr, t_RR_IMM_ASS(ra, rach_fn))) {
					log("Received IMM.ASS for our RACH!");
				} else {
					repeat;
				}
			};
			[] pt.receive { repeat };
			[] T.timeout {
				setverdict(fail, "Timeout waiting for IMM ASS");
				mtc.stop;
				}
		}
		T.stop;
		return rr.payload.imm_ass;
	}

	function f_L1CTL_WAIT_IMM_ASS_TBF_DL(L1CTL_PT pt, GprsTlli tlli) return ImmediateAssignment {
		var L1ctlDlMessage dl;
		var GsmRrMessage rr;
		timer T := 10.0;
		T.start;
		alt {
			[] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
				rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
				log("PCH/AGCN DL RR: ", rr);
				if (match(rr, t_RR_IMM_ASS_TBF_DL(tlli))) {
					log("Received IMM.ASS for our TLLI!");
				} else {
					repeat;
				}
			};
			[] pt.receive { repeat };
			[] T.timeout {
				setverdict(fail, "Timeout waiting for IMM ASS");
				mtc.stop;
				}
		}
		T.stop;
		return rr.payload.imm_ass;
	}

	function f_L1CTL_TBF_CFG(L1CTL_PT pt, boolean is_uplink, TfiUsfArr tfi_usf) {
		timer T := 2.0;
		T.start;
		pt.send(ts_L1CTL_TBF_CFG_REQ(is_uplink, tfi_usf));
		alt {
			[] pt.receive(tr_L1CTL_TBF_CFG_CONF(is_uplink)) {}
			[] pt.receive { repeat };
			[] T.timeout {
				setverdict(fail, "Timeout waiting for TBF-CFG.conf");
				mtc.stop;
				};
		}
		T.stop;
	}
	function f_L1CTL_DM_EST_REQ(L1CTL_PT pt, Arfcn arfcn, RslChannelNr chan_nr, GsmTsc tsc) {
		pt.send(ts_L1CTL_DM_EST_REQ(arfcn, chan_nr, tsc));
	}

	/* Send DM_EST_REQ from parameters derived from IMM ASS */
	function f_L1CTL_DM_EST_REQ_IA(L1CTL_PT pt, ImmediateAssignment imm_ass) {
		f_L1CTL_DM_EST_REQ(pt, { false, imm_ass.chan_desc.arfcn }, imm_ass.chan_desc.chan_nr,
				   imm_ass.chan_desc.tsc);
	}

	/* Send DM_REL_REQ from parameters derived from IMM ASS */
	function f_L1CTL_DM_REL_REQ(L1CTL_PT pt, RslChannelNr chan_nr) {
		pt.send(ts_L1CTL_DM_REL_REQ(chan_nr));
	}

	function f_L1CTL_RESET(L1CTL_PT pt, L1ctlResetType res_type := L1CTL_RES_T_FULL) {
		timer T := 2.0;
		pt.send(t_L1ctlResetReq(res_type));
		T.start;
		alt {
			[] pt.receive(tr_L1CTL_MsgType(L1CTL_RESET_CONF)) { }
			[] pt.receive { repeat; }
			[] T.timeout {
				setverdict(fail, "Timeout waiting for RESET.conf");
				mtc.stop;
				}
		}
	}

	function f_L1CTL_CRYPTO_REQ(L1CTL_PT pt, RslChannelNr chan_nr, uint8_t algo, octetstring key) {
		pt.send(ts_L1CTL_CRYPTO_REQ(chan_nr, algo, key));
	}

	function f_connect_reset(L1CTL_PT pt, charstring l1ctl_sock_path := m_l1ctl_sock_path) {
		var f_UD_getMsgLen vl_f := refers(f_L1CTL_getMsgLen);
		f_L1CTL_setGetMsgLen(pt, -1, vl_f, {});
		pt.send(L1CTL_connect:{path:=l1ctl_sock_path});
		pt.receive(L1CTL_connect_result:{result_code := SUCCESS, err:=omit});
		f_L1CTL_setGetMsgLen(pt, 0, vl_f, {});
		f_L1CTL_RESET(pt);
	}

	private function L1CTL_to_UD_connect(in L1CTL_connect pin, out UD_connect pout) {
		pout.path := pin.path;
		pout.id := 0;
	} with { extension "prototype(fast)" }

	private function UD_to_L1CTL_connect_result(in UD_connect_result pin, out L1CTL_connect_result pout) {
		pout.result_code := pin.result.result_code;
		pout.err := pin.result.err;
	} with { extension "prototype(fast)" }

	private function L1CTL_to_UD_ul(in L1ctlUlMessage pin, out UD_send_data pout) {
		var L1ctlUlMessageLV msg_lv := { msg := pin };
		pout.data := enc_L1ctlUlMessageLV(msg_lv);
		pout.id := 0;
	} with { extension "prototype(fast)" }

	private function UD_to_L1CTL_dl(in UD_send_data pin, out L1ctlDlMessage pout) {
		var L1ctlDlMessageLV msg_lv := dec_L1ctlDlMessageLV(pin.data);
		pout:= msg_lv.msg;
	} with { extension "prototype(fast)" }

	type port L1CTL_PT message {
		out L1ctlUlMessage
		out L1CTL_connect
		in L1ctlDlMessage
		in L1CTL_connect_result
		in UD_listen_result
		in UD_connected
	} with { extension "user UD_PT
		out(L1ctlUlMessage -> UD_send_data: function(L1CTL_to_UD_ul);
		    L1CTL_connect -> UD_connect: function(L1CTL_to_UD_connect))
		in(UD_send_data -> L1ctlDlMessage: function(UD_to_L1CTL_dl);
		   UD_connect_result -> L1CTL_connect_result: function(UD_to_L1CTL_connect_result);
		   UD_listen_result -> UD_listen_result: simple;
		   UD_connected -> UD_connected: simple
		)" }
}
