| /* LAPDm definitions according to 3GPP TS 44.006 |
| * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org> |
| * All rights reserved. |
| * |
| * Released under the terms of GNU General Public License, Version 2 or |
| * (at your option) any later version. |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| |
| module LAPDm_Types { |
| |
| import from General_Types all; |
| import from Osmocom_Types all; |
| |
| type uint3_t LapdmSapi; |
| type BIT2 LapdmSBits; |
| type BIT3 LapdmUBits; |
| type BIT2 LapdmU2Bits; |
| |
| /* 44.006 6.3.2 */ |
| const boolean cr_MO_CMD := false; |
| const boolean cr_MO_RSP := true; |
| const boolean cr_MT_CMD := true; |
| const boolean cr_MT_RSP := false; |
| |
| /* TS 44.006 Figure 4 */ |
| type record LapdmAddressField { |
| BIT1 spare, |
| uint2_t lpd, |
| LapdmSapi sapi, |
| boolean c_r, |
| boolean ea |
| } with { variant "FIELDORDER(msb)" }; |
| |
| template LapdmAddressField tr_LapdmAddr(template LapdmSapi sapi, template boolean c_r) := { |
| spare := '0'B, |
| lpd := 0, |
| sapi := sapi, |
| c_r := c_r, |
| ea := true |
| }; |
| |
| template (value) LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := { |
| spare := '0'B, |
| lpd := 0, |
| sapi := sapi, |
| c_r := c_r, |
| ea := true |
| }; |
| |
| type record LapdmCtrlI { |
| uint3_t n_r, |
| boolean p, |
| uint3_t n_s, |
| BIT1 spare ('0'B) |
| } with { variant "FIELDORDER(msb)" }; |
| |
| type record LapdmCtrlS { |
| uint3_t n_r, |
| boolean p_f, |
| LapdmSBits s, |
| BIT2 spare ('01'B) |
| } with { variant "FIELDORDER(msb)" }; |
| |
| type record LapdmCtrlU { |
| LapdmUBits u, |
| boolean p_f, |
| LapdmU2Bits u2, |
| BIT2 spare ('11'B) |
| } with { variant "FIELDORDER(msb)" }; |
| |
| /* TS 44.006 Table 3 */ |
| type union LapdmCtrl { |
| LapdmCtrlS s, |
| LapdmCtrlU u, |
| LapdmCtrlI i, |
| uint8_t other |
| } with { variant "TAG(u, spare = '11'B; |
| s, spare = '01'B; |
| i, spare = '0'B; |
| other, OTHERWISE)" }; |
| /* )" }; */ |
| |
| /* TS 44.006 Table 4 */ |
| |
| template LapdmCtrl tr_LapdmCtrlS := { |
| s := { n_r := ?, p_f := ?, s := ?, spare := '01'B } |
| }; |
| |
| template LapdmCtrl tr_LapdmCtrlU := { |
| u := { u := ?, p_f := ?, u2 := ?, spare := '11'B } |
| }; |
| |
| /* TS 44.006 Table 4 */ |
| template LapdmCtrl tr_LapdmCtrlI(template uint3_t nr, template uint3_t ns, template boolean p) := { |
| i := { n_r := nr, p := p, n_s := ns, spare := '0'B } |
| }; |
| template (value) LapdmCtrl ts_LapdmCtrlI(uint3_t nr, uint3_t ns, boolean p) := { |
| i := { n_r := nr, p := p, n_s := ns, spare := '0'B } |
| }; |
| |
| |
| template LapdmCtrl tr_LapdmCtrlRR(template uint3_t nr, template boolean pf) modifies tr_LapdmCtrlS := { |
| s := { n_r := nr, p_f := pf, s := '00'B } |
| }; |
| template (value) LapdmCtrl ts_LapdmCtrlRR(uint3_t nr, boolean pf) := { |
| s := { n_r := nr, p_f := pf, s := '00'B, spare := '01'B } |
| }; |
| |
| template LapdmCtrl tr_LapdmCtrlRNR(template uint3_t nr, template boolean pf) modifies tr_LapdmCtrlS := { |
| s := { n_r := nr, p_f := pf, s := '01'B } |
| }; |
| |
| template LapdmCtrl tr_LapdmCtrlREJ(template uint3_t nr, template boolean pf) modifies tr_LapdmCtrlS := { |
| s := { n_r := nr, p_f := pf, s := '10'B } |
| }; |
| template (value) LapdmCtrl ts_LapdmCtrlREJ(uint3_t nr, boolean pf) := { |
| s := { n_r := nr, p_f := pf, s := '10'B, spare := '01'B } |
| }; |
| |
| |
| template LapdmCtrl tr_LapdmCtrlSABM(template boolean p) := { |
| u := { u := '001'B, p_f := p, u2 := '11'B, spare := '11'B } |
| }; |
| template (value) LapdmCtrl ts_LapdmCtrlSABM(boolean p) := { |
| u := { u := '001'B, p_f := p, u2 := '11'B, spare := '11'B } |
| }; |
| |
| template LapdmCtrl tr_LapdmCtrlDM(template boolean f) := { |
| u := { u := '000'B, p_f := f, u2 := '11'B, spare := '11'B } |
| }; |
| template (value) LapdmCtrl ts_LapdmCtrlDM(boolean f) := { |
| u := { u := '000'B, p_f := f, u2 := '11'B, spare := '11'B } |
| }; |
| |
| template LapdmCtrl tr_LapdmCtrlUI(template boolean p := false) := { |
| u := { u := '000'B, p_f := p, u2 := '00'B, spare := '11'B } |
| }; |
| template (value) LapdmCtrl ts_LapdmCtrlUI(boolean p := false) := { |
| u := { u := '000'B, p_f := p, u2 := '00'B, spare := '11'B } |
| }; |
| |
| template LapdmCtrl tr_LapdmCtrlDISC(template boolean p) := { |
| u := { u := '010'B, p_f := p, u2 := '00'B, spare := '11'B } |
| }; |
| template LapdmCtrl ts_LapdmCtrlDISC(boolean p) := { |
| u := { u := '010'B, p_f := p, u2 := '00'B, spare := '11'B } |
| }; |
| |
| template LapdmCtrl tr_LapdmCtrlUA(template boolean f) modifies tr_LapdmCtrlU := { |
| u := { u := '011'B, p_f := f, u2 := '00'B, spare := '11'B } |
| }; |
| template (value) LapdmCtrl ts_LapdmCtrlUA(boolean f) := { |
| u := { u := '011'B, p_f := f, u2 := '00'B, spare := '11'B } |
| }; |
| |
| |
| |
| external function dec_LapdmAddressField(in octetstring stream) return LapdmAddressField |
| with { extension "prototype(convert) decode(RAW)" }; |
| |
| external function dec_LapdmCtrl(in octetstring stream) return LapdmCtrl |
| with { extension "prototype(convert) decode(RAW)" }; |
| |
| external function dec_LapdmCtrlU(in octetstring stream) return LapdmCtrlU |
| with { extension "prototype(convert) decode(RAW)" }; |
| |
| /* Formats B, Bter and B4 are used on DCCHs for frames containing an information field: |
| /* - format Bter is used on request of higher layers if and only if short L2 header type 1 is |
| * supported and a UI command is to be transmitted on SAPI 0 */ |
| /* - format B4 is used for UI frames transmitted by the network on SACCH; */ |
| /* - format B is applied in all other cases. */ |
| /* Format Bbis is used only on BCCH, PCH, NCH, and AGCH. |
| |
| /* Format B */ |
| type record LapdmFrameAB { |
| LapdmAddressField addr, |
| LapdmCtrl ctrl, |
| uint6_t len, |
| boolean m, |
| uint1_t el, |
| octetstring payload /* zero-length in Frame A */ |
| } with { variant (len) "LENGTHTO(payload)" |
| variant "FIELDORDER(msb)" }; |
| |
| external function enc_LapdmFrameAB(in LapdmFrameAB si) return octetstring |
| with { extension "prototype(convert) encode(RAW)" }; |
| external function dec_LapdmFrameAB(in octetstring stream) return LapdmFrameAB |
| with { extension "prototype(convert) decode(RAW)" }; |
| |
| /* Format B4 */ |
| type record LapdmFrameB4 { |
| LapdmAddressField addr, |
| LapdmCtrl ctrl, |
| octetstring payload |
| } with { variant "" }; |
| |
| external function enc_LapdmFrameB4(in LapdmFrameB4 si) return octetstring |
| with { extension "prototype(convert) encode(RAW)" }; |
| external function dec_LapdmFrameB4(in octetstring stream) return LapdmFrameB4 |
| with { extension "prototype(convert) decode(RAW)" }; |
| |
| type record LapdmFrameBbis { |
| octetstring payload |
| } with { variant "" }; |
| |
| external function enc_LapdmFrameBbis(in LapdmFrameBbis si) return octetstring |
| with { extension "prototype(convert) encode(RAW)" }; |
| external function dec_LapdmFrameBbis(in octetstring stream) return LapdmFrameBbis |
| with { extension "prototype(convert) decode(RAW)" }; |
| |
| type union LapdmFrame { |
| LapdmFrameAB ab, |
| LapdmFrameBbis bbis, |
| LapdmFrameB4 b4 |
| } with { variant "" }; |
| |
| external function enc_LapdmFrame(in LapdmFrame si) return octetstring |
| with { extension "prototype(convert) encode(RAW)" }; |
| /* automatic decoding to the generic LapdmFrame will not work, you have to call one of the |
| * type-specific decoder routines above */ |
| |
| /* SABM frame with L3 payload */ |
| template (value) LapdmFrame ts_LAPDm_SABM(LapdmSapi sapi, boolean c_r, boolean p, |
| octetstring l3) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlSABM(p), |
| len := 0, /* overwritten in encoder */ |
| m := false, |
| el := 1, |
| payload := l3 |
| } |
| } |
| template LapdmFrame tr_LAPDm_SABM(template LapdmSapi sapi, template boolean c_r, |
| template boolean p, template octetstring l3) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlSABM(p), |
| len := ?, |
| m := false, |
| el := 1, |
| payload := l3 |
| } |
| } |
| |
| template (value) LapdmFrame ts_LAPDm_UA(LapdmSapi sapi, boolean c_r, boolean f, |
| octetstring l3) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlUA(f), |
| len := 0, /* overwritten in encoder */ |
| m := false, |
| el := 1, |
| payload := l3 |
| } |
| } |
| template LapdmFrame tr_LAPDm_UA(template LapdmSapi sapi, template boolean c_r, |
| template boolean f, template octetstring l3) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlUA(f), |
| len := ?, |
| m := false, |
| el := 1, |
| payload := l3 |
| } |
| } |
| |
| template (value) LapdmFrame ts_LAPDm_DM(LapdmSapi sapi, boolean c_r, boolean f) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlDM(f), |
| len := 0, /* overwritten in encoder */ |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| template LapdmFrame tr_LAPDm_DM(template LapdmSapi sapi, template boolean c_r, |
| template boolean f) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlDM(f), |
| len := ?, |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| |
| template LapdmFrame ts_LAPDm_DISC(LapdmSapi sapi, boolean c_r, boolean p) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlDISC(p), |
| len := 0, |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| template LapdmFrame tr_LAPDm_DISC(template LapdmSapi sapi, template boolean c_r, |
| template boolean p) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlDISC(p), |
| len := ?, |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| |
| template LapdmFrame ts_LAPDm_UI(LapdmSapi sapi, boolean c_r, octetstring l3) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlUI, |
| len := 0, |
| m := false, |
| el := 1, |
| payload := l3 |
| } |
| } |
| template LapdmFrame tr_LAPDm_UI(template LapdmSapi sapi, template boolean c_r, |
| template octetstring l3) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlUI, |
| len := ?, |
| m := false, |
| el := 1, |
| payload := l3 |
| } |
| } |
| |
| template LapdmFrame ts_LAPDm_B4_UI(LapdmSapi sapi, boolean c_r, octetstring l3) := { |
| b4 := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlUI, |
| payload := l3 |
| } |
| } |
| template LapdmFrame tr_LAPDm_B4_UI(template LapdmSapi sapi, template boolean c_r, |
| template octetstring l3) := { |
| b4 := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlUI, |
| payload := l3 |
| } |
| } |
| |
| template LapdmFrame tr_LAPDm_I(template LapdmSapi sapi, template boolean c_r, |
| template boolean p, template uint3_t nr, |
| template uint3_t ns, template octetstring l3, |
| boolean m := false) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlI(nr, ns, p), |
| len := ?, |
| m := m, |
| el := 1, |
| payload := l3 |
| } |
| } |
| template (value) LapdmFrame ts_LAPDm_I(LapdmSapi sapi, boolean c_r, boolean p, uint3_t nr, |
| uint3_t ns, octetstring l3, boolean m := false) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlI(nr, ns, p), |
| len := 0, |
| m := m, |
| el := 1, |
| payload := l3 |
| } |
| } |
| |
| template LapdmFrame tr_LAPDm_RR(template LapdmSapi sapi, template boolean c_r, |
| template boolean p, template uint3_t nr) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlRR(nr, p), |
| len := 0, |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| template (value) LapdmFrame ts_LAPDm_RR(LapdmSapi sapi, boolean c_r, |
| boolean p, uint3_t nr) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlRR(nr, p), |
| len := 0, |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| |
| template LapdmFrame tr_LAPDm_REJ(template LapdmSapi sapi, template boolean c_r, |
| template boolean p, template uint3_t nr) := { |
| ab := { |
| addr := tr_LapdmAddr(sapi, c_r), |
| ctrl := tr_LapdmCtrlREJ(nr, p), |
| len := 0, |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| template (value) LapdmFrame ts_LAPDm_REJ(LapdmSapi sapi, boolean c_r, |
| boolean p, uint3_t nr) := { |
| ab := { |
| addr := ts_LapdmAddr(sapi, c_r), |
| ctrl := ts_LapdmCtrlREJ(nr, p), |
| len := 0, |
| m := false, |
| el := 1, |
| payload := ''O |
| } |
| } |
| |
| |
| |
| } with { encode "RAW"; /*variant "FIELDORDER(msb)" */} |