remsim: Integrate VPCD test port into RemsimBankd_Tests.ttcn

VPCD (specifically ifd-vpcd) is an ifd-handler (reader driver)
for a virtual smart card reader integrated with pcsc-lite.  It is
part of the virtualsmartcard project.   Using this ifd-vpcd, we
can implementa virtual smart card reader beneath osmo-remsim-bankd,
which allows us to implement both the smart card [reader] below
osmo-remsim-bankd as well as the osmo-remsim-server + client above
osmo-remsim-bankd - in other words a fully virtualized test fixture for
bankd.

Change-Id: I967f2d526f4ef1278bd2ac1d590a8dce732379d5
diff --git a/remsim/RemsimBankd_Tests.ttcn b/remsim/RemsimBankd_Tests.ttcn
index e9e3b31..fd3f907 100644
--- a/remsim/RemsimBankd_Tests.ttcn
+++ b/remsim/RemsimBankd_Tests.ttcn
@@ -17,6 +17,10 @@
 import from IPA_Emulation all;
 import from Misc_Helpers all;
 
+import from VPCD_Types all;
+import from VPCD_CodecPort all;
+import from VPCD_Adapter all;
+
 import from RSPRO all;
 import from RSRES all;
 import from RSPRO_Types all;
@@ -30,7 +34,7 @@
 
 /* We implement a RSPRO server to simulate the remsim-server and a
    RSPRO client to simulate a remsim-client connecting to bankd */
-type component bankd_test_CT extends rspro_server_CT, rspro_client_CT {
+type component bankd_test_CT extends rspro_server_CT, rspro_client_CT, VPCD_Adapter_CT {
 }
 
 private function f_init(boolean start_client := false) runs on bankd_test_CT {
@@ -332,11 +336,43 @@
 	Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
 }
 
+private altstep as_vpcd() runs on VPCD_Adapter_CT {
+	[] VPCD.receive(tr_VPCD_Recv(g_vpcd_conn_id, tr_VPCD_CTRL_ATR)) {
+		f_vpcd_send(ts_VPCD_DATA('3B9F96801FC78031A073BE21136743200718000001A5'O));
+		repeat;
+		}
+	[] VPCD.receive(tr_VPCD_Recv(g_vpcd_conn_id, tr_VPCD_CTRL_OFF)) {
+		repeat;
+		}
+	[] VPCD.receive(tr_VPCD_Recv(g_vpcd_conn_id, tr_VPCD_CTRL_ON)) {
+		repeat;
+		}
+}
+
+/* transceive a TPDU from modem to card (and back) */
+function f_rspro_xceive_mdm2card_vpcd(integer idx, BankSlot bs, template (value) octetstring data,
+				 template (value) TpduFlags flags, template (value) octetstring res) runs on bankd_test_CT return octetstring {
+	var RsproPDU rx;
+	RSPRO[idx].send(ts_RSPRO_TpduModemToCard(rspro[idx].rspro_client_slot, bs, flags, data));
+	f_vpcd_exp(tr_VPCD_DATA(data));
+	f_vpcd_send(ts_VPCD_DATA(res));
+	rx := f_rspro_exp(tr_RSPRO_TpduCardToModem(bs, rspro[idx].rspro_client_slot, ?, ?));
+	if (rx.msg.tpduCardToModem.data != valueof(res)) {
+		setverdict(fail, "Expected ", res, " from card, but got ", rx.msg.tpduCardToModem.data);
+	}
+	return rx.msg.tpduCardToModem.data;
+}
+
+
 /* first add mapping, then connect matching client and exchange some TPDUs */
 testcase TC_createMapping_exchangeTPDU() runs on bankd_test_CT {
 	/* FIXME: this would only be done in f_init_client(), but we need it before */
 	rspro[0].rspro_client_slot := { clientId := 23+0, slotNr := 0 };
 
+	VPCD_Adapter.f_connect();
+	activate(as_vpcd());
+	f_sleep(2.0);
+
 	f_init();
 	as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
 	f_rspro_srv_reset_state(ok);
@@ -354,7 +390,7 @@
 	var TpduFlags f := {tpduHeaderPresent:=true, finalPart:=true, procByteContinueTx:=false,
 			    procByteContinueRx:=false};
 	for (var integer i := 0; i < 10; i:=i+1) {
-		f_rspro_xceive_mdm2card(0, bs, 'A0A40000023F00'O, f);
+		f_rspro_xceive_mdm2card_vpcd(0, bs, 'A0A40000023F00'O, f, '9000'O);
 	}
 	Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
 }