aboutsummaryrefslogtreecommitdiffstats
path: root/simtrace/SIMTRACE_Emulation.ttcn
blob: c90760899724797055870899d4b25c6eb6f6b8a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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);
		}
	}
	}
}


}