summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-06-03 22:47:48 +0200
committerHarald Welte <laforge@osmocom.org>2021-06-09 23:51:17 +0200
commitb98a38256af8803c6c89aff326269a4f0a901947 (patch)
treed99e990970f4d69e6f6deff3a772fb156a38d7a3
parent6ab602c977891ea4a9a82019107ab74c3c5b21f1 (diff)
octsim: initial commitlaforge/octsim
-rw-r--r--octsim/OCTSIM_Tests.cfg20
-rw-r--r--octsim/OCTSIM_Tests.default10
-rw-r--r--octsim/OCTSIM_Tests.ttcn239
-rwxr-xr-xoctsim/gen_links.sh22
-rwxr-xr-xoctsim/regen_makefile.sh9
5 files changed, 300 insertions, 0 deletions
diff --git a/octsim/OCTSIM_Tests.cfg b/octsim/OCTSIM_Tests.cfg
new file mode 100644
index 00000000..79b78a3c
--- /dev/null
+++ b/octsim/OCTSIM_Tests.cfg
@@ -0,0 +1,20 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./OCTSIM_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+ConsoleMask := ERROR | WARNING | TESTCASE | USER;
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+OCTSIM_Tests.control
diff --git a/octsim/OCTSIM_Tests.default b/octsim/OCTSIM_Tests.default
new file mode 100644
index 00000000..b15f7fae
--- /dev/null
+++ b/octsim/OCTSIM_Tests.default
@@ -0,0 +1,10 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+CCID.FileMask := USER;
+ST.FileMask := USER;
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[EXECUTE]
diff --git a/octsim/OCTSIM_Tests.ttcn b/octsim/OCTSIM_Tests.ttcn
new file mode 100644
index 00000000..941cfa32
--- /dev/null
+++ b/octsim/OCTSIM_Tests.ttcn
@@ -0,0 +1,239 @@
+module OCTSIM_Tests {
+
+import from Osmocom_Types all;
+import from General_Types all;
+import from Misc_Helpers all;
+
+import from USB_PortType all;
+import from USB_Types all;
+import from USB_Templates all;
+import from USB_Component all;
+import from USB_PortTypes all;
+
+import from CCID_Types all;
+import from CCID_Templates all;
+import from CCID_Emulation all;
+
+import from SIMTRACE_Types all;
+import from SIMTRACE_Templates all;
+import from SIMTRACE_Emulation all;
+
+modulepar {
+ //USB_Device_Match mp_usb_dev_match := { vid_pid := { vid := '1d50'H, pid := '60e3'H} };
+ charstring mp_cardem_usb_path := "1-2";
+ integer mp_cardem_usb_interface := 0;
+ USB_Device_Match mp_ccid_usb_dev_match := { vid_pid := { vid := '076b'H, pid := '6622'H } };
+}
+
+type component test_CT extends Slot_CT {
+ var ST_Emulation_CT vc_ST;
+ port ST_USER_PT ST;
+ port ST_USER_PT ST_IRQ;
+
+ var CCID_Emulation_CT vc_CCID;
+};
+
+private template (value) USB_IF_Params ts_UsbPars_path(charstring path, uint8_t if_nr) := {
+ usb_dev_match := {
+ path := {
+ path := path
+ }
+ },
+ usb_if_nr := if_nr
+}
+
+private function f_init(integer slot_nr := 0) runs on test_CT
+{
+ g_slot_nr := slot_nr;
+
+ var USB_IF_Params st_usb_pars;
+ st_usb_pars := valueof(ts_UsbPars_path(mp_cardem_usb_path, mp_cardem_usb_interface));
+ vc_ST := ST_Emulation_CT.create("ST");
+ map(vc_ST:USB, system:USB);
+ connect(vc_ST:INOUT, self:ST);
+ connect(vc_ST:IRQ, self:ST_IRQ);
+ vc_ST.start(SIMTRACE_Emulation.main(st_usb_pars));
+
+ /* remove the virtual card */
+ ST.send(ts_SIMTRACE_CEMU_CARDINSERT(0));
+
+ /* TODO: set the ATR */
+
+ /* Enable the use of the IRQ endpoint to report status updates */
+ f_st_xceive(ts_SIMTRACE_CEMU_CONFIG(ts_FeatureFlags(true)),
+ tr_SIMTRACE_CEMU_CONFIG(tr_FeatureFlags(true)))
+
+
+ var CCID_Emulation_Params cep := { usb_dev_match := mp_ccid_usb_dev_match };
+ vc_CCID := CCID_Emulation_CT.create("CCID");
+ map(vc_CCID:USB, system:USB);
+ connect(vc_CCID:SLOT[slot_nr], self:CCID);
+ vc_CCID.start(CCID_Emulation.main(cep));
+ CCID.receive(CCID_Emulation_Event:{up_down:=CCID_EVENT_UP});
+
+ //activate(as_Tguard);
+ //g_Tguard.start;
+
+ /* we want to start ind powered-off state */
+ f_ccid_power_off(?);
+}
+
+function f_st_drain() runs on test_CT {
+ timer T := 0.1;
+ T.start;
+ alt {
+ [] ST.receive {
+ log("Drained msg from INOUT");
+ repeat;
+ }
+ [] ST_IRQ.receive {
+ log("Drained msg from IRQ");
+ repeat;
+ }
+ [] T.timeout { }
+ }
+}
+
+
+function f_st_xceive(template (value) SIMTRACE_PDU tx, template (present) SIMTRACE_PDU exp_rx)
+runs on test_CT return SIMTRACE_PDU {
+ var SIMTRACE_PDU rx;
+ timer T := 5.0;
+
+ ST.send(tx);
+ T.start;
+ alt {
+ [] ST.receive(exp_rx) -> value rx {
+ T.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for ", exp_rx);
+ mtc.stop;
+ }
+ }
+ return rx;
+}
+
+private altstep as_ccid_any() runs on test_CT {
+ var CCID_PDU pdu;
+ [] CCID.receive(CCID_PDU:?) -> value pdu {
+ setverdict(fail, "Received unexpected CCID ", pdu);
+ self.stop;
+ }
+ [] CCID.receive {
+ setverdict(fail, "Received unexpected non-CCID");
+ self.stop;
+ }
+}
+
+/* transceive a CCID command (send 'tx' on OUT; expect 'rx' on IN) */
+private function f_ccid_xceive(template (value) CCID_PDU tx, template (present) CCID_PDU exp_rx)
+runs on test_CT return CCID_PDU {
+ var CCID_PDU pdu;
+
+ tx.hdr.bSlot := g_slot_nr;
+ exp_rx.hdr.bSlot := g_slot_nr;
+
+ CCID.send(tx);
+ alt {
+ [] CCID.receive(exp_rx) -> value pdu {
+ return pdu;
+ }
+ [] as_ccid_any();
+ }
+ return pdu;
+}
+
+private altstep as_st_irq_wait_flags(template (present) CardEmu_StatusFlags exp_flags) runs on test_CT {
+var SIMTRACE_PDU rx_st;
+[] ST_IRQ.receive(tr_SIMTRACE_CEMU_STATUS(flags := exp_flags)) {
+ log("Expected flags received, continuing ", exp_flags);
+ }
+[] ST_IRQ.receive(tr_SIMTRACE_CEMU_STATUS) -> value rx_st {
+ log("Ignoring non-matching flags of ", rx_st);
+ repeat;
+ }
+}
+
+private template (present) CardEmu_DataFlags tr_cef_tpdu_hdr :=
+ tr_CardEmu_DataFlags(false, false, false, tpdu_hdr := true);
+
+/* transceive a TPDU, either with e rx data part, or a tx data part */
+function f_xceive(octetstring apdu, octetstring sw := '9000'O, boolean rx := true) runs on test_CT {
+ var octetstring apdu_hdr := substr(apdu, 0, 5);
+ var octetstring pb := substr(apdu, 1, 1);
+ var octetstring data := substr(apdu, 5, lengthof(apdu)-5);
+
+ CCID.send(ts_CCID_XfrBlock(g_slot_nr, apdu));
+ ST.receive(tr_SIMTRACE_CEMU_RX_DATA(tr_cef_tpdu_hdr, apdu_hdr));
+ if (rx) {
+ /* transmit procedure byte and wait for remainder */
+ ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags(pb_and_rx:=true), pb));
+ /* expect reader to transmit the remaining data */
+ ST.receive(tr_SIMTRACE_CEMU_RX_DATA(tr_CardEmu_DataFlags(final:=true), data));
+ /* respond with status word */
+ ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags(final:=true), sw));
+ /* expect reader to receive status word */
+ CCID.receive(tr_CCID_DataBlock(g_slot_nr, hdr_in := tr_CCID_HeaderIN_OK, data := sw));
+ } else {
+ /* FIXmE: doesn't work yet! */
+ /* transmit procedure byte and remainder */
+ var octetstring tx := data;
+ ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags(pb_and_tx:=true), pb & data));
+ ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags(pb_and_tx:=true, final:=true), sw));
+ /* expect reader to receive status word */
+ CCID.receive(tr_CCID_DataBlock(g_slot_nr, hdr_in := tr_CCID_HeaderIN_OK, data := tx));
+ }
+ setverdict(pass);
+}
+
+
+testcase TC_test() runs on test_CT
+{
+ var template (present) CardEmu_StatusFlags exp_flags;
+ var CCID_PDU rx_ccid;
+
+ f_init();
+ f_st_drain();
+
+ f_sleep(1.0);
+
+ /* insert the virtual card */
+ ST.send(ts_SIMTRACE_CEMU_CARDINSERT(1));
+
+ //f_ccid_xceive(ts_CCID_GetSlotStatus(0, g_slot_nr), tr_CCID_SlotStatus(slot := g_slot_nr, hdr_in := tr_CCID_HeaderIN_OK(?)));
+
+ rx_ccid := f_ccid_power_on();
+
+ if (false) {
+ /* FIXME: why does this only work on the first time after powering both devices? */
+ f_sleep(1.0);
+ /* wait for status with RESET active */
+ exp_flags := tr_CardEmu_StatusFlags(reset_active := true, clk_active := true, vcc_present := true);
+ as_st_irq_wait_flags(exp_flags);
+ }
+
+ /* wait for status with RESET inactive/released */
+ exp_flags := tr_CardEmu_StatusFlags(reset_active := false, clk_active := true, vcc_present := true);
+ as_st_irq_wait_flags(exp_flags);
+
+ if (not match(rx_ccid, tr_CCID_DataBlock(data := '3B8080811FC759'O))) {
+ setverdict(fail, "Unexpected ATR on CCID side: ", rx_ccid.u.DataBlock.abData);
+ }
+
+ for (var integer i := 0; i < 100; i := i+1) {
+ f_xceive('a0a40004023f00'O);
+ }
+ /* doesn't work yet */
+ //f_xceive('a0a40004023f00'O, rx:=false);
+ f_sleep(2.0);
+}
+
+
+
+control {
+ execute( TC_test() );
+}
+
+
+}
diff --git a/octsim/gen_links.sh b/octsim/gen_links.sh
new file mode 100755
index 00000000..c1ae16c9
--- /dev/null
+++ b/octsim/gen_links.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+#FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+#gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.USB/src
+FILES="USB_PT.cc USB_PT.hh USB_PortType.ttcn USB_PortTypes.ttcn USB_Templates.ttcn USB_Types.ttcn USB_Component.ttcn "
+FILES+="CCID_Types.ttcn CCID_Templates.ttcn CCID_Emulation.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn "
+FILES+="Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="SIMTRACE_Types.ttcn SIMTRACE_Templates.ttcn SIMTRACE_Emulation.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/octsim/regen_makefile.sh b/octsim/regen_makefile.sh
new file mode 100755
index 00000000..b258ccc3
--- /dev/null
+++ b/octsim/regen_makefile.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+FILES="*.ttcn USB_PT.cc Native_FunctionDefs.cc "
+
+../regen-makefile.sh OCTSIM_Tests.ttcn $FILES
+
+#sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lusb/' Makefile
+sed -i -e '/^LINUX_LIBS/ s/$/ `pkg-config --libs libusb-1.0`/' Makefile
+sed -i -e '/^CPPFLAGS/ s/$/ `pkg-config --cflags libusb-1.0`/' Makefile