/* Data Types / Encoding / Decoding for OsmocomBB L1CTL interface */ /* (C) 2017 by Harald Welte , derived from l1ctl_proto.h * (C) 2010 by Harald Welte + Holger Hans Peter Freyther */ module L1CTL_Types { import from General_Types all; import from GSM_Types all; import from Osmocom_Types all; type enumerated L1ctlMsgType { L1CTL_NONE, L1CTL_FBSB_REQ, L1CTL_FBSB_CONF, L1CTL_DATA_IND, L1CTL_RACH_REQ, L1CTL_DM_EST_REQ, L1CTL_DATA_REQ, L1CTL_RESET_IND, L1CTL_PM_REQ, /* power measurement */ L1CTL_PM_CONF, /* power measurement */ L1CTL_ECHO_REQ, L1CTL_ECHO_CONF, L1CTL_RACH_CONF, L1CTL_RESET_REQ, L1CTL_RESET_CONF, L1CTL_DATA_CONF, L1CTL_CCCH_MODE_REQ, L1CTL_CCCH_MODE_CONF, L1CTL_DM_REL_REQ, L1CTL_PARAM_REQ, L1CTL_DM_FREQ_REQ, L1CTL_CRYPTO_REQ, L1CTL_SIM_REQ, L1CTL_SIM_CONF, L1CTL_TCH_MODE_REQ, L1CTL_TCH_MODE_CONF, L1CTL_NEIGH_PM_REQ, L1CTL_NEIGH_PM_IND, L1CTL_TRAFFIC_REQ, L1CTL_TRAFFIC_CONF, L1CTL_TRAFFIC_IND } with { variant "FIELDLENGTH(8)" }; type enumerated L1ctlCcchMode { CCCH_MODE_NONE (0), CCCH_MODE_NON_COMBINED, CCCH_MODE_COMBINED } with { variant "FIELDLENGTH(8)" }; type enumerated L1ctlNeighMode { NEIGH_MODE_NONE (0), NEIGH_MODE_PM, NEIGH_MODE_SB } with { variant "FIELDLENGTH(8)" }; type enumerated L1ctlResetType { L1CTL_RES_T_BOOT (0), L1CTL_RES_T_FULL, L1CTL_RES_T_SCHED } with { variant "FIELDLENGTH(8)" }; const integer TRAFFIC_DATA_LEN := 40; type record L1ctlHdrFlags { BIT7 padding, boolean f_done } with { variant "" }; type record L1ctlHeader { L1ctlMsgType msg_type, L1ctlHdrFlags flags, OCT2 padding } with { variant "" }; template L1ctlHeader t_L1ctlHeader(template L1ctlMsgType msg_type) := { msg_type := msg_type, flags := { padding := '0000000'B, f_done := false }, padding := '0000'O }; type record L1ctlDlInfo { RslChannelNr chan_nr, RslLinkId link_id, Arfcn arfcn, uint32_t frame_nr, GsmRxLev rx_level, uint8_t snr, uint8_t num_biterr, uint8_t fire_crc } with { variant "" }; type record L1ctlFbsbConf { int16_t initial_freq_err, uint8_t result, uint8_t bsic } with { variant "" }; type record L1ctlCcchModeConf { L1ctlCcchMode ccch_mode, OCT3 padding } with { variant "" }; /* gsm48_chan_mode */ type uint8_t L1ctlTchMode; type record L1ctlAudioMode { BIT4 padding, boolean tx_microphone, boolean tx_traffic_req, boolean rx_speaker, boolean rx_traffic_ind } with { variant "" }; template L1ctlAudioMode t_L1CTL_AudioModeNone := { '0000'B, false, false, false, false }; type record L1ctlTchModeConf { L1ctlTchMode tch_mode, L1ctlAudioMode audio_mode, OCT2 padding } with { variant "" }; type record L1ctlDataInd { octetstring payload length(23) } with { variant "" }; type union L1ctlDlPayload { L1ctlFbsbConf fbsb_conf, L1ctlCcchModeConf ccch_mode_conf, L1ctlTchModeConf tch_mode_conf, L1ctlDataInd data_ind, L1ctlTrafficReq traffic_ind, octetstring other } with { variant "" }; type record L1ctlDlMessage { L1ctlHeader header, L1ctlDlInfo dl_info optional, L1ctlDlPayload payload } with { variant (dl_info) "PRESENCE(header.msg_type = L1CTL_FBSB_CONF, header.msg_type = L1CTL_RACH_CONF, header.msg_type = L1CTL_DATA_IND, header.msg_type = L1CTL_DATA_CONF, header.msg_type = L1CTL_TRAFFIC_IND)" variant (payload) "CROSSTAG(fbsb_conf, header.msg_type = L1CTL_FBSB_CONF; ccch_mode_conf, header.msg_type = L1CTL_CCCH_MODE_CONF; tch_mode_conf, header.msg_type = L1CTL_TCH_MODE_CONF; data_ind, header.msg_type = L1CTL_DATA_IND; traffic_ind, header.msg_type = L1CTL_TRAFFIC_IND; other, OTHERWISE; )" }; external function enc_L1ctlDlMessage(in L1ctlDlMessage msg) return octetstring with { extension "prototype(convert) encode(RAW)" }; external function dec_L1ctlDlMessage(in octetstring stream) return L1ctlDlMessage with { extension "prototype(convert) decode(RAW)" }; type record L1ctlUlInfo { RslChannelNr chan_nr, RslLinkId link_id, OCT2 padding } with { variant "" }; type record L1ctlFbsbFlags { BIT5 padding, boolean sb, boolean fb1, boolean fb0 } with { variant "" }; template L1ctlFbsbFlags t_L1CTL_FBSB_F_ALL := { padding := '00000'B, sb := true, fb1 := true, fb0 := true }; type record L1ctlFbsbReq { Arfcn arfcn, uint16_t timeout_tdma_frames, uint16_t freq_err_thresh1, uint16_t freq_err_thresh2, uint8_t num_freqerr_avg, L1ctlFbsbFlags flags, uint8_t sync_info_idx, L1ctlCcchMode ccch_mode, GsmRxLev rxlev_exp } with { variant "" }; type record L1ctlCcchModeReq { L1ctlTchMode tch_mode, L1ctlAudioMode audio_mode, OCT2 padding } with { variant "" }; type record L1ctlTchModeReq { L1ctlTchMode tch_mode, L1ctlAudioMode audio_mode, OCT2 padding } with { variant "" }; type record L1ctlRachReq { uint8_t ra, uint8_t combined, uint16_t offset } with { variant "" }; type record L1ctlParReq { int8_t ta, uint8_t tx_power, OCT2 padding } with { variant "" }; type record L1ctlH1 { uint8_t hsn, uint8_t maio, uint8_t n, OCT1 padding, bitstring ma length(64) } with { variant "" }; type record L1ctlDmEstReq { GsmTsc tsc, uint8_t h, Arfcn arfcn optional, L1ctlH1 hopping optional, L1ctlTchMode tch_mode, L1ctlAudioMode audio_mode } with { variant (arfcn) "PRESENCE(h = 0)" variant (hopping) "PRESENCE(h = 1)" }; type record L1ctlReset { L1ctlResetType reset_type, OCT3 padding } with { variant "" }; type record L1ctlTrafficReq { octetstring data length(TRAFFIC_DATA_LEN) } with { variant "" }; type union L1ctlUlPayload { L1ctlFbsbReq fbsb_req, L1ctlCcchModeReq ccch_mode_req, L1ctlTchModeReq tch_mode_req, L1ctlRachReq rach_req, L1ctlParReq par_req, L1ctlDmEstReq dm_est_req, L1ctlReset reset_req, //L1ctlNeighPmReq neigh_pm_req, L1ctlTrafficReq traffic_req, octetstring other } with { variant "" }; type record L1ctlUlMessage { L1ctlHeader header, L1ctlUlInfo ul_info optional, L1ctlUlPayload payload } with { variant (ul_info) "PRESENCE(header.msg_type = L1CTL_RACH_REQ, header.msg_type = L1CTL_PARAM_REQ, header.msg_type = L1CTL_CRYPTO_REQ, header.msg_type = L1CTL_DATA_REQ, header.msg_type = L1CTL_DM_EST_REQ, header.msg_type = L1CTL_DM_FREQ_REQ, header.msg_type = L1CTL_DM_REL_REQ, header.msg_type = L1CTL_TRAFFIC_REQ)" variant (payload) "CROSSTAG(fbsb_req, header.msg_type = L1CTL_FBSB_REQ; ccch_mode_req, header.msg_type = L1CTL_CCCH_MODE_REQ; tch_mode_req, header.msg_type = L1CTL_TCH_MODE_REQ; rach_req, header.msg_type = L1CTL_RACH_REQ; par_req, header.msg_type = L1CTL_PARAM_REQ; dm_est_req, header.msg_type = L1CTL_DM_EST_REQ; reset_req, header.msg_type = L1CTL_RESET_REQ; traffic_req, header.msg_type = L1CTL_TRAFFIC_REQ; other, OTHERWISE; )" }; external function enc_L1ctlUlMessage(in L1ctlUlMessage msg) return octetstring with { extension "prototype(convert) encode(RAW)" }; external function dec_L1ctlUlMessage(in octetstring stream) return L1ctlUlMessage with { extension "prototype(convert) decode(RAW)" }; type record L1ctlUlMessageLV { uint16_t len, L1ctlUlMessage msg } with { variant (len) "LENGTHTO(msg)" }; external function enc_L1ctlUlMessageLV(in L1ctlUlMessageLV msg) return octetstring with { extension "prototype(convert) encode(RAW)" }; external function dec_L1ctlUlMessageLV(in octetstring stream) return L1ctlUlMessageLV with { extension "prototype(convert) decode(RAW)" }; type record L1ctlDlMessageLV { uint16_t len, L1ctlDlMessage msg } with { variant (len) "LENGTHTO(msg)" }; external function enc_L1ctlDlMessageLV(in L1ctlDlMessageLV msg) return octetstring with { extension "prototype(convert) encode(RAW)" }; external function dec_L1ctlDlMessageLV(in octetstring stream) return L1ctlDlMessageLV with { extension "prototype(convert) decode(RAW)" }; /* for generating RESET_REQ */ template L1ctlUlMessage t_L1ctlResetReq(template L1ctlResetType rst_type) := { header := t_L1ctlHeader(L1CTL_RESET_REQ), ul_info := omit, payload := { reset_req := { reset_type := rst_type, padding := '000000'O } } }; /* for generating FBSB_REQ */ template L1ctlUlMessage t_L1CTL_FBSB_REQ(template Arfcn arfcn, template L1ctlFbsbFlags flags, uint8_t sync_info_idx, L1ctlCcchMode ccch_mode, GsmRxLev rxlev_exp) := { header := t_L1ctlHeader(L1CTL_FBSB_REQ), ul_info := omit, payload := { fbsb_req := { arfcn := arfcn, timeout_tdma_frames := 10, freq_err_thresh1 := 10000, freq_err_thresh2 := 800, num_freqerr_avg := 3, flags := flags, sync_info_idx := sync_info_idx, ccch_mode := ccch_mode, rxlev_exp := rxlev_exp } } }; /* for matching against incoming FBSB_CONF */ template L1ctlDlMessage t_L1CTL_FBSB_CONF(template uint8_t result) := { header := t_L1ctlHeader(L1CTL_FBSB_CONF), dl_info := ?, payload := { fbsb_conf := { initial_freq_err := ?, result := result, bsic := ? } } }; template L1ctlUlMessage t_L1CTL_RACH_REQ(uint8_t ra, uint8_t combined, uint16_t offset) := { header := t_L1ctlHeader(L1CTL_RACH_REQ), ul_info := { chan_nr := t_RslChanNr_RACH(0), link_id := ts_RslLinkID_DCCH(0), padding := '0000'O }, payload := { rach_req := { ra := ra, combined := combined, offset := offset } } } template L1ctlUlMessage t_L1CTL_DM_EST_REQ(Arfcn arfcn, RslChannelNr chan_nr, GsmTsc tsc) := { header := t_L1ctlHeader(L1CTL_DM_EST_REQ), ul_info := { chan_nr := chan_nr, link_id := ts_RslLinkID_DCCH(0), padding := '0000'O }, payload := { dm_est_req := { tsc := tsc, h := 0, arfcn := arfcn, hopping := omit, tch_mode := 0, audio_mode := t_L1CTL_AudioModeNone } } } template L1ctlUlMessage t_L1CTL_DM_REL_REQ(RslChannelNr chan_nr) := { header := t_L1ctlHeader(L1CTL_DM_REL_REQ), ul_info := { chan_nr := chan_nr, link_id := ts_RslLinkID_DCCH(0), padding := '0000'O }, payload := { other := ''O } } template L1ctlUlMessage t_L1CTL_DATA_REQ(template RslChannelNr chan_nr, template RslLinkId link_id, octetstring l2_data) := { header := t_L1ctlHeader(L1CTL_DATA_REQ), ul_info := { chan_nr := chan_nr, link_id := link_id, padding := '0000'O }, payload := { other := l2_data } } /* for matching against incoming RACH_CONF */ template L1ctlDlMessage t_L1CTL_RACH_CONF := { header := t_L1ctlHeader(L1CTL_RACH_CONF), dl_info := ?, payload := ? }; /* for matching against incoming RACH_CONF */ template L1ctlDlMessage t_L1CTL_DATA_IND(template RslChannelNr chan_nr) := { header := t_L1ctlHeader(L1CTL_DATA_IND), dl_info := { chan_nr := chan_nr, link_id := ?, arfcn := ?, frame_nr := ?, rx_level := ?, snr := ?, num_biterr := ?, fire_crc := ? }, payload := { data_ind := ? } }; template GsmRrMessage t_RR_IMM_ASS(uint8_t ra, uint8_t fn) := { header := t_RrHeader(IMMEDIATE_ASSIGNMENT, ?), payload := { imm_ass := { ded_or_tbf := ?, page_mode := ?, chan_desc := ?, pkt_chan_desc := omit, req_ref := f_compute_ReqRef(ra, fn), timing_advance := ?, mobile_allocation := ? } } }; } with { encode "RAW" };