module BSSMAP_LE_Templates {

/* BSSMAP-LE Templates, building on top of BSSAP_LE_Types.
 *
 * (C) 2017-2020 by Harald Welte <laforge@gnumonks.org>
 * contributions by sysmocom - s.f.m.c. GmbH
 * 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
 */

import from General_Types all;
import from Osmocom_Types all;
import from GSM_Types all;
import from BSSAP_Types all;
import from BSSAP_LE_Types all;
import from BSSMAP_Templates all;
import from L3_Templates all;

function ts_BSSMAP_LE_LcsCause(template (omit) BSSMAP_LE_LcsCause cause)
return template (omit) BSSMAP_LE_IE_LcsCause {
	if (istemplatekind(cause, "omit")) {
		return omit;
	}
	var template (omit) BSSMAP_LE_IE_LcsCause ie := {
		iei := BSSMAP_LE_IEI_LCS_CAUSE,
		len := 1,
		cause := cause,
		diag_val := omit
	}
	return ie;
}
function tr_BSSMAP_LE_LcsCause(template BSSMAP_LE_LcsCause cause)
return template BSSMAP_LE_IE_LcsCause {
	if (istemplatekind(cause, "omit")) {
		return omit;
	}
	var template BSSMAP_LE_IE_LcsCause ie := {
		iei := BSSMAP_LE_IEI_LCS_CAUSE,
		len := ?,
		cause := cause,
		diag_val := *
	}
	return ie;
}


function ts_BSSMAP_LE_GeographicLoc(template (omit) octetstring loc)
return template (omit) BSSMAP_LE_IE_GeographicLoc {
	if (istemplatekind(loc, "omit")) {
		return omit;
	}
	var template (omit) BSSMAP_LE_IE_GeographicLoc ie := {
		iei := BSSMAP_LE_IEI_GEO_LOCATION,
		len := 0,
		location := loc
	}
	return ie;
}
function tr_BSSMAP_LE_GeographicLoc(template octetstring loc)
return template BSSMAP_LE_IE_GeographicLoc {
	if (istemplatekind(loc, "omit")) {
		return omit;
	}
	var template BSSMAP_LE_IE_GeographicLoc ie := {
		iei := BSSMAP_LE_IEI_GEO_LOCATION,
		len := ?,
		location := loc
	}
	return ie;
}




template (value) PDU_BSSAP_LE ts_BSSAP_LE_BSSMAP := {
	discriminator := '0'B,
	spare := '0000000'B,
	dlci := omit,
	lengthIndicator := 0,	/* overwritten by codec */
	pdu := {
		bssmap := -
	}
}

template (present) PDU_BSSAP_LE tr_BSSAP_LE_BSSMAP := {
	discriminator := '0'B,
	spare := '0000000'B,
	dlci := *,
	lengthIndicator := ?,
	pdu := {
		bssmap := ?
	}
}

template (value) PDU_BSSAP_LE ts_BSSAP_LE_DTAP(octetstring dtap, template (value) OCT1 dlci) := {
	discriminator := '1'B,
	spare := '0000000'B,
	dlci := dlci,
	lengthIndicator := 0,	/* overwritten by codec */
	pdu := {
		dtap := dtap
	}
}

template (present) PDU_BSSAP_LE tr_BSSAP_LE_DTAP := {
	discriminator := '1'B,
	spare := '0000000'B,
	dlci := *,
	lengthIndicator := ?,
	pdu := {
		dtap := ?
	}
}

function ts_BSSMAP_LE_IMSI(template (omit) hexstring imsi) return template (omit) BSSMAP_LE_IE_IMSI {
	if (istemplatekind(imsi, "omit")) {
		return omit;
	}
	template (value) BSSMAP_LE_IE_IMSI res := {
		iei := BSSMAP_LE_IEI_IMSI,
		len := 0,
		imsi := ts_MI_IMSI(valueof(imsi))
	};
	return res;
}
function tr_BSSMAP_LE_IMSI(template hexstring imsi) return template BSSMAP_LE_IE_IMSI {
	if (istemplatekind(imsi, "omit")) {
		return omit;
	}
	template BSSMAP_LE_IE_IMSI res := {
		iei := BSSMAP_LE_IEI_IMSI,
		len := ?,
		imsi := tr_MI_IMSI(imsi)
	};
	return res;
}

template (value) BSSMAP_LE_IE_LocationType ts_BSSMAP_LE_LocType(template (value) BSSMAP_LE_LocInfo li,
								template (omit) BSSMAP_LE_PosMethod pm := omit) := {
	iei := BSSMAP_LE_IEI_LOCATION_TYPE,
	len := 0,
	loc_info := li,
	pos_method := pm
}
template (present) BSSMAP_LE_IE_LocationType tr_BSSMAP_LE_LocType(template (present) BSSMAP_LE_LocInfo li,
								  template BSSMAP_LE_PosMethod pm := omit) := {
	iei := BSSMAP_LE_IEI_LOCATION_TYPE,
	len := ?,
	loc_info := li,
	pos_method := pm
}


/* Section 9.1 */
template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LocInfo loc_info := BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC,
						      template (value) BSSMAP_IE_CellIdentifier cell_id,
						      template (omit) hexstring imsi,
						      template (omit) octetstring bsslap_apdu := omit)

