From cc165e81753b5235945ff5226a6c99429de5b8f6 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 29 Feb 2020 11:32:50 +0100 Subject: Iniaital SIMTRACE testsuite This doesn't really do much yet in terms of test coverage, but it adds all related infrastructure Change-Id: If9fa66b6c5fbddd742ff61fa2c1345736d07accd --- Makefile | 3 +- library/General_Types.ttcn | 1 + simtrace/SIMTRACE_CARDEM_Tests.ttcn | 10 + simtrace/SIMTRACE_Emulation.ttcn | 175 ++++++++++++++++++ simtrace/SIMTRACE_Templates.ttcn | 333 +++++++++++++++++++++++++++++++++ simtrace/SIMTRACE_Tests.ttcn | 162 ++++++++++++++++ simtrace/SIMTRACE_Types.ttcn | 356 ++++++++++++++++++++++++++++++++++++ simtrace/gen_links.sh | 20 ++ simtrace/regen_makefile.sh | 9 + 9 files changed, 1068 insertions(+), 1 deletion(-) create mode 100644 simtrace/SIMTRACE_CARDEM_Tests.ttcn create mode 100644 simtrace/SIMTRACE_Emulation.ttcn create mode 100644 simtrace/SIMTRACE_Templates.ttcn create mode 100644 simtrace/SIMTRACE_Tests.ttcn create mode 100644 simtrace/SIMTRACE_Types.ttcn create mode 100755 simtrace/gen_links.sh create mode 100755 simtrace/regen_makefile.sh diff --git a/Makefile b/Makefile index 4ceacf39..90b54b36 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -SUBDIRS=bsc bsc-nat bts ggsn_tests hlr mgw msc pcu remsim sccp selftest sgsn sip stp sysinfo +SUBDIRS=bsc bsc-nat bts ggsn_tests hlr mgw msc pcu remsim sccp selftest sgsn \ + simtrace sip stp sysinfo NPROC=$(shell nproc 2>/dev/null) ifeq ($(NPROC),) diff --git a/library/General_Types.ttcn b/library/General_Types.ttcn index 924f28ba..da396b76 100644 --- a/library/General_Types.ttcn +++ b/library/General_Types.ttcn @@ -75,6 +75,7 @@ group SimpleNativeTypes { type bitstring BIT15 length(15) with { variant "FIELDLENGTH(15)" }; type bitstring BIT16 length(16) with { variant "FIELDLENGTH(16)" }; type bitstring BIT24 length(24) with { variant "FIELDLENGTH(24)" }; + type bitstring BIT27 length(27) with { variant "FIELDLENGTH(27)" }; type bitstring BIT28 length(28) with { variant "FIELDLENGTH(28)" }; type bitstring BIT29 length(29) with { variant "FIELDLENGTH(29)" }; type bitstring BIT30 length(30) with { variant "FIELDLENGTH(30)" }; diff --git a/simtrace/SIMTRACE_CARDEM_Tests.ttcn b/simtrace/SIMTRACE_CARDEM_Tests.ttcn new file mode 100644 index 00000000..0f7a31f8 --- /dev/null +++ b/simtrace/SIMTRACE_CARDEM_Tests.ttcn @@ -0,0 +1,10 @@ +module SIMTRACE_CARDEM_Tests { + +import from General_Types all; +import from Osmocom_Types all; + +import from SIMTRACE_Tests all; +import from SIMTRACE_Types all; +import from SIMTRACE_Templates all; + +} diff --git a/simtrace/SIMTRACE_Emulation.ttcn b/simtrace/SIMTRACE_Emulation.ttcn new file mode 100644 index 00000000..c9076089 --- /dev/null +++ b/simtrace/SIMTRACE_Emulation.ttcn @@ -0,0 +1,175 @@ +module SIMTRACE_Emulation { + +import from General_Types all; +import from Osmocom_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 SIMTRACE_Types all; +import from SIMTRACE_Templates all; + +/* one USB interface */ +type component ST_Emulation_CT extends USB_CT { + var integer g_ep_in; + var integer g_ep_out; + var integer g_ep_irq; + var USB_IF_Params g_pars; + + port ST_USER_PT INOUT; + port ST_USER_PT IRQ; +}; + +type port ST_USER_PT message { + inout SIMTRACE_PDU; +} with { extension "internal" }; + +/* configuration for a ST_Emulation_CT */ +type record USB_IF_Params { + USB_Device_Match usb_dev_match, + integer usb_if_nr +}; + +private const octetstring c_oct261 := '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'O; + +private function f_usb_submit_xfer(USB_endpoint ep, octetstring data := c_oct261, + USB_transfer_type ttype := USB_TRANSFER_TYPE_BULK, + integer tout_ms := 30000) runs on USB_CT +{ + var integer req_hdl := f_usb_get_req_hdl(); + var USB_transfer xfer := { + device_hdl := g_dev_hdl, + transfer_hdl := req_hdl, + endpoint := ep, + ttype := ttype, + data := data, + timeout_msec := tout_ms + }; + USB.send(xfer); +} + +/* open libusb device; claim interface; resolve endpoints; submit IN/IRQ transfers */ +function main(USB_IF_Params pars) runs on ST_Emulation_CT { + var USB_Descriptor_Node root; + var integer i_config; + var integer i; + + g_pars := pars; + + f_usb_init(g_pars.usb_dev_match); + + i_config := f_usb_get_config(); + log("USB Configuration: ", i_config); + + root := f_usb_get_desc_tree(); + log(root); + + /* iterate over list of interfaces in current configuration */ + for (i := 0; i < lengthof(root.children[i_config].children); i:=i+1) { + var USB_Descriptor_Node ifn := root.children[i_config].children[i]; + var USB_InterfaceDescriptor ifd := ifn.desc.interface; + var integer j; + if (ifd.bInterfaceNumber != g_pars.usb_if_nr) { + continue; + } + /* determine endpoints inside interface */ + for (j := 0; j < lengthof(ifn.children); j:=j+1) { + if (ischosen(ifn.children[j].desc.endpoint)) { + var USB_EndpointDescriptor epd := ifn.children[j].desc.endpoint; + select (epd.bmAttributes.TranferType) { + case (USB_EpTransfer_BULK) { + if (epd.bEndpointAddress and4b '80'O == '80'O) { + g_ep_in := oct2int(epd.bEndpointAddress); + } else { + g_ep_out := oct2int(epd.bEndpointAddress); + } + } + case (USB_EpTransfer_INTERRUPT) { + g_ep_irq := oct2int(epd.bEndpointAddress); + } + } + } + } + } + + log("USB Endpoints found: IN: ", int2oct(g_ep_in, 1), ", OUT: ", int2oct(g_ep_out, 1), + " IRQ: ", int2oct(g_ep_irq, 1)); + + f_usb_claim_interface(g_dev_hdl, g_pars.usb_if_nr); + + /* submit xfer fro IN and IRQ endpoints */ + f_usb_submit_xfer(g_ep_in); + f_usb_submit_xfer(g_ep_irq, ttype := USB_TRANSFER_TYPE_INTERRUPT); + + var USB_transfer_compl tc; + var SIMTRACE_PDU stpdu_out, stpdu_in; + while (true) { + alt { + [] USB.receive(tr_UsbXfer_compl(g_ep_out, USB_TRANSFER_TYPE_BULK, + USB_TRANSFER_COMPLETED, g_dev_hdl, ?)) { + /* do nothing; normal completion of OUT transfer */ + } + [] USB.receive(tr_UsbXfer_compl(g_ep_in, USB_TRANSFER_TYPE_BULK, + USB_TRANSFER_COMPLETED, g_dev_hdl, ?)) -> value tc { + /* Submit another IN transfer */ + f_usb_submit_xfer(g_ep_in); + stpdu_in := dec_SIMTRACE_PDU(tc.data); + INOUT.send(stpdu_in); + } + [] USB.receive(tr_UsbXfer_compl(g_ep_irq, USB_TRANSFER_TYPE_INTERRUPT, + USB_TRANSFER_COMPLETED, g_dev_hdl, ?))-> value tc { + /* Submit another IRQ transfer */ + f_usb_submit_xfer(g_ep_irq, ttype := USB_TRANSFER_TYPE_INTERRUPT); + stpdu_in := dec_SIMTRACE_PDU(tc.data); + IRQ.send(stpdu_in); + } + [] USB.receive(tr_UsbXfer_compl(g_ep_irq, USB_TRANSFER_TYPE_INTERRUPT, + USB_TRANSFER_TIMED_OUT, g_dev_hdl, ?)) -> value tc { + /* Submit another IRQ transfer */ + f_usb_submit_xfer(g_ep_irq, ttype := USB_TRANSFER_TYPE_INTERRUPT); + } + [] USB.receive(tr_UsbXfer_compl(?, ?, USB_TRANSFER_STALL, g_dev_hdl, ?)) -> value tc { + setverdict(fail, "Unexpected USB_TRANSFER_STALL on EP ", int2hex(tc.endpoint, 2)); + //mtc.stop; + /* Submit another IN transfer */ + f_usb_submit_xfer(tc.endpoint); + } + [] USB.receive(tr_UsbXfer_compl(?, ?, USB_TRANSFER_ERROR, g_dev_hdl, ?)) -> value tc { + setverdict(fail, "Unexpected USB_TRANSFER_ERROR on EP ", int2hex(tc.endpoint, 2)); + mtc.stop; + } + [] USB.receive(tr_UsbXfer_compl(?, ?, USB_TRANSFER_TIMED_OUT, g_dev_hdl, ?)) -> value tc { + setverdict(fail, "Unexpected USB_TRANSFER_TIMED_OUT on EP ", int2hex(tc.endpoint, 2)); + mtc.stop; + } + [] USB.receive(tr_UsbXfer_compl(?, ?, USB_TRANSFER_OVERFLOW, g_dev_hdl, ?)) -> value tc { + setverdict(fail, "Unexpected USB_TRANSFER_OVERFLOW on EP ", int2hex(tc.endpoint, 2)); + mtc.stop; + } + [] USB.receive(tr_UsbXfer_compl(?, ?, ?, g_dev_hdl, ?)) -> value tc { + setverdict(fail, "Unexpected USB Endpoint ", int2hex(tc.endpoint, 2)); + mtc.stop; + } + [] USB.receive(tr_UsbXfer_compl(?, ?, ?, ?, ?)) -> value tc { + setverdict(fail, "Unexpected USB Device ", tc.device_hdl); + mtc.stop; + } + [] USB.receive { + setverdict(fail, "Unexpected Message from USB"); + mtc.stop; + } + + + [] INOUT.receive(SIMTRACE_PDU:?) -> value stpdu_out { + f_usb_submit_xfer(g_ep_out, enc_SIMTRACE_PDU(stpdu_out), tout_ms := 3000); + } + } + } +} + + +} diff --git a/simtrace/SIMTRACE_Templates.ttcn b/simtrace/SIMTRACE_Templates.ttcn new file mode 100644 index 00000000..934253ed --- /dev/null +++ b/simtrace/SIMTRACE_Templates.ttcn @@ -0,0 +1,333 @@ +module SIMTRACE_Templates { + +import from SIMTRACE_Types all; +import from General_Types all; +import from Osmocom_Types all; + +/* TTCN-3 templates Osmocom SIMTRACE2 + * as found in simtrace2.git/host/include/osmocom/simtrace2/simtrace_prot.h + * + * (C) 2020 by Harald Welte + */ + + +/*********************************************************************** + * GENERAL + ***********************************************************************/ + +template (value) SIMTRACE_PDU +ts_SIMTRACE(template (value) SIMTRACE_MsgClassType msg_type, + template (value) SIMTRACE_Payload payload) := { + msg_type := msg_type, + seq_nr := 0, + slot_nr := 0, + reserved := '0000'O, + msg_len := 0, /* overwritten */ + payload := payload +} +template (present) SIMTRACE_PDU +tr_SIMTRACE(template (present) SIMTRACE_MsgClassType msg_type, + template (present) SIMTRACE_Payload payload) := { + msg_type := msg_type, + seq_nr := ?, + slot_nr := ?, + reserved := '0000'O, + msg_len := ?, + payload := payload +} + +template (value) SIMTRACE_PDU ts_SIMTRACE_BOARD_INFO := + ts_SIMTRACE(SIMTRACE_CMD_BD_BOARD_INFO, + { gen_bd_board_info := { + hardware := { + manufacturer := "", + model := "", + version := "" + }, + software := { + provider := "", + name := "", + version := "", + buildhost := "", + crc := '00000000'O + }, + max_baud_rate := 0, + cap_generic_bytes := 0, + cap_vendor_bytes := 0, + cap_generic := omit, + cap_vendor := omit + } + }); +template (present) SIMTRACE_PDU +tr_SIMTRACE_BOARD_INFO(template (present) Board_Info_Hardware hw := ?, + template (present) Board_Info_Software sw := ?, + template Generic_Capability cap_gen := *, + template Generic_Capability_Vendor cap_vend := *) := + tr_SIMTRACE(SIMTRACE_CMD_BD_BOARD_INFO, + { gen_bd_board_info := { + hardware := hw, + software := sw, + max_baud_rate := ?, + cap_generic_bytes := ?, + cap_vendor_bytes := ?, + cap_generic := cap_gen, + cap_vendor := cap_vend + } + }); + + +/*********************************************************************** + * CARD EMULATION + ***********************************************************************/ + +/* dummy flags for BD_STATUS [request] */ +template (value) CardEmu_StatusFlags ts_CardEmu_StatusFlags := { + reserved := '000'B, + reset_active := false, + card_insert := false, + rcemu_active := false, + clk_active := false, + vcc_present := false, + reserved2 := '000000000000000000000000'B +}; +template (present) CardEmu_StatusFlags +tr_CardEmu_StatusFlags(template (present) boolean reset_active := ?, + template (present) boolean card_insert := ?, + template (present) boolean clk_active := ?, + template (present) boolean vcc_present := ?, + template (present) boolean rcemu_active := ?) := { + reserved := ?, + reset_active := reset_active, + card_insert := card_insert, + rcemu_active := rcemu_active, + clk_active := clk_active, + vcc_present := vcc_present, + reserved2 := ? +}; + +template (value) CardEmu_DataFlags +ts_CardEmu_DataFlags(template (value) boolean pb_and_rx := false, + template (value) boolean pb_and_tx := false, + template (value) boolean final := false, + template (value) boolean tpdu_hdr := false) := { + reserved := '0000'B, + pb_and_rx := pb_and_rx, + pb_and_tx := pb_and_tx, + final := final, + tpdu_hdr := tpdu_hdr, + reserved2 := '000000000000000000000000'B +}; +template (present) CardEmu_DataFlags +tr_CardEmu_DataFlags(template (present) boolean pb_and_rx := ?, + template (present) boolean pb_and_tx := ?, + template (present) boolean final := ?, + template (present) boolean tpdu_hdr := ?) := { + reserved := ?, + pb_and_rx := pb_and_rx, + pb_and_tx := pb_and_tx, + final := final, + tpdu_hdr := tpdu_hdr, + reserved2 := ? +}; + + +template (value) SIMTRACE_PDU + ts_SIMTRACE_CEMU_TX_DATA(template (value) CardEmu_DataFlags flags, + template (value) octetstring data) := +ts_SIMTRACE(SIMTRACE_MSGT_DT_CEMU_TX_DATA, + { cardem_dt_txdata := { + flags := flags, + data_len := 0, /* overwritten */ + data := data } + }); + + +template (value) SIMTRACE_PDU +ts_SIMTRACE_CEMU_SET_ATR(template (value) octetstring atr) := + ts_SIMTRACE(SIMTRACE_MSGT_DT_CEMU_SET_ATR, + { cardem_dt_setatr := { atr_len := 0 /* overwritten */, atr := atr } }); + + +template (value) SIMTRACE_PDU +ts_SIMTRACE_CEMU_STATUS := + ts_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_STATUS, + { cardem_bd_status := { + flags := ts_CardEmu_StatusFlags, + voltage_mv := 0, fi := 0, di := 0, wi := 0, waiting_time := 0 + } + }); + +template (present) SIMTRACE_PDU +tr_SIMTRACE_CEMU_STATUS(template (present) CardEmu_StatusFlags flags := ?, + template (present) uint16_t voltage_mv := ?, + template (present) uint8_t fi := ?, + template (present) uint8_t di := ?, + template (present) uint8_t wi := ?, + template (present) uint32_t waiting_time := ?) := + tr_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_STATUS, + { cardem_bd_status := { + flags := flags, + voltage_mv := voltage_mv, + fi := fi, + di := di, + wi := wi, + waiting_time := waiting_time + }}); + + +template (value) SIMTRACE_PDU +ts_SIMTRACE_CEMU_CARDINSERT(uint8_t insert) := + ts_SIMTRACE(SIMTRACE_MSGT_DT_CEMU_CARDINSERT, + { cardem_dt_cardinsert := { card_insert := insert } }); + + +template (present) SIMTRACE_PDU +tr_SIMTRACE_CEMU_RX_DATA(template (present) CardEmu_DataFlags flags, + template (present) octetstring data) := + tr_SIMTRACE(SIMTRACE_MSGT_DO_CEMU_RX_DATA, + { cardem_do_rxdata := { + flags := flags, + data_len := ?, + data := data + } + }); + +template (present) SIMTRACE_PDU +tr_SIMTRACE_CEMU_PTS(template (present) octetstring req, template (present) octetstring resp) := + tr_SIMTRACE(SIMTRACE_MSGT_DO_CEMU_PTS, + { cardem_do_pts := { + pts_len := ?, + req := req, + resp := resp + } + }); + +template (value) CardEmu_FeatureFlags ts_FeatureFlags(boolean status_irq) := { + reserved := '0000000'B, + status_irq := status_irq, + reserved2 := '000000000000000000000000'B +} +template (present) CardEmu_FeatureFlags tr_FeatureFlags(template (present) boolean status_irq := ?) := { + reserved := '0000000'B, + status_irq := status_irq, + reserved2 := '000000000000000000000000'B +} + + +template (value) SIMTRACE_PDU +ts_SIMTRACE_CEMU_CONFIG(template (value) CardEmu_FeatureFlags flags) := + ts_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_CONFIG, { cardem_bd_config := { features := flags } }); + +template (present) SIMTRACE_PDU +tr_SIMTRACE_CEMU_CONFIG(template (present) CardEmu_FeatureFlags flags) := + tr_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_CONFIG, { cardem_bd_config := { features := flags } }); + + +/*********************************************************************** + * MODEM CONTROL + ***********************************************************************/ + +template (value) Modem_Status ts_ModemStatus(boolean card_inserted, boolean wwan_led) := { + reserved := '000000'B, + card_inserted := card_inserted, + wwan_led := wwan_led +} +template (present) Modem_Status tr_ModemStatus(template (present) boolean card_inserted, + template (present) boolean wwan_led) := { + reserved := ?, + card_inserted := card_inserted, + wwan_led := wwan_led +} + + + +template (value) SIMTRACE_PDU +ts_SIMTRACE_MODEM_RESET(ModemResetType rst_type := MODEM_RESET_PULSE, + uint16_t duration_msec := 400) := + ts_SIMTRACE(SIMTRACE_MSGT_DT_MODEM_RESET, + { modem_dt_reset := { + asserted := rst_type, + pulse_duration_msec := duration_msec + } + }); + +template (value) SIMTRACE_PDU +ts_SIMTRACE_MODEM_SIM_SELECT(SimSelect sim_sel) := + ts_SIMTRACE(SIMTRACE_MSGT_DT_MODEM_SIM_SELECT, + { modem_dt_sim_select := { + sim_select := sim_sel + } + }); + +template (value) SIMTRACE_PDU +ts_SIMTRACE_MODEM_STATUS := + ts_SIMTRACE(SIMTRACE_MSGT_BD_MODEM_STATUS, + { modem_bd_status := { + supported := ts_ModemStatus(false, false), + status := ts_ModemStatus(false, false), + changed := ts_ModemStatus(false, false) + } + }); +template (present) SIMTRACE_PDU +tr_SIMTRACE_MODEM_STATUS(template (present) Modem_Status supported := ?, + template (present) Modem_Status status := ?, + template (present) Modem_Status changed := ?) := + tr_SIMTRACE(SIMTRACE_MSGT_BD_MODEM_STATUS, + { modem_bd_status := { + supported := supported, + status := status, + changed := changed + } + }); + + +/*********************************************************************** + * SNIFFER + ***********************************************************************/ + +template (present) SIMTRACE_PDU +tr_SIMTRACE_SNIFF_CHANGE(template (present) Sniff_Flags flags) := + tr_SIMTRACE(SIMTRACE_MSGT_SNIFF_CHANGE, + { sniff_do_change := { flags := flags } }); + +template (present) SIMTRACE_PDU +tr_SIMTRACE_SNIFF_FIDI(template (present) uint8_t fidi := ?) := + tr_SIMTRACE(SIMTRACE_MSGT_SNIFF_FIDI, + { sniff_do_fidi := { fidi := fidi } }); + +template (present) SIMTRACE_PDU +tr_SIMTRACE_SNIFF_ATR(template (present) octetstring data, + template (present) Sniff_Flags flags := ?) := + tr_SIMTRACE(SIMTRACE_MSGT_SNIFF_FIDI, + { sniff_do_atr := { + flags := flags, + data_len := ?, + data := data + } + }); + +template (present) SIMTRACE_PDU +tr_SIMTRACE_SNIFF_PPS(template (present) octetstring data, + template (present) Sniff_Flags flags := ?) := + tr_SIMTRACE(SIMTRACE_MSGT_SNIFF_PPS, + { sniff_do_atr := { + flags := flags, + data_len := ?, + data := data + } + }); + +template (present) SIMTRACE_PDU +tr_SIMTRACE_SNIFF_TPDU(template (present) octetstring data, + template (present) Sniff_Flags flags := ?) := + tr_SIMTRACE(SIMTRACE_MSGT_SNIFF_TPDU, + { sniff_do_atr := { + flags := flags, + data_len := ?, + data := data + } + }); + + + +} diff --git a/simtrace/SIMTRACE_Tests.ttcn b/simtrace/SIMTRACE_Tests.ttcn new file mode 100644 index 00000000..90ac9865 --- /dev/null +++ b/simtrace/SIMTRACE_Tests.ttcn @@ -0,0 +1,162 @@ +module SIMTRACE_Tests { + +import from General_Types all; +import from Osmocom_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 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} }; + USB_Device_Match mp_usb_dev_match := { vid_pid := { vid := '1d50'H, pid := '4004'H} }; + charstring mp_usb_path := "1-2.4.4"; + integer mp_usb_interface := 0; +} + +//private const integer NR_IF := 2; + +type component Test_CT { + var ST_Emulation_CT vc_ST; + port ST_USER_PT ST; + port ST_USER_PT ST_IRQ; +}; + +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 +} + +function f_init(USB_IF_Params pars) runs on Test_CT { + 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(pars)); +} + +function f_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_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; +} + +testcase TC_test() runs on Test_CT { + + var USB_IF_Params pars := valueof(ts_UsbPars_path(mp_usb_path, mp_usb_interface)); + f_init(pars); + f_drain(); + + /* Enable the use of the IRQ endpoint to report status updates */ + f_xceive(ts_SIMTRACE_CEMU_CONFIG(ts_FeatureFlags(true)), + tr_SIMTRACE_CEMU_CONFIG(tr_FeatureFlags(true))) + + /* Choose "remote" SIM */ + ST.send(ts_SIMTRACE_MODEM_SIM_SELECT(SIM_SELECT_REMOTE)); + /* Trigger modem reset pulse */ + ST.send(ts_SIMTRACE_MODEM_RESET); + + f_drain(); + + var SIMTRACE_PDU rx; + while (true) { + /* receive TPDU header */ + ST.receive(tr_SIMTRACE_CEMU_RX_DATA(tr_CardEmu_DataFlags(tpdu_hdr:=true), ?)) -> value rx; + var octetstring apdu_hdr := rx.payload.cardem_do_rxdata.data; + /* send PB and request further Rx (command bytes) */ + ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags(pb_and_rx:=true), apdu_hdr[1])); + /* receive remaining data from reader */ + ST.receive(tr_SIMTRACE_CEMU_RX_DATA(tr_CardEmu_DataFlags(final:=true), ?)); + ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags(pb_and_tx:=true), '9000'O)); + } + + f_sleep(100.0); + + +} + +/* Test how firmware reacts on overly-long message (OS#4429, OS#4428) */ +testcase TC_long_out() runs on Test_CT { + var USB_IF_Params pars := valueof(ts_UsbPars_path(mp_usb_path, mp_usb_interface)); + f_init(pars); + f_drain(); + + ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags, f_rnd_octstring(300))); + f_sleep(5.0); + /* FIXME: how to verify the device did not reset itself? */ +} + + +/* flood the OUT endpoint with 1000 messages; much more than the firmware can handle */ +testcase TC_flood_out() runs on Test_CT { + var USB_IF_Params pars := valueof(ts_UsbPars_path(mp_usb_path, mp_usb_interface)); + f_init(pars); + f_drain(); + + var integer i; + for (i := 0; i < 1000; i := i+1) { + ST.send(ts_SIMTRACE_CEMU_TX_DATA(ts_CardEmu_DataFlags, f_rnd_octstring(10))); + } + f_sleep(5.0); + /* FIXME: how to verify the device is still responsive? */ +} + + +testcase TC_selftest() runs on Test_CT { + const octetstring c_cemu_sim_rem := '020200000000090001'O; + const octetstring c_cemu_rx := '010600000000130001000000050000A4000402'O; + /* 0106000000001300 + 01000000 + 0500 + 00A4000402 + */ + log(dec_SIMTRACE_PDU(c_cemu_rx)); +} + + + + + + +} diff --git a/simtrace/SIMTRACE_Types.ttcn b/simtrace/SIMTRACE_Types.ttcn new file mode 100644 index 00000000..7b1c8577 --- /dev/null +++ b/simtrace/SIMTRACE_Types.ttcn @@ -0,0 +1,356 @@ +module SIMTRACE_Types { + +/* TTCN-3 data types with TITAN RAW codec annotations for Osmocom SIMTRACE2 + * as found in simtrace2.git/host/include/osmocom/simtrace2/simtrace_prot.h + * + * (C) 2020 by Harald Welte + */ + +import from General_Types all; +import from Osmocom_Types all; + +type integer u16le_t (0..65535) with { variant "unsigned 16 bit" variant "BYTEORDER(first)" }; +type integer u32le_t (0..4294967295) with { variant "unsigned 32 bit" variant "BYTEORDER(first)" }; +type charstring CHAR32 length (0..32) with { variant "FIELDLENGTH(32)" }; + +type enumerated SIMTRACE_MsgClassType { + /* SIMTRACE_MSGC_GENERIC */ + SIMTRACE_CMD_DO_ERROR ('0000'H), + SIMTRACE_CMD_BD_BOARD_INFO ('0001'H), + + /* SIMTRACE_MSGC_CARDEM */ + SIMTRACE_MSGT_DT_CEMU_TX_DATA ('0101'H), + SIMTRACE_MSGT_DT_CEMU_SET_ATR ('0102'H), + SIMTRACE_MSGT_BD_CEMU_STATS ('0103'H), + SIMTRACE_MSGT_BD_CEMU_STATUS ('0104'H), + SIMTRACE_MSGT_DT_CEMU_CARDINSERT ('0105'H), + SIMTRACE_MSGT_DO_CEMU_RX_DATA ('0106'H), + SIMTRACE_MSGT_DO_CEMU_PTS ('0107'H), + SIMTRACE_MSGT_BD_CEMU_CONFIG ('0108'H), + + /* SIMTRACE_MSGC_MODEM */ + SIMTRACE_MSGT_DT_MODEM_RESET ('0201'H), + SIMTRACE_MSGT_DT_MODEM_SIM_SELECT ('0202'H), + SIMTRACE_MSGT_BD_MODEM_STATUS ('0203'H), + + /* SIMTRACE_MSGC_SNIFF */ + SIMTRACE_MSGT_SNIFF_CHANGE ('0300'H), + SIMTRACE_MSGT_SNIFF_FIDI ('0301'H), + SIMTRACE_MSGT_SNIFF_ATR ('0302'H), + SIMTRACE_MSGT_SNIFF_PPS ('0303'H), + SIMTRACE_MSGT_SNIFF_TPDU ('0304'H) +} with { variant "FIELDLENGTH(16)" variant "BYTEORDER(last)" }; + +type record SIMTRACE_PDU { + SIMTRACE_MsgClassType msg_type, + uint8_t seq_nr, + uint8_t slot_nr, + OCT2 reserved, + u16le_t msg_len, + SIMTRACE_Payload payload + /* payload */ +} with { + variant (msg_len) "LENGTHTO(msg_type,seq_nr,slot_nr,reserved,msg_len,payload)" + variant (payload) "CROSSTAG( + gen_do_error, msg_type = SIMTRACE_CMD_DO_ERROR; + gen_bd_board_info, msg_type = SIMTRACE_CMD_BD_BOARD_INFO; + + cardem_dt_txdata, msg_type = SIMTRACE_MSGT_DT_CEMU_TX_DATA; + cardem_dt_setatr, msg_type = SIMTRACE_MSGT_DT_CEMU_SET_ATR; + /* FIXME: stats */ + cardem_bd_status, msg_type = SIMTRACE_MSGT_BD_CEMU_STATUS; + cardem_dt_cardinsert, msg_type = SIMTRACE_MSGT_DT_CEMU_CARDINSERT; + cardem_do_rxdata, msg_type = SIMTRACE_MSGT_DO_CEMU_RX_DATA; + cardem_do_pts, msg_type = SIMTRACE_MSGT_DO_CEMU_PTS; + cardem_bd_config, msg_type = SIMTRACE_MSGT_BD_CEMU_CONFIG; + + modem_dt_reset, msg_type = SIMTRACE_MSGT_DT_MODEM_RESET; + modem_dt_sim_select, msg_type = SIMTRACE_MSGT_DT_MODEM_SIM_SELECT; + modem_bd_status, msg_type = SIMTRACE_MSGT_BD_MODEM_STATUS; + + sniff_do_change, msg_type = SIMTRACE_MSGT_SNIFF_CHANGE; + sniff_do_fidi, msg_type = SIMTRACE_MSGT_SNIFF_FIDI; + sniff_do_atr, msg_type = SIMTRACE_MSGT_SNIFF_ATR; + sniff_do_pps, msg_type = SIMTRACE_MSGT_SNIFF_PPS; + sniff_do_tpdu, msg_type = SIMTRACE_MSGT_SNIFF_TPDU; + other, OTHERWISE; + )" +}; + +external function enc_SIMTRACE_PDU(in SIMTRACE_PDU pdu) return octetstring +with { extension "prototype(convert)" extension "encode(RAW)" }; + +external function dec_SIMTRACE_PDU(in octetstring stream) return SIMTRACE_PDU +with { extension "prototype(convert)" extension "decode(RAW)" }; + +type union SIMTRACE_Payload { + Generic_DO_Error gen_do_error, + Generic_BD_BoardInfo gen_bd_board_info, + + CardEmu_DT_TxData cardem_dt_txdata, + CardEmu_DT_SetAtr cardem_dt_setatr, + CardEmu_BD_Status cardem_bd_status, + Cardemu_DT_CardInsert cardem_dt_cardinsert, + CardEmu_DO_RxData cardem_do_rxdata, + CardEmu_DO_Pts cardem_do_pts, + CardEmu_BD_Config cardem_bd_config, + + Modem_DT_Reset modem_dt_reset, + Modem_DT_SimSelect modem_dt_sim_select, + Modem_BD_Status modem_bd_status, + + Sniff_DO_Change sniff_do_change, + Sniff_DO_FiDi sniff_do_fidi, + Sniff_DO_Data sniff_do_atr, + Sniff_DO_Data sniff_do_pps, + Sniff_DO_Data sniff_do_tpdu, + + octetstring other +}; + +/*********************************************************************** + * GENERIC + ***********************************************************************/ + +/* SIMTRACE_CMD_DO_ERROR */ +type record Generic_DO_Error { + uint8_t severity, + uint8_t subsystem, + u16le_t code, + uint8_t msg_len, + charstring msg +} with { + variant (msg_len) "LENGTHTO(msg)" +}; + +type record Generic_Capability_Vendor { + /* Can erase a peer SAM3 controller */ + boolean sysmo_qmod_erase_peer, + /* Can read/write an attached EEPROM */ + boolean sysmo_qmod_rw_eeprom, + /* can reset an attached USB hub */ + boolean sysmo_qmod_reset_hub +}; + +type record Generic_Capability { + /* compatible with 5V SIM card interface */ + boolean cap_volt_5v, + /* compatible with 3V SIM card interface */ + boolean cap_volt_3v, + /* compatible with 1.8V SIM card interface */ + boolean cap_volt_1v8, + boolean cap_led_1, + boolean cap_led_2, + /* Has Single-Pole Dual-Throw (local/remote SIM) */ + boolean cap_spdt, + /* Has Bus-Switch (trace / MITM) */ + boolean cap_bus_switch, + /* Can read VSIM via ADC */ + boolean cap_vsim_adc, + /* Can read temperature via ADC */ + boolean cap_temp_adc, + /* Supports DFU for firmware update */ + boolean cap_dfu, + /* Supports Ctrl EP command for erasing flash / return to SAM-BA */ + boolean cap_erase_flash, + /* Can read the status of card insert contact */ + boolean cap_read_card_det, + /* Can control the status of a simulated card insert */ + boolean cap_assert_card_det, + /* Can toggle the hardware reset of an attached modem */ + boolean cap_assert_modem_rst +}; + +type record Board_Info_Hardware { + CHAR32 manufacturer, + CHAR32 model, + CHAR32 version +}; + +type record Board_Info_Software { + CHAR32 provider, + CHAR32 name, + CHAR32 version, + CHAR32 buildhost, + OCT4 crc +}; + +type record Generic_BD_BoardInfo { + Board_Info_Hardware hardware, + Board_Info_Software software, + u32le_t max_baud_rate, + uint8_t cap_generic_bytes, + uint8_t cap_vendor_bytes, + Generic_Capability cap_generic optional, + Generic_Capability_Vendor cap_vendor optional +} with { + variant (cap_generic_bytes) "LENGTHTO(cap_generic)" + variant (cap_vendor_bytes) "LENGTHTO(cap_vendor)" +}; + + +/*********************************************************************** + * CARD EMULATOR / FORWARDER + ***********************************************************************/ + +/* CEMU_USB_MSGT_DT_CARDINSERT */ +type record Cardemu_DT_CardInsert { + uint8_t card_insert +}; + +/* CEMU_USB_MSGT_DT_SET_ATR */ +type record CardEmu_DT_SetAtr { + uint8_t atr_len, + octetstring atr +} with { + variant (atr_len) "LENGTHTO(atr)" +}; + +type record CardEmu_DataFlags { + /* First octet here is last octet of little-endian encoded uint32_t */ + BIT4 reserved, + /* indicates a PB is present and we should continue with RX */ + boolean pb_and_rx, + /* indicates a PB is present and we should continue with TX */ + boolean pb_and_tx, + /* indicates last part of transmission in this direction */ + boolean final, + /* indicates a TPDU header is present in this message */ + boolean tpdu_hdr, + BIT24 reserved2 +} with { variant "BITORDER(msb)" }; + +/* CEMU_USB_MSGT_DT_TX_DATA */ +type record CardEmu_DT_TxData { + CardEmu_DataFlags flags, + u16le_t data_len, + octetstring data +} with { + variant (data_len) "LENGTHTO(data)" +}; + +/* CEMU_USB_MSGT_DO_RX_DATA */ +type record CardEmu_DO_RxData { + CardEmu_DataFlags flags, + u16le_t data_len, + octetstring data +} with { + variant (data_len) "LENGTHTO(data)" +}; + +type record CardEmu_StatusFlags { + /* First octet here is last octet of little-endian encoded uint32_t */ + BIT3 reserved, + boolean reset_active, + boolean card_insert, + boolean rcemu_active, + boolean clk_active, + boolean vcc_present, + BIT24 reserved2 +}; + +/* CEMU_USB_MSGT_BD_STATUS */ +type record CardEmu_BD_Status { + CardEmu_StatusFlags flags, + u16le_t voltage_mv, + uint8_t fi, + uint8_t di, + uint8_t wi, + u32le_t waiting_time +}; + +/* CEMU_USB_MSGT_DO_PTS */ +type record CardEmu_DO_Pts { + uint8_t pts_len, + OCT6 req, + OCT6 resp +}; + +type record CardEmu_FeatureFlags { + BIT7 reserved, + boolean status_irq, + BIT24 reserved2 +}; + +type record CardEmu_BD_Config { + CardEmu_FeatureFlags features +}; + +/*********************************************************************** + * MODEM CONTROL + ***********************************************************************/ + +type enumerated ModemResetType { + MODEM_RESET_RELEASE (0), + MODEM_RESET_ASSERT (1), + MODEM_RESET_PULSE (2) +} with { variant "FIELDLENGTH(8)" }; + +/* SIMTRACE_MSGT_DT_MODEM_RESET */ +type record Modem_DT_Reset { + ModemResetType asserted, + u16le_t pulse_duration_msec +}; + +type enumerated SimSelect { + SIM_SELECT_LOCAL (0), + SIM_SELECT_REMOTE (1) +} with { variant "FIELDLENGTH(8)" }; + +/* SIMTRACE_MSGT_DT_MODEM_SIM_SELECT */ +type record Modem_DT_SimSelect { + SimSelect sim_select +}; + +type record Modem_Status { + BIT6 reserved, + boolean card_inserted, + boolean wwan_led +}; + +/* SIMTRACE_MSGT_BD_MODEM_STATUS */ +type record Modem_BD_Status { + Modem_Status supported, + Modem_Status status, + Modem_Status changed +}; + +/*********************************************************************** + * SNIFF + ***********************************************************************/ + +type record Sniff_Flags { + /* First octet here is last octet of little-endian encoded uint32_t */ + boolean error_checksum, + boolean error_malformed, + boolean error_incomplete, + boolean timeout_wt, + boolean reset_deassert, + boolean reset_assert, + boolean card_eject, + boolean card_insert, + BIT24 reserved +}; + +/* SIMTRACE_MSGT_SNIFF_CHANGE */ +type record Sniff_DO_Change { + Sniff_Flags flags +}; + +/* SIMTRACE_MSGT_SNIFF_FIDI */ +type record Sniff_DO_FiDi { + uint8_t fidi +}; + +/* SIMTRACE_MSGT_SNIFF_ATR, PPS, TPDU */ +type record Sniff_DO_Data { + Sniff_Flags flags, + u16le_t data_len, + octetstring data +} with { + variant (data_len) "LENGTHTO(data)" +}; + + + +} with { encode "RAW"; variant "FIELDORDER(msb)" }; diff --git a/simtrace/gen_links.sh b/simtrace/gen_links.sh new file mode 100755 index 00000000..72787b90 --- /dev/null +++ b/simtrace/gen_links.sh @@ -0,0 +1,20 @@ +#!/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 " +gen_links $DIR $FILES + +DIR=../library +FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn " +FILES+="Native_Functions.ttcn Native_FunctionDefs.cc " +gen_links $DIR $FILES + +ignore_pp_results diff --git a/simtrace/regen_makefile.sh b/simtrace/regen_makefile.sh new file mode 100755 index 00000000..3f2d4727 --- /dev/null +++ b/simtrace/regen_makefile.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +FILES="*.ttcn USB_PT.cc Native_FunctionDefs.cc " + +../regen-makefile.sh SIMTRACE_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 -- cgit v1.2.3