pcu: First DL TBF hack

Change-Id: Ib3f09e125a7a4492d9072f8e9f5896eaac7ed03b
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index ef46831..12b63d6 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -16,6 +16,7 @@
 	import from LAPDm_RAW_PT all;
 	import from GPRS_Context all;
 	import from GPRS_TBF all;
+	import from L1CTL_PortType all;
 
 	modulepar {
 		BssgpConfig mp_gb_cfg := {
@@ -221,12 +222,12 @@
 		L1.send(tune_req);
 		/* FIXME: wait for confirm */
 
-		var TBF_establish_req est_req := { ra := hex2int('7B'H) };
+		var TBF_UL_establish_req est_req := { tbf_nr := 0, ra := hex2int('7B'H) };
 		L1.send(est_req);
 		T.start;
 		/* FIXME: wait for confirm */
 		alt {
-			[] L1.receive(TBF_establish_res:?) {}
+			[] L1.receive(TBF_UL_establish_res:?) {}
 			[] L1.receive { repeat; }
 			[] T.timeout {
 				setverdict(fail, "Timeout establishing UL TBF");
@@ -526,6 +527,82 @@
 		f_exit();
 	}
 
+	testcase TC_dl_tbf() runs on dummy_CT {
+		g_mmctx.imsi := '262420123456789'H;
+		g_mmctx.tlli := f_random_tlli();
+		f_init();
+
+		f_establish_dl_tbf();
+
+		f_exit();
+	}
+
+	function f_wait_tbf_dl(TbfNr tbf_nr, GprsTlli tlli) runs on dummy_CT return ImmediateAssignment {
+		var LAPDm_ph_data ph_data;
+		var GsmRrMessage rr;
+		timer T := 10.0;
+		T.start;
+		alt {
+		[] L1.receive(LAPDm_ph_data:{sacch:=?,sapi:=0,lapdm:={bbis:=?}}) -> value ph_data {
+			rr := dec_GsmRrMessage(ph_data.lapdm.bbis.payload);
+			log("PCH/AGCH DL RR: ", rr);
+			if (match(rr, t_RR_IMM_ASS_TBF_DL(tlli))) {
+				var TbfPars tbf_pars := valueof(t_TbfParsInit);
+				log("Received IMM.ASS for our TLLI!");
+				tbf_pars.tfi[rr.payload.imm_ass.pkt_chan_desc.tn] :=
+					rr.payload.imm_ass.rest_octets.hh.dl.group1.tfi_assignment;
+				L1.send(TBF_DL_establish_req:{tbf_nr, tbf_pars});
+			} else {
+				repeat;
+			}
+		}
+		[] L1.receive { repeat };
+		[] T.timeout {
+			setverdict(fail, "Timeout waiting for IMM ASS")
+			self.stop;
+			}
+		}
+		T.stop;
+		return rr.payload.imm_ass;
+	}
+
+	/* Establish an UL TBF: Tune to ARFCN, send RACH, receive AGCH, enable TBF Rx */
+	function f_establish_dl_tbf() runs on dummy_CT {
+		timer T := 5.0;
+		var BCCH_tune_req tune_req := { { false, 871 }, true };
+		L1.send(tune_req);
+		/* FIXME: wait for confirm */
+
+		/* sending a GMM PDU as DL-UNITDATA should trigger Paging + DL TBF Assignment */
+		tx_gmm('1'B, '01020304'O, c_LLC_SAPI_LLGMM);
+
+		/* Expect an IMM.ASS for PDCH on the AGCH */
+		f_wait_tbf_dl(0, g_mmctx.tlli);
+
+		var RLCMAC_ph_data_ind dl;
+		alt {
+		[] L1.receive(RLCMAC_ph_data_ind:{cs:=?, ts_nr:=?, fn:=?, block:=tr_RLCMAC_DATA_RRBP}) ->
+value dl {
+			var uint6_t tfi := dl.block.data.mac_hdr.hdr_ext.tfi;
+			var GsmFrameNumber ul_fn := f_rrbp_fn(dl.fn, dl.block.data.mac_hdr.mac_hdr.rrbp);
+			var AckNackDescription an_desc := { /* FIXME: compute this based on state */
+				final_ack := '1'B,
+				starting_seq_nr := 0,
+				receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000001'B
+			}
+			var RlcmacUlCtrlMsg ctrl_ack;
+			ctrl_ack := valueof(ts_RlcMacUlCtrl_PKT_DL_ACK(tfi, an_desc));
+			var RlcmacUlBlock ul_block := valueof(ts_RLC_UL_CTRL_ACK(ctrl_ack));
+			L1.send(ts_PH_DATA_ABS(0, CS1, dl.ts_nr, ul_fn, {false, 871}, ul_block));
+			log("Sent DL ACK: ", ul_block);
+			}
+		[] L1.receive { repeat; }
+		}
+
+		f_sleep(10.0);
+	}
+
+
 	control {
 		execute(TC_selftest_bssgp());
 		execute(TC_selftest_ns());