/* Test Port that stacks on top of L1CTL test port and performs LAPDm encoding/decoding, so the user can send
 * and receive LAPDm frames in decoded TTCN-3 data types.  This is particularly useful for sending/receiving
 * all kinds of hand-crafted LAPDm frames for testing of the remote LAPDm layer */

/* (C) 2017-2018 Harald Welte <laforge@gnumonks.org>
 * 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 LAPDm_RAW_PT {
	import from GSM_Types all;
	import from GSM_RR_Types all;
	import from Osmocom_Types all;
	import from L1CTL_Types all;
	import from L1CTL_PortType all;
	import from LAPDm_Types all;
	import from RLCMAC_Types all;

	/* request to tune to a given ARFCN and start BCCH decoding */
	type record BCCH_tune_req {
		Arfcn arfcn,
		boolean combined_ccch
	}

	/* ask for a dedicated channel to be established */
	type record DCCH_establish_req {
		uint8_t ra
	}

	type record DCCH_establish_res {
		ChannelDescription chan_desc optional,
		charstring err optional
	}

	/* directly switch to a dedicated channel (without RACH/IMM.ASS */
	type record DCCH_switch_req {
		ChannelDescription chan_desc,
		L1ctlMA ma
	}

	type record DCCH_switch_res {
		charstring err optional
	}

	type record length(8) of uint8_t TfiList;
	type record TbfPars {
		GsmArfcn	arfcn optional,
		/* Temporary Flow Identifier for each TN */
		TfiList		tfi
	}
	type record length(8) of TbfPars TbfParsPerTs;

	template TbfPars t_TbfParsInit := {
		arfcn := omit,
		tfi := { 255, 255, 255, 255, 255, 255, 255, 255 }
	}

	type record TBF_UL_establish_res {
		TbfPars pars optional,
		charstring err optional
	}

	type record DCCH_release_req {
	}

	/* PH-DATA.ind / PH-DATA.req */
	type record LAPDm_ph_data {
		boolean sacch,
		GsmSapi sapi,
		LapdmFrame lapdm
	}

	type integer TbfNr (0..7);	/* maximum of 8 concurrent TBF per direction */
	type record TBF_UL_establish_req {
		TbfNr tbf_nr,
		uint8_t ra
	}

	type record TBF_DL_establish_req {
		TbfNr tbf_nr,
		TbfPars pars
	}

	/* PH-DATA.ind / PH-DATA.req */
	type record RLCMAC_ph_data_ind {
		GprsCodingScheme cs,
		uint8_t ts_nr,
		GsmFrameNumber fn,
		RlcmacDlBlock block
	}
	type record RLCMAC_ph_data_req_dyn {
		uint8_t tbf_id,
		GprsCodingScheme cs,
		RlcmacUlBlock block
	}
	type record RLCMAC_ph_data_req_abs {
		uint8_t tbf_id,
		GprsCodingScheme cs,
		uint8_t ts_nr,
		GsmFrameNumber fn,
		Arfcn arfcn,
		RlcmacUlBlock block
	}
	type union RLCMAC_ph_data_req {
		RLCMAC_ph_data_req_dyn	dyn,
		RLCMAC_ph_data_req_abs	abs
	}

	/* port from our (internal) point of view */
	type port LAPDm_SP_PT message {
		in	BCCH_tune_req,
			DCCH_establish_req,
			DCCH_switch_req,
			DCCH_release_req,
			TBF_UL_establish_req,
			TBF_DL_establish_req,
			RLCMAC_ph_data_req,
			LAPDm_ph_data;
		out	DCCH_establish_res,
			DCCH_switch_res,
			TBF_UL_establish_res,
			RLCMAC_ph_data_ind,
			LAPDm_ph_data;
	} with {extension "internal"};

	/* port from user (external) point of view */
	type port LAPDm_PT message {
		in	DCCH_establish_res,
			DCCH_switch_res,
			TBF_UL_establish_res,
			RLCMAC_ph_data_ind,
			LAPDm_ph_data;
		out	BCCH_tune_req,
			DCCH_establish_req,
			DCCH_switch_req,
			DCCH_release_req,
			TBF_UL_establish_req,
			TBF_DL_establish_req,
			RLCMAC_ph_data_req,
			LAPDm_ph_data;
	} with {extension "internal"};

	function LAPDmStart() runs on lapdm_CT {
		f_init();
		ScanEvents();
	}

	/* TS 44.004 Figure 5.1 */
	type enumerated ph_state_enum {
		PH_STATE_NULL,
		PH_STATE_BCH,
		PH_STATE_SEARCHING_BCH,
		PH_STATE_TUNING_DCH,
		PH_STATE_DCH,
		PH_STATE_TBF
	}

	type component lapdm_CT {

		/* L1CTL port towards the bottom */
		port L1CTL_PT L1CTL;
		/* Port towards L2 */
		port LAPDm_SP_PT LAPDM_SP;

		/* physical layer state */
		var ph_state_enum ph_state := PH_STATE_NULL;

		/* channel description of the currently active DCH */
		var ChannelDescription chan_desc;

		/* last SACCH downlink L1 header we received */
		var uint5_t ms_power_lvl := 0;
		var uint8_t timing_adv := 0;

		var TbfParsPerTs g_tbf_ul;
		var TbfParsPerTs g_tbf_dl;
	};

	/* wrapper function to log state transitions */
	private function set_ph_state(ph_state_enum new_state) runs on lapdm_CT {
		log("PH-STATE ", ph_state, " -> ", new_state);
		ph_state := new_state;
	}

	private function f_init() runs on lapdm_CT {
		f_connect_reset(L1CTL);
		set_ph_state(PH_STATE_NULL);
	}

	/* release the dedicated radio channel */
	private function f_release_dcch() runs on lapdm_CT {
		L1CTL.send(ts_L1CTL_DM_REL_REQ(chan_desc.chan_nr));
		set_ph_state(PH_STATE_BCH);
	}

	/* tune to given ARFCN and start BCCH/CCCH decoding */
	private function f_tune_bcch(Arfcn arfcn, boolean combined) runs on lapdm_CT {
		var L1ctlCcchMode mode := CCCH_MODE_NON_COMBINED;
		if (combined) {
			mode := CCCH_MODE_COMBINED;
		}

		if (ph_state == PH_STATE_DCH) {
			/* release any previous DCH */
			f_release_dcch();
		} else if (ph_state == PH_STATE_TBF) {
			f_release_tbf();
		}

		set_ph_state(PH_STATE_SEARCHING_BCH);

		/* send FB/SB req to sync to cell */
		f_L1CTL_FBSB(L1CTL, arfcn, mode);
		set_ph_state(PH_STATE_BCH);
	}

	/* master function establishing a dedicated radio channel */
	private function f_establish_dcch(uint8_t ra) runs on lapdm_CT {
		var ImmediateAssignment imm_ass;
		var GsmFrameNumber rach_fn;

		/* send RACH request and obtain FN at which it was sent */
		rach_fn := f_L1CTL_RACH(L1CTL, ra);
		//if (not rach_fn) { return; }

		/* wait for receiving matching IMM ASS */
		imm_ass := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, rach_fn)
		//if (not imm_ass) { return; }
		set_ph_state(PH_STATE_TUNING_DCH);

		/* store/save channel description */
		chan_desc := imm_ass.chan_desc;

		/* send DM_EST_REQ, TODO: Mobile Allocation */
		f_L1CTL_DM_EST_REQ_IA(L1CTL, imm_ass);
		set_ph_state(PH_STATE_DCH);
	}

	/* switching directly to a dedicated channel *without RACH/IMM-ASS */
	private function f_switch_dcch(in DCCH_switch_req sw_req) runs on lapdm_CT {
		set_ph_state(PH_STATE_TUNING_DCH);
		/* store/save channel description */
		chan_desc := sw_req.chan_desc;

		/* tune the L1 to the indicated channel */
		if (chan_desc.h) {
			L1CTL.send(ts_L1CTL_DM_EST_REQ_H1(chan_desc.chan_nr,
							  chan_desc.tsc,
							  chan_desc.maio_hsn.hsn,
							  chan_desc.maio_hsn.maio,
							  sw_req.ma));
		} else {
			L1CTL.send(ts_L1CTL_DM_EST_REQ_H0(chan_desc.chan_nr,
							  chan_desc.tsc,
							  chan_desc.arfcn));
		}

		set_ph_state(PH_STATE_DCH);
	}

	/* initialize a tfi_usf array with "not used" value 255 for all TN */
	function f_TfiUsfArrInit() return TfiUsfArr {
		var TfiUsfArr tua := { 255, 255, 255, 255, 255, 255, 255, 255 };
		return tua;
	}

	/* set TFI/USF value for one given timeslot number (index) */
	function f_TfiUsfArrSet(inout TfiUsfArr a, in uint8_t idx, in uint8_t tfi_usf) {
		a[idx] := tfi_usf;
	}

	template (value) RLCMAC_ph_data_req ts_PH_DATA_ABS(uint8_t tbf_id, GprsCodingScheme cs,
							   uint8_t ts, uint32_t fn, Arfcn arfcn,
							   RlcmacUlBlock block) := {
		abs := {
			tbf_id := tbf_id,
			cs := CS1,	/* FIXME */
			ts_nr := ts,
			fn := fn,
			arfcn := arfcn,
			block := block
		}
	}

	private function f_establish_tbf(uint8_t ra) runs on lapdm_CT return boolean {
		var template GsmRrMessage imm_ass_rr;
		var ImmediateAssignment imm_ass;
		var PacketUlAssign pkt_ul_ass;
		var GsmFrameNumber rach_fn;
		var TfiUsfArr tua := f_TfiUsfArrInit();

		/* send RACH request and obtain FN at which it was sent */
		rach_fn := f_L1CTL_RACH(L1CTL, ra);

		/* wait for receiving matching IMM ASS */
		imm_ass := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, rach_fn);

		/* make sure we got *Packet* (Uplink) Immediate Assignment */
		imm_ass_rr := tr_IMM_TBF_ASS(dl := false, ra := ra, fn := rach_fn,
					     rest := tr_IaRestOctets_ULAss(?));
		if (not match(imm_ass, imm_ass_rr.payload.imm_ass)) {
			log("Failed to match Packet Immediate Assignment");
			return false;
		}

		/* decapsulate PacketUlAssign for further matching */
		pkt_ul_ass := imm_ass.rest_octets.hh.pa.uldl.ass.ul;

		/* Dynamic Block Allocation */
		if (match(pkt_ul_ass, tr_PacketUlDynAssign)) {
			set_ph_state(PH_STATE_TBF);

			/* store/save channel description */
			//chan_desc := imm_ass.chan_desc;

			/* Important: ARFCN, TN, TSC, USF, USF_GRANULARITY, CH_CODING_CMD */
			f_TfiUsfArrSet(tua, imm_ass.pkt_chan_desc.tn, pkt_ul_ass.dynamic.usf);
			f_L1CTL_TBF_CFG(L1CTL, true, tua);
			return true;
		/* FIXME: Single Block Allocation */
		} else if (match(pkt_ul_ass, tr_PacketUlSglAssign)) {
			log("Non-dynamic UL TBF assignment not supported yet");
			return false;
		} else {
			log("Failed to match Uplink Block Allocation: ", pkt_ul_ass);
			return false;
		}
	}

	private function f_release_tbf() runs on lapdm_CT {
		var TfiUsfArr tua := f_TfiUsfArrInit();
		/* send "all timeslots unused" for both UL and DL */
		f_L1CTL_TBF_CFG(L1CTL, true, tua);
		f_L1CTL_TBF_CFG(L1CTL, false, tua);
		/* L1 will then fall back to BCCH/CCCH */
		set_ph_state(PH_STATE_BCH);
	}

	/* Establish TBF / packet transfer mode */
	private altstep as_tbf_ul_est() runs on lapdm_CT {
		var TBF_UL_establish_req tbf_ul_req;
		[] LAPDM_SP.receive(TBF_UL_establish_req:?) -> value tbf_ul_req {
			var TbfNr tbf_nr := tbf_ul_req.tbf_nr;
			var TBF_UL_establish_res res;
			if (isvalue(g_tbf_ul[tbf_nr].arfcn)) {
				setverdict(fail, "Cannot establish UL TBF ID ", tbf_nr, ": BUSY");
				mtc.stop;
			}
			f_establish_tbf(tbf_ul_req.ra);
			if (ph_state == PH_STATE_TBF) {
				g_tbf_ul[tbf_nr] := valueof(t_TbfParsInit); /* FIXME: Actual TFI[s] */
				log("Established UL TBF ", tbf_nr);
				res := { pars := g_tbf_ul[tbf_nr], err := omit };
			} else {
				res := { pars := omit, err := "Unable to establish UL TBF" };
			}
			LAPDM_SP.send(res);
		}
	}

	private altstep as_tbf_dl_est() runs on lapdm_CT {
		var TBF_DL_establish_req tbf_dl_req;
		[] LAPDM_SP.receive(TBF_DL_establish_req:?) -> value tbf_dl_req {
			var TbfNr tbf_nr := tbf_dl_req.tbf_nr;
			if (isvalue(g_tbf_dl[tbf_nr].arfcn)) {
				setverdict(fail, "Cannot establish DL TBF ID ", tbf_nr, ": BUSY");
				mtc.stop;
			}
			g_tbf_dl[tbf_nr] := tbf_dl_req.pars;
			f_L1CTL_TBF_CFG(L1CTL, false, tbf_dl_req.pars.tfi);
			set_ph_state(PH_STATE_TBF);
			log("Established DL TBF ", tbf_nr, ": ", tbf_dl_req.pars);
		}
	}

	private function f_init_tbf() runs on lapdm_CT {
		var integer i;
		for (i := 0; i < 8; i := i+1) {
			g_tbf_ul[i] := valueof(t_TbfParsInit);
			g_tbf_dl[i] := valueof(t_TbfParsInit);
		}
	}

	function ScanEvents() runs on lapdm_CT {
		var L1ctlDlMessage dl;
		var BCCH_tune_req bt;
		var LAPDm_ph_data lpd;
		var RLCMAC_ph_data_ind rpdi;
		var RLCMAC_ph_data_req rpdr;
		var DCCH_establish_req est_req;
		var DCCH_switch_req sw_req;
		var DCCH_establish_res est_res;

		f_init_tbf();

		while (true) {
		if (ph_state == PH_STATE_NULL) {
			alt {
			[] LAPDM_SP.receive(BCCH_tune_req:?) -> value bt {
				f_tune_bcch(bt.arfcn, bt.combined_ccch);
			}

			[] LAPDM_SP.receive {}
			[] L1CTL.receive {}

			}
		} else if (ph_state == PH_STATE_BCH or ph_state == PH_STATE_SEARCHING_BCH) {
			alt {
			[] LAPDM_SP.receive(BCCH_tune_req:?) -> value bt {
				f_tune_bcch(bt.arfcn, bt.combined_ccch);
			}

			/* forward CCCH SAPI from L1CTL to User */
			[] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0))) -> value dl {
				lpd.sacch := false;
				lpd.sapi := 0;
				lpd.lapdm.bbis := dec_LapdmFrameBbis(dl.payload.data_ind.payload);
				LAPDM_SP.send(lpd);
			}

			/* forward BCCH SAPI from L1CTL to User */
			[] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
				lpd.sacch := false;
				lpd.sapi := 0;
				lpd.lapdm.bbis := dec_LapdmFrameBbis(dl.payload.data_ind.payload);
				LAPDM_SP.send(lpd);
			}

			/* Establish dedicated channel */
			[] LAPDM_SP.receive(DCCH_establish_req:?) -> value est_req {
				var DCCH_establish_res res;
				f_establish_dcch(est_req.ra);
				if (ph_state == PH_STATE_DCH) {
					res := { chan_desc, omit };
				} else {
					res := { omit, "Unable to esetablish DCCH" };
				}
				LAPDM_SP.send(res);
			}
			[] LAPDM_SP.receive(DCCH_switch_req:?) -> value sw_req {
				var DCCH_switch_res res;
				f_switch_dcch(sw_req);
				if (ph_state == PH_STATE_DCH) {
					res := { omit };
				} else {
					res := { "Unable to switch to DCCH" };
				}
				LAPDM_SP.send(res);
			}


			[] as_tbf_ul_est();
			[] as_tbf_dl_est();

			[] LAPDM_SP.receive {}
			[] L1CTL.receive {}

			}

		} else if (ph_state == PH_STATE_TUNING_DCH or ph_state == PH_STATE_DCH) {
			alt {

			/* decode any received DATA frames for the dedicated channel and pass them up */
			[] L1CTL.receive(tr_L1CTL_DATA_IND(chan_desc.chan_nr)) -> value dl {
				var octetstring l2;
				if (dl.dl_info.link_id.c == SACCH) {
					lpd.sacch := true;
					var octetstring l1 := substr(dl.payload.data_ind.payload, 0, 2);
					l2 := substr(dl.payload.data_ind.payload, 2,
						     lengthof(dl.payload.data_ind.payload)-2);
					ms_power_lvl := oct2int(l1[0] and4b '1F'O);
					timing_adv := oct2int(l1[1]);
					/* FIXME: how to deal with UI frames in B4 format (lo length!) */
				} else {
					lpd.sacch := false;
					l2 := dl.payload.data_ind.payload;
				}
				lpd.sapi := dl.dl_info.link_id.sapi;
				lpd.lapdm.ab := dec_LapdmFrameAB(l2);
				LAPDM_SP.send(lpd);
			}

			/* encode any LAPDm record from user and pass it on to L1CTL */
			[] LAPDM_SP.receive(LAPDm_ph_data:?) -> value lpd {
				var octetstring buf;
				var RslLinkId link_id;
				if (lpd.sacch) {
					link_id := valueof(ts_RslLinkID_SACCH(lpd.sapi));
					buf := f_pad_oct(enc_LapdmFrame(lpd.lapdm), 21, '2B'O);
					var SacchL1Header l1h := valueof(ts_SacchL1Header(ms_power_lvl,
										false, timing_adv));
					L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(chan_desc.chan_nr, link_id,
									   l1h, buf));
				} else {
					link_id := valueof(ts_RslLinkID_DCCH(lpd.sapi));
					buf := f_pad_oct(enc_LapdmFrame(lpd.lapdm), 23, '2B'O);
					L1CTL.send(ts_L1CTL_DATA_REQ(chan_desc.chan_nr, link_id, buf));
				}
			}

			/* Release dedicated channel */
			[] LAPDM_SP.receive(DCCH_release_req:?) {
				/* go back to BCCH */
				f_release_dcch();
			}

			[] LAPDM_SP.receive {}
			[] L1CTL.receive {}


			}
		} else if (ph_state == PH_STATE_TBF) {
			alt {

			/* decode + forward any blocks from L1 to L23*/
			[] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PDCH(?))) -> value dl {
				rpdi.block := dec_RlcmacDlBlock(dl.payload.data_ind.payload);
				/* FIXME: Filter based on g_tbf_dl */
				rpdi.fn := dl.dl_info.frame_nr;
				rpdi.ts_nr := dl.dl_info.chan_nr.tn;
				rpdi.cs := CS1; /* FIXME */
				log("RPDI: ", rpdi);
				LAPDM_SP.send(rpdi);
			}

			[] L1CTL.receive { }

			/* encode + forward any blocks from L23 to L1 */
			[] LAPDM_SP.receive(RLCMAC_ph_data_req:?) -> value rpdr {
				var octetstring buf;
				if (ischosen(rpdr.dyn)) {
					buf := enc_RlcmacUlBlock(rpdr.dyn.block);
					L1CTL.send(ts_L1CTL_DATA_TBF_REQ(buf, L1CTL_CS1, rpdr.dyn.tbf_id));
				} else {
					buf := enc_RlcmacUlBlock(rpdr.abs.block);
					L1CTL.send(ts_L1CTL_DATA_ABS_REQ(buf, rpdr.abs.arfcn,
									rpdr.abs.ts_nr, rpdr.abs.fn,
									L1CTL_CS1, rpdr.abs.tbf_id));
				}
			}

			[] as_tbf_ul_est();
			[] as_tbf_dl_est();

			/* FIXME: release TBF mode */
			[] LAPDM_SP.receive(DCCH_release_req:?) {
				/* go back to BCCH */
				f_release_tbf();
				f_init_tbf();
			}

			}
		}

		} /* while (1) */
	}
}