modifies ts_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_req := {
				msg_type := BSSMAP_LE_PERFORM_LOC_REQ,
				location_type := ts_BSSMAP_LE_LocType(loc_info),
				cell_id := cell_id,
				cm3 := omit,
				lcs_client_type := omit,
				chosen_channel := omit,
				lcs_priority := omit,
				lcs_qos := omit,
				req_gps_ass_d := omit,
				bsslap_apdu := ts_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, bsslap_apdu),
				lcs_capability := omit,
				packet_meas_rep := omit,
				meas_cell_id_list := omit,
				imsi := ts_BSSMAP_LE_IMSI(imsi),
				imei := omit
			}
		}
	}
}
template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LocInfo loc_info := BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC,
							template (present) BSSMAP_IE_CellIdentifier cell_id,
							template hexstring imsi)
modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_req := {
				msg_type := BSSMAP_LE_PERFORM_LOC_REQ,
				location_type := tr_BSSMAP_LE_LocType(loc_info),
				cell_id := cell_id,
				cm3 := *,
				lcs_client_type := *,
				chosen_channel := *,
				lcs_priority := *,
				lcs_qos := *,
				req_gps_ass_d := *,
				bsslap_apdu := *,
				lcs_capability := *,
				packet_meas_rep := *,
				meas_cell_id_list := *,
				imsi := tr_BSSMAP_LE_IMSI(imsi),
				imei := *
			}
		}
	}
}


/* Section 9.2 */
template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerfLocResp(template (omit) octetstring geo_loc,
						       template (omit) BSSMAP_LE_LcsCause cause)

modifies ts_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_resp := {
				msg_type := BSSMAP_LE_PERFORM_LOC_RESP,
				geographic_loc := ts_BSSMAP_LE_GeographicLoc(geo_loc),
				pos_data := omit,
				deciph_keys := omit,
				lcs_cause := ts_BSSMAP_LE_LcsCause(cause),
				velocity_data := omit,
				ganss_pos_data := omit
			}
		}
	}
}
template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerfLocResp(template octetstring geo_loc,
							 template BSSMAP_LE_LcsCause cause)
modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_resp := {
				msg_type := BSSMAP_LE_PERFORM_LOC_RESP,
				geographic_loc := tr_BSSMAP_LE_GeographicLoc(geo_loc),
				pos_data := *,
				deciph_keys := *,
				lcs_cause := tr_BSSMAP_LE_LcsCause(cause),
				velocity_data := *,
				ganss_pos_data := *
			}
		}
	}
}


/* Section 9.8 */
template (value) PDU_BSSAP_LE ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_ProtocolId prot_id, octetstring data,
						    template (omit) BSSMAP_LE_IE_Segmentation segm := omit)
modifies ts_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			co_info := {
				msg_type := BSSMAP_LE_CONN_ORIENTED_INFO,
				bsslap_apdu := {
					iei := BSSMAP_LE_IEI_APDU,
					len := 0,
					protocol_id := prot_id,
					spare := '0'B,
					data := data
				},
				segmentation := segm
			}
		}
	}
}
template (present) PDU_BSSAP_LE tr_BSSMAP_LE_ConnInfo(template (present) BSSMAP_LE_ProtocolId prot_id,
						      template (present) octetstring data,
						      template BSSMAP_LE_IE_Segmentation segm := omit)
modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			co_info := {
				msg_type := BSSMAP_LE_CONN_ORIENTED_INFO,
				bsslap_apdu := {
					iei := BSSMAP_LE_IEI_APDU,
					len := ?,
					protocol_id := prot_id,
					spare := '0'B,
					data := data
				},
				segmentation := segm
			}
		}
	}
}

