blob: a1ca5fe5aa68487ed6b667d8a942cef91a2e060c [file] [log] [blame]
Harald Welte34b5a952019-05-27 11:54:11 +02001/* LAPDm definitions according to 3GPP TS 44.006
2 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
3 * All rights reserved.
4 *
5 * Released under the terms of GNU General Public License, Version 2 or
6 * (at your option) any later version.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
Harald Weltef6543322017-07-16 07:35:10 +020011module LAPDm_Types {
12
13 import from General_Types all;
14 import from Osmocom_Types all;
15
16 type uint3_t LapdmSapi;
17 type BIT2 LapdmSBits;
18 type BIT3 LapdmUBits;
19 type BIT2 LapdmU2Bits;
20
Harald Welte0472ab42018-03-12 15:02:26 +010021 /* 44.006 6.3.2 */
22 const boolean cr_MO_CMD := false;
23 const boolean cr_MO_RSP := true;
24 const boolean cr_MT_CMD := true;
25 const boolean cr_MT_RSP := false;
26
Harald Weltef6543322017-07-16 07:35:10 +020027 /* TS 44.006 Figure 4 */
28 type record LapdmAddressField {
29 BIT1 spare,
Harald Weltec2a5c072017-07-17 20:58:32 +020030 uint2_t lpd,
Harald Weltef6543322017-07-16 07:35:10 +020031 LapdmSapi sapi,
32 boolean c_r,
33 boolean ea
Harald Weltec2a5c072017-07-17 20:58:32 +020034 } with { variant "FIELDORDER(msb)" };
Harald Weltef6543322017-07-16 07:35:10 +020035
Harald Welte9e4725d2017-07-16 23:18:09 +020036 template LapdmAddressField tr_LapdmAddr(template LapdmSapi sapi, template boolean c_r) := {
Harald Weltef6543322017-07-16 07:35:10 +020037 spare := '0'B,
38 lpd := 0,
39 sapi := sapi,
40 c_r := c_r,
41 ea := true
42 };
43
Harald Welted879bd92018-03-12 15:01:23 +010044 template (value) LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := {
45 spare := '0'B,
46 lpd := 0,
47 sapi := sapi,
48 c_r := c_r,
49 ea := true
50 };
51
Harald Weltef6543322017-07-16 07:35:10 +020052 type record LapdmCtrlI {
Harald Welte1bbe0b72018-05-10 18:28:15 +020053 uint3_t n_r,
Harald Weltec2a5c072017-07-17 20:58:32 +020054 boolean p,
Harald Welte1bbe0b72018-05-10 18:28:15 +020055 uint3_t n_s,
56 BIT1 spare ('0'B)
57 } with { variant "FIELDORDER(msb)" };
Harald Weltef6543322017-07-16 07:35:10 +020058
59 type record LapdmCtrlS {
Harald Welte1bbe0b72018-05-10 18:28:15 +020060 uint3_t n_r,
Harald Weltec2a5c072017-07-17 20:58:32 +020061 boolean p_f,
Harald Welte1bbe0b72018-05-10 18:28:15 +020062 LapdmSBits s,
63 BIT2 spare ('01'B)
64 } with { variant "FIELDORDER(msb)" };
Harald Weltef6543322017-07-16 07:35:10 +020065
66 type record LapdmCtrlU {
Harald Welte1bbe0b72018-05-10 18:28:15 +020067 LapdmUBits u,
Harald Weltec2a5c072017-07-17 20:58:32 +020068 boolean p_f,
Harald Welte1bbe0b72018-05-10 18:28:15 +020069 LapdmU2Bits u2,
70 BIT2 spare ('11'B)
71 } with { variant "FIELDORDER(msb)" };
Harald Weltef6543322017-07-16 07:35:10 +020072
73 /* TS 44.006 Table 3 */
74 type union LapdmCtrl {
Harald Weltef6543322017-07-16 07:35:10 +020075 LapdmCtrlS s,
Harald Weltec2a5c072017-07-17 20:58:32 +020076 LapdmCtrlU u,
77 LapdmCtrlI i,
78 uint8_t other
79 } with { variant "TAG(u, spare = '11'B;
Harald Weltef6543322017-07-16 07:35:10 +020080 s, spare = '01'B;
Harald Weltec2a5c072017-07-17 20:58:32 +020081 i, spare = '0'B;
82 other, OTHERWISE)" };
83 /* )" }; */
84
85 /* TS 44.006 Table 4 */
Harald Weltef6543322017-07-16 07:35:10 +020086
Harald Welted879bd92018-03-12 15:01:23 +010087 template LapdmCtrl tr_LapdmCtrlS := {
Harald Welte1bbe0b72018-05-10 18:28:15 +020088 s := { n_r := ?, p_f := ?, s := ?, spare := '01'B }
Harald Weltef6543322017-07-16 07:35:10 +020089 };
90
Harald Welted879bd92018-03-12 15:01:23 +010091 template LapdmCtrl tr_LapdmCtrlU := {
Harald Welte1bbe0b72018-05-10 18:28:15 +020092 u := { u := ?, p_f := ?, u2 := ?, spare := '11'B }
Harald Weltef6543322017-07-16 07:35:10 +020093 };
94
95 /* TS 44.006 Table 4 */
Harald Welted879bd92018-03-12 15:01:23 +010096 template LapdmCtrl tr_LapdmCtrlI(template uint3_t nr, template uint3_t ns, template boolean p) := {
Harald Welte1bbe0b72018-05-10 18:28:15 +020097 i := { n_r := nr, p := p, n_s := ns, spare := '0'B }
98 };
99 template (value) LapdmCtrl ts_LapdmCtrlI(uint3_t nr, uint3_t ns, boolean p) := {
100 i := { n_r := nr, p := p, n_s := ns, spare := '0'B }
Harald Weltef6543322017-07-16 07:35:10 +0200101 };
102
Harald Welte1bbe0b72018-05-10 18:28:15 +0200103
Harald Welted879bd92018-03-12 15:01:23 +0100104 template LapdmCtrl tr_LapdmCtrlRR(template uint3_t nr, template boolean pf) modifies tr_LapdmCtrlS := {
Harald Welte1bbe0b72018-05-10 18:28:15 +0200105 s := { n_r := nr, p_f := pf, s := '00'B }
106 };
107 template (value) LapdmCtrl ts_LapdmCtrlRR(uint3_t nr, boolean pf) := {
108 s := { n_r := nr, p_f := pf, s := '00'B }
Harald Weltef6543322017-07-16 07:35:10 +0200109 };
110
Harald Welted879bd92018-03-12 15:01:23 +0100111 template LapdmCtrl tr_LapdmCtrlRNR(template uint3_t nr, template boolean pf) modifies tr_LapdmCtrlS := {
Harald Welte1bbe0b72018-05-10 18:28:15 +0200112 s := { n_r := nr, p_f := pf, s := '01'B }
Harald Weltef6543322017-07-16 07:35:10 +0200113 };
114
Harald Welted879bd92018-03-12 15:01:23 +0100115 template LapdmCtrl tr_LapdmCtrlREJ(template uint3_t nr, template boolean pf) modifies tr_LapdmCtrlS := {
Harald Welte1bbe0b72018-05-10 18:28:15 +0200116 s := { n_r := nr, p_f := pf, s := '10'B }
Harald Weltef6543322017-07-16 07:35:10 +0200117 };
118
Harald Welte1bbe0b72018-05-10 18:28:15 +0200119 template LapdmCtrl tr_LapdmCtrlSABM(template boolean p) := {
120 u := { u := '001'B, p_f := p, u2 := '11'B, spare := '11'B }
Harald Weltef6543322017-07-16 07:35:10 +0200121 };
Harald Welted879bd92018-03-12 15:01:23 +0100122 template (value) LapdmCtrl ts_LapdmCtrlSABM(boolean p) := {
Harald Welte1bbe0b72018-05-10 18:28:15 +0200123 u := { u := '001'B, p_f := p, u2 := '11'B, spare := '11'B }
Harald Welted879bd92018-03-12 15:01:23 +0100124 };
Harald Weltef6543322017-07-16 07:35:10 +0200125
Harald Welte1bbe0b72018-05-10 18:28:15 +0200126 template LapdmCtrl tr_LapdmCtrlDM(template boolean f) := {
127 u := { u := '000'B, p_f := f, u2 := '11'B, spare := '11'B }
Harald Weltef6543322017-07-16 07:35:10 +0200128 };
129
Harald Welte1bbe0b72018-05-10 18:28:15 +0200130 template LapdmCtrl tr_LapdmCtrlUI(template boolean p := false) := {
131 u := { u := '000'B, p_f := p, u2 := '00'B, spare := '11'B }
Harald Weltef6543322017-07-16 07:35:10 +0200132 };
Harald Welte1bbe0b72018-05-10 18:28:15 +0200133 template (value) LapdmCtrl ts_LapdmCtrlUI(boolean p := false) := {
134 u := { u := '000'B, p_f := p, u2 := '00'B, spare := '11'B }
Harald Welted879bd92018-03-12 15:01:23 +0100135 };
Harald Weltef6543322017-07-16 07:35:10 +0200136
Harald Welte1bbe0b72018-05-10 18:28:15 +0200137 template LapdmCtrl tr_LapdmCtrlDISC(template boolean p) := {
138 u := { u := '010'B, p_f := p, u2 := '00'B, spare := '11'B }
Harald Weltef6543322017-07-16 07:35:10 +0200139 };
Harald Welted879bd92018-03-12 15:01:23 +0100140 template LapdmCtrl ts_LapdmCtrlDISC(boolean p) := {
Harald Welte1bbe0b72018-05-10 18:28:15 +0200141 u := { u := '010'B, p_f := p, u2 := '00'B, spare := '11'B }
Harald Welted879bd92018-03-12 15:01:23 +0100142 };
Harald Weltef6543322017-07-16 07:35:10 +0200143
Harald Welted879bd92018-03-12 15:01:23 +0100144 template LapdmCtrl tr_LapdmCtrlUA(template boolean f) modifies tr_LapdmCtrlU := {
Harald Welte1bbe0b72018-05-10 18:28:15 +0200145 u := { u := '011'B, p_f := f, u2 := '00'B, spare := '11'B }
Harald Weltef6543322017-07-16 07:35:10 +0200146 };
Harald Welted879bd92018-03-12 15:01:23 +0100147 template (value) LapdmCtrl ts_LapdmCtrlUA(boolean f) := {
Harald Welte1bbe0b72018-05-10 18:28:15 +0200148 u := { u := '011'B, p_f := f, u2 := '00'B, spare := '11'B }
Harald Welted879bd92018-03-12 15:01:23 +0100149 };
150
151
Harald Weltef6543322017-07-16 07:35:10 +0200152
Harald Welte1bd7c322017-07-17 20:59:46 +0200153 external function dec_LapdmAddressField(in octetstring stream) return LapdmAddressField
154 with { extension "prototype(convert) decode(RAW)" };
155
156 external function dec_LapdmCtrl(in octetstring stream) return LapdmCtrl
157 with { extension "prototype(convert) decode(RAW)" };
158
159 external function dec_LapdmCtrlU(in octetstring stream) return LapdmCtrlU
160 with { extension "prototype(convert) decode(RAW)" };
161
Harald Weltef6543322017-07-16 07:35:10 +0200162 /* Formats B, Bter and B4 are used on DCCHs for frames containing an information field:
163 /* - format Bter is used on request of higher layers if and only if short L2 header type 1 is
164 * supported and a UI command is to be transmitted on SAPI 0 */
165 /* - format B4 is used for UI frames transmitted by the network on SACCH; */
166 /* - format B is applied in all other cases. */
167 /* Format Bbis is used only on BCCH, PCH, NCH, and AGCH.
168
169 /* Format B */
Harald Welted879bd92018-03-12 15:01:23 +0100170 type record LapdmFrameAB {
Harald Weltef6543322017-07-16 07:35:10 +0200171 LapdmAddressField addr,
172 LapdmCtrl ctrl,
Harald Welted879bd92018-03-12 15:01:23 +0100173 uint6_t len,
Harald Welted4ba7ff2017-07-17 21:00:48 +0200174 boolean m,
Harald Welted879bd92018-03-12 15:01:23 +0100175 uint1_t el,
176 octetstring payload /* zero-length in Frame A */
Harald Welted4ba7ff2017-07-17 21:00:48 +0200177 } with { variant (len) "LENGTHTO(payload)"
178 variant "FIELDORDER(msb)" };
Harald Weltef6543322017-07-16 07:35:10 +0200179
Harald Welted879bd92018-03-12 15:01:23 +0100180 external function enc_LapdmFrameAB(in LapdmFrameAB si) return octetstring
Harald Weltef6543322017-07-16 07:35:10 +0200181 with { extension "prototype(convert) encode(RAW)" };
Harald Welted879bd92018-03-12 15:01:23 +0100182 external function dec_LapdmFrameAB(in octetstring stream) return LapdmFrameAB
Harald Weltef6543322017-07-16 07:35:10 +0200183 with { extension "prototype(convert) decode(RAW)" };
184
Harald Weltef6543322017-07-16 07:35:10 +0200185 /* Format B4 */
186 type record LapdmFrameB4 {
187 LapdmAddressField addr,
188 LapdmCtrl ctrl,
189 octetstring payload
190 } with { variant "" };
191
192 external function enc_LapdmFrameB4(in LapdmFrameB4 si) return octetstring
193 with { extension "prototype(convert) encode(RAW)" };
194 external function dec_LapdmFrameB4(in octetstring stream) return LapdmFrameB4
195 with { extension "prototype(convert) decode(RAW)" };
196
Harald Weltec2a5c072017-07-17 20:58:32 +0200197 type record LapdmFrameBbis {
198 octetstring payload
199 } with { variant "" };
200
201 external function enc_LapdmFrameBbis(in LapdmFrameBbis si) return octetstring
202 with { extension "prototype(convert) encode(RAW)" };
203 external function dec_LapdmFrameBbis(in octetstring stream) return LapdmFrameBbis
204 with { extension "prototype(convert) decode(RAW)" };
205
206 type union LapdmFrame {
Harald Welted879bd92018-03-12 15:01:23 +0100207 LapdmFrameAB ab,
Harald Weltec2a5c072017-07-17 20:58:32 +0200208 LapdmFrameBbis bbis,
209 LapdmFrameB4 b4
210 } with { variant "" };
211
212 external function enc_LapdmFrame(in LapdmFrame si) return octetstring
213 with { extension "prototype(convert) encode(RAW)" };
214 /* automatic decoding to the generic LapdmFrame will not work, you have to call one of the
215 * type-specific decoder routines above */
216
Harald Welte0472ab42018-03-12 15:02:26 +0100217 /* SABM frame with L3 payload */
218 template (value) LapdmFrame ts_LAPDm_SABM(LapdmSapi sapi, boolean c_r, boolean p,
219 octetstring l3) := {
220 ab := {
221 addr := ts_LapdmAddr(sapi, c_r),
222 ctrl := ts_LapdmCtrlSABM(p),
223 len := 0, /* overwritten in encoder */
224 m := false,
225 el := 1,
226 payload := l3
227 }
228 }
229 template LapdmFrame tr_LAPDm_SABM(template LapdmSapi sapi, template boolean c_r,
230 template boolean p, template octetstring l3) := {
231 ab := {
232 addr := tr_LapdmAddr(sapi, c_r),
233 ctrl := tr_LapdmCtrlSABM(p),
234 len := ?,
235 m := false,
236 el := 1,
237 payload := l3
238 }
239 }
240
241 template (value) LapdmFrame ts_LAPDm_UA(LapdmSapi sapi, boolean c_r, boolean f,
242 octetstring l3) := {
243 ab := {
244 addr := ts_LapdmAddr(sapi, c_r),
245 ctrl := ts_LapdmCtrlUA(f),
246 len := 0, /* overwritten in encoder */
247 m := false,
248 el := 1,
249 payload := l3
250 }
251 }
252 template LapdmFrame tr_LAPDm_UA(template LapdmSapi sapi, template boolean c_r,
253 template boolean f, template octetstring l3) := {
254 ab := {
255 addr := tr_LapdmAddr(sapi, c_r),
256 ctrl := tr_LapdmCtrlUA(f),
257 len := ?,
258 m := false,
259 el := 1,
260 payload := l3
261 }
262 }
263
264 template LapdmFrame ts_LAPDm_DISC(LapdmSapi sapi, boolean c_r, boolean p) := {
265 ab := {
266 addr := ts_LapdmAddr(sapi, c_r),
267 ctrl := ts_LapdmCtrlDISC(p),
268 len := 0,
269 m := false,
270 el := 1,
271 payload := ''O
272 }
273 }
274 template LapdmFrame tr_LAPDm_DISC(template LapdmSapi sapi, template boolean c_r,
275 template boolean p) := {
276 ab := {
277 addr := tr_LapdmAddr(sapi, c_r),
278 ctrl := tr_LapdmCtrlDISC(p),
279 len := ?,
280 m := false,
281 el := 1,
282 payload := ''O
283 }
284 }
285
Harald Weltee613f962018-04-18 22:38:16 +0200286 template LapdmFrame ts_LAPDm_UI(LapdmSapi sapi, boolean c_r, octetstring l3) := {
Harald Welte0472ab42018-03-12 15:02:26 +0100287 ab := {
288 addr := ts_LapdmAddr(sapi, c_r),
Harald Weltee613f962018-04-18 22:38:16 +0200289 ctrl := ts_LapdmCtrlUI,
Harald Welte0472ab42018-03-12 15:02:26 +0100290 len := 0,
291 m := false,
292 el := 1,
293 payload := l3
294 }
295 }
296 template LapdmFrame tr_LAPDm_UI(template LapdmSapi sapi, template boolean c_r,
Harald Weltee613f962018-04-18 22:38:16 +0200297 template octetstring l3) := {
Harald Welte0472ab42018-03-12 15:02:26 +0100298 ab := {
299 addr := tr_LapdmAddr(sapi, c_r),
Harald Weltee613f962018-04-18 22:38:16 +0200300 ctrl := tr_LapdmCtrlUI,
Harald Welte0472ab42018-03-12 15:02:26 +0100301 len := ?,
302 m := false,
303 el := 1,
304 payload := l3
305 }
306 }
307
Harald Weltee613f962018-04-18 22:38:16 +0200308 template LapdmFrame ts_LAPDm_B4_UI(LapdmSapi sapi, boolean c_r, octetstring l3) := {
Harald Welte0472ab42018-03-12 15:02:26 +0100309 b4 := {
310 addr := ts_LapdmAddr(sapi, c_r),
Harald Weltee613f962018-04-18 22:38:16 +0200311 ctrl := ts_LapdmCtrlUI,
Harald Welte0472ab42018-03-12 15:02:26 +0100312 payload := l3
313 }
314 }
315 template LapdmFrame tr_LAPDm_B4_UI(template LapdmSapi sapi, template boolean c_r,
Harald Weltee613f962018-04-18 22:38:16 +0200316 template octetstring l3) := {
Harald Welte0472ab42018-03-12 15:02:26 +0100317 b4 := {
318 addr := tr_LapdmAddr(sapi, c_r),
Harald Weltee613f962018-04-18 22:38:16 +0200319 ctrl := tr_LapdmCtrlUI,
Harald Welte0472ab42018-03-12 15:02:26 +0100320 payload := l3
321 }
322 }
323
Harald Weltee613f962018-04-18 22:38:16 +0200324 template LapdmFrame tr_LAPDm_I(template LapdmSapi sapi, template boolean c_r,
325 template boolean p, template uint3_t nr,
326 template uint3_t ns, template octetstring l3) := {
327 ab := {
328 addr := tr_LapdmAddr(sapi, c_r),
329 ctrl := tr_LapdmCtrlI(nr, ns, p),
330 len := ?,
331 m := false,
332 el := 1,
333 payload := l3
334 }
335 }
336 template (value) LapdmFrame ts_LAPDm_I(LapdmSapi sapi, boolean c_r, boolean p, uint3_t nr,
337 uint3_t ns, octetstring l3) := {
338 ab := {
339 addr := ts_LapdmAddr(sapi, c_r),
340 ctrl := ts_LapdmCtrlI(nr, ns, p),
341 len := 0,
342 m := false,
343 el := 1,
344 payload := l3
345 }
346 }
347
348 template LapdmFrame tr_LAPDm_RR(template LapdmSapi sapi, template boolean c_r,
349 template boolean p, template uint3_t nr) := {
350 ab := {
351 addr := tr_LapdmAddr(sapi, c_r),
352 ctrl := tr_LapdmCtrlRR(nr, p),
353 len := 0,
354 m := false,
355 el := 1,
356 payload := ''O
357 }
358 }
359 template (value) LapdmFrame ts_LAPDm_RR(LapdmSapi sapi, boolean c_r,
360 boolean p, uint3_t nr) := {
361 ab := {
362 addr := ts_LapdmAddr(sapi, c_r),
363 ctrl := ts_LapdmCtrlRR(nr, p),
364 len := 0,
365 m := false,
366 el := 1,
367 payload := ''O
368 }
369 }
370
Harald Welte0472ab42018-03-12 15:02:26 +0100371
372
Harald Weltec2a5c072017-07-17 20:58:32 +0200373} with { encode "RAW"; /*variant "FIELDORDER(msb)" */}