template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LcsCause cause)
modifies ts_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_abort := {
				msg_type := BSSMAP_LE_PERFORM_LOC_ABORT,
				lcs_cause := ts_BSSMAP_LE_LcsCause(cause)
			}
		}
	}
}

template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerfLocAbort(template BSSMAP_LE_LcsCause cause)
modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_abort := {
				msg_type := BSSMAP_LE_PERFORM_LOC_ABORT,
				lcs_cause := tr_BSSMAP_LE_LcsCause(cause)
			}
		}
	}
}

/* Section 9.10 */
template (value) PDU_BSSAP_LE ts_BSSMAP_LE_Reset(myBSSMAP_Cause cause) modifies ts_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			reset := {
				msg_type := BSSMAP_LE_RESET,
				cause := ts_BSSMAP_IE_Cause(enum2int(cause))
			}
		}
	}
}
template (present) PDU_BSSAP_LE tr_BSSMAP_LE_Reset modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			reset := {
				msg_type := BSSMAP_LE_RESET,
				cause := ?
			}
		}
	}
}

/* Section 9.11 */
template (value) PDU_BSSAP_LE ts_BSSMAP_LE_ResetAck modifies ts_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			reset_ack := {
				msg_type := BSSMAP_LE_RESET_ACK
			}
		}
	}
}
template (present) PDU_BSSAP_LE tr_BSSMAP_LE_ResetAck modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			reset_ack := {
				msg_type := BSSMAP_LE_RESET_ACK
			}
		}
	}
}

function ts_BSSMAP_LE_APDU(BSSMAP_LE_ProtocolId prot_id, template (omit) octetstring data)
return template (omit) BSSMAP_LE_IE_APDU {
	var BSSMAP_LE_IE_APDU ie := {
		iei := BSSMAP_LE_IEI_APDU,
		len := 0, // overwritten
		protocol_id := prot_id,
		spare := '0'B
	}
	if (istemplatekind(data, "omit")) {
		return omit;
	}
	ie.data := valueof(data);
	return ie;
}

function tr_BSSMAP_LE_APDU(template BSSMAP_LE_ProtocolId prot_id, template octetstring data)
return template BSSMAP_LE_IE_APDU {
	var template BSSMAP_LE_IE_APDU ie := {
		iei := BSSMAP_LE_IEI_APDU,
		len := ?,
		protocol_id := prot_id,
		spare := '0'B
	}
	if (istemplatekind(data, "omit")) {
		return omit;
	} else if (istemplatekind(data, "*")) {
		return *;
	}
	ie.data := data;
	return ie;
}


/* Section 9.12 */
template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerformLocInfo(BSSMAP_IE_CellIdentifier cell_id,
							  BSSMAP_LE_ProtocolId prot_id,
							  template (omit) octetstring data)
modifies ts_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_info := {
				msg_type := BSSMAP_LE_PERFORM_LOC_INFO,
				cell_id := cell_id,
				bsslap_apdu := ts_BSSMAP_LE_APDU(prot_id, data)
			}
		}
	}
}
template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerformLocInfo(template (present) BSSMAP_IE_CellIdentifier cell_id,
							    template BSSMAP_LE_ProtocolId prot_id,
							    template octetstring data)
modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			perf_loc_info := {
				msg_type := BSSMAP_LE_PERFORM_LOC_INFO,
				cell_id := cell_id,
				bsslap_apdu := tr_BSSMAP_LE_APDU(prot_id, data)
			}
		}
	}
}

/* return Layer3 octetstring inside BSSAP-LE PDU */
function f_bssap_le_extract_l3(PDU_BSSAP_LE bssap) return template octetstring {
	if (ischosen(bssap.pdu.bssmap)) {
		return omit;
	} else {
		return bssap.pdu.dtap;
	}
}


template PDU_BSSAP_LE tr_BSSMAP_LE_Paging(template hexstring imsi_digits := ?,
					template OCT4 tmsi := *,
					template BSSMAP_IE_ChannelNeeded chneed := *)
modifies tr_BSSAP_LE_BSSMAP := {
	pdu := {
		bssmap := {
			paging := {
				messageType := '52'O,
				iMSI := tr_BSSMAP_Imsi(imsi_digits),
				tMSI := tr_BSSMAP_IE_TMSI(tmsi) ifpresent,
				cellIdentifierList := ?,
				channelNeeded := chneed,
				eMLPP_Priority := omit,
				pagingInformation := omit /* only VGCS/VBS flag */
			}
		}
	}
}




} with { encode "RAW" };