/* Osmocom HNBLL Interface Templates, as per osmo-hnodeb/include/osmocom/hnodeb/hnb_prim.h
 * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
 *
 * 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 HNBLLIF_Templates {

import from General_Types all;
import from Osmocom_Types all;
import from HNBLLIF_Types all;

/**********************
 * CTL SAPI
 **********************/
template (value) HNBLLIF_Message ts_HNBLLIF_CTL_HELLO_REQ(template (value) HNBLLIF_Sapi sapi,
							  template (value) uint16_t api_version) := {
	sapi := HNBLL_IF_SAPI_CTL,
	u := {
		ctl := {
			prim := HNBLL_IF_CTL_MSG_HELLO,
			u := {
				hello := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							sapi := sapi,
							api_version := api_version
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_CTL_HELLO_CNF(template (present) HNBLLIF_Sapi sapi := ?,
							    template (present) uint32_t api_version := ?) := {
	sapi := HNBLL_IF_SAPI_CTL,
	u := {
		ctl := {
			prim := HNBLL_IF_CTL_MSG_HELLO,
			u := {
				hello := {
					op := HNBLL_IF_OP_CONFIRM,
					u := {
						cnf := {
							sapi := sapi,
							api_version := api_version
						}
					}
				}
			}
		}
	}
}


/**********************
 * IUH SAPI
 **********************/

template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONFIGURE_IND(template (present) uint16_t mcc := ?,
								template (present) uint16_t mnc := ?,
								template (present) uint16_t cell_identity := ?,
								template (present) uint16_t lac := ?,
								template (present) uint8_t rac := ?,
								template (present) uint16_t sac := ?,
								template (present) uint16_t rnc_id := ?) := {
	sapi := HNBLL_IF_SAPI_IUH,
	u := {
		iuh := {
			prim := HNBLL_IF_IUH_MSG_CONFIGURE,
			u := {
				configure := {
					op := HNBLL_IF_OP_INDICATION,
					u := {
						ind := {
							mcc := mcc,
							mnc := mnc,
							cell_identity := cell_identity,
							lac := lac,
							rac := rac,
							reserved := ?,
							sac := sac,
							rnc_id := rnc_id
						}
					}
				}
			}
		}
	}
}

template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(template (value) uint32_t context_id,
								template (value) uint8_t domain,
								template (value) uint8_t est_cause,
								template (value) octetstring data) := {
	sapi := HNBLL_IF_SAPI_IUH,
	u := {
		iuh := {
			prim := HNBLL_IF_IUH_MSG_CONN_ESTABLISH,
			u := {
				conn_establish := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							context_id := context_id,
							domain := domain,
							est_cause := est_cause,
							reserved := 0,
							data_len := lengthof(data),
							data := data
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(template (present) uint32_t context_id := ?,
								template (present) uint8_t domain := ?,
								template (present) uint8_t est_cause := ?) := {
	sapi := HNBLL_IF_SAPI_IUH,
	u := {
		iuh := {
			prim := HNBLL_IF_IUH_MSG_CONN_ESTABLISH,
			u := {
				conn_establish := {
					op := HNBLL_IF_OP_CONFIRM,
					u := {
						cnf := {
							context_id := context_id,
							domain := domain,
							est_cause := est_cause
						}
					}
				}
			}
		}
	}
}

template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_RELEASE_REQ(template (value) uint32_t context_id,
							      template (value) uint8_t domain,
							      template (value) uint8_t cause_type,
							      template (value) uint8_t cause,
							      template (value) octetstring data) := {
	sapi := HNBLL_IF_SAPI_IUH,
	u := {
		iuh := {
			prim := HNBLL_IF_IUH_MSG_CONN_RELEASE,
			u := {
				conn_release := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							context_id := context_id,
							domain := domain,
							spare1 := 0,
							cause_type := cause_type,
							cause := cause,
							data_len := lengthof(data),
							data := data
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONN_DATA_IND(template (present) uint32_t context_id := ?,
								template (present) uint8_t domain := ?,
								template (present) octetstring data := ?) := {
	sapi := HNBLL_IF_SAPI_IUH,
	u := {
		iuh := {
			prim := HNBLL_IF_IUH_MSG_CONN_DATA,
			u := {
				conn_data := {
					op := HNBLL_IF_OP_INDICATION,
					u := {
						ind := {
							context_id := context_id,
							domain := domain,
							spare1 := ?,
							spare2 := ?,
							data_len := ?,
							data := data
						}
					}
				}
			}
		}
	}
}

template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_DATA_REQ(template (value) uint32_t context_id,
							      template (value) uint8_t domain,
							      template (value) octetstring data) := {
	sapi := HNBLL_IF_SAPI_IUH,
	u := {
		iuh := {
			prim := HNBLL_IF_IUH_MSG_CONN_DATA,
			u := {
				conn_data := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							context_id := context_id,
							domain := domain,
							spare1 := 0,
							spare2 := 0,
							data_len := lengthof(data),
							data := data
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_IUH_UNITDATA_IND(template (present) octetstring data := ?) := {
	sapi := HNBLL_IF_SAPI_IUH,
	u := {
		iuh := {
			prim := HNBLL_IF_IUH_MSG_UNITDATA,
			u := {
				unitdata := {
					op := HNBLL_IF_OP_INDICATION,
					u := {
						ind := {
							data_len := ?,
							data := data
						}
					}
				}
			}
		}
	}
}

/**********************
 * AUDIO SAPI
 **********************/
const HNBLLIF_AUDIO_IPTIs IPTIs_default := {
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

private function f_subflow_sizes_default() return HNBLLIF_AUDIO_SubflowSizes
{
	var HNBLLIF_AUDIO_SubflowSizes ss;

	for (var integer i := 0; i < HNBLLIF_MAX_RFCIS; i := i + 1) {
		for (var integer j := 0; j < HNBLLIF_MAX_SUBFLOWS; j := j + 1) {
			ss[i][j] := 0;
		}
	}

	ss[0][0] := 81; ss[0][1] := 103; ss[0][2] := 60;
	ss[1][0] := 39; ss[1][1] := 0; ss[1][2] := 0;
	ss[2][0] := 0;  ss[2][1] := 0;   ss[2][2] := 0;

	return ss;
}

private function f_rfcis_default() return HNBLLIF_AUDIO_RFCIs
{
	var HNBLLIF_AUDIO_RFCIs rfcis;

	for (var integer i := 0; i < HNBLLIF_MAX_RFCIS; i := i + 1) {
		rfcis[i] := i;
	}

	return rfcis;
}

template (value) HNBLLIF_Message ts_HNBLLIF_AUDIO_CONN_ESTABLISH_REQ(template (value) uint32_t context_id,
								     template (value) uint16_t remote_rtp_port,
								     template (value) HNBLLIF_AddrType remote_rtp_address_type,
								     template (value) HNBLLIF_Addr remote_addr,
								     template (value) uint8_t transparent := 0,
								     template (value) uint8_t data_pdu_type := 0,
								     template (value) uint16_t supported_versions_mask := 3,
								     template (value) uint8_t num_rfci := 3,
								     template (value) uint8_t num_subflows := 3,
								     template (value) HNBLLIF_AUDIO_SubflowSizes subflow_sizes := f_subflow_sizes_default(),
								     template (value) uint8_t IPTIs_present := 0,
								     template (value) HNBLLIF_AUDIO_IPTIs IPTIs := IPTIs_default,
								     template (omit) HNBLLIF_AUDIO_RFCIs rfci := f_rfcis_default()) := {
	sapi := HNBLL_IF_SAPI_AUDIO,
	u := {
		audio := {
			prim := HNBLL_IF_AUDIO_MSG_CONN_ESTABLISH,
			u := {
				conn_establish := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							context_id := context_id,
							remote_rtp_port := remote_rtp_port,
							reserved := 0,
							remote_rtp_address_type := remote_rtp_address_type,
							remote_addr := remote_addr,
							transparent := transparent,
							data_pdu_type := data_pdu_type,
							supported_versions_mask := supported_versions_mask,
							num_rfci := num_rfci,
							num_subflows := num_subflows,
							subflow_sizes := subflow_sizes,
							IPTIs_present := IPTIs_present,
							IPTIs := IPTIs,
							rfci := rfci
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_AUDIO_CONN_ESTABLISH_CNF(template (present) uint32_t context_id := ?,
								     template (present) uint32_t audio_conn_id := ?,
								     template (present) uint8_t error_code := ?,
								     template (present) uint16_t local_rtp_port:= ?,
								     template (present) HNBLLIF_AddrType local_rtp_address_type := ?,
								     template (present) HNBLLIF_Addr local_addr := ?) := {
	sapi := HNBLL_IF_SAPI_AUDIO,
	u := {
		audio := {
			prim := HNBLL_IF_AUDIO_MSG_CONN_ESTABLISH,
			u := {
				conn_establish := {
					op := HNBLL_IF_OP_CONFIRM,
					u := {
						cnf := {
							context_id := context_id,
							audio_conn_id := audio_conn_id,
							local_rtp_port := local_rtp_port,
							error_code := error_code,
							local_rtp_address_type := local_rtp_address_type,
							local_addr := local_addr
						}
					}
				}
			}
		}
	}
}

template (value) HNBLLIF_Message ts_HNBLLIF_AUDIO_CONN_RELEASE_REQ(template (value) uint32_t audio_conn_id) := {
	sapi := HNBLL_IF_SAPI_AUDIO,
	u := {
		audio := {
			prim := HNBLL_IF_AUDIO_MSG_CONN_RELEASE,
			u := {
				conn_release := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							audio_conn_id := audio_conn_id
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_AUDIO_CONN_DATA_IND(template (present) uint32_t audio_conn_id := ?,
								  template (present) uint8_t frame_nr := ?,
								  template (present) uint8_t fqc := ?,
								  template (present) uint8_t rfci := ?,
								  template (present) octetstring data := ?) := {
	sapi := HNBLL_IF_SAPI_AUDIO,
	u := {
		audio := {
			prim := HNBLL_IF_AUDIO_MSG_CONN_DATA,
			u := {
				conn_data := {
					op := HNBLL_IF_OP_INDICATION,
					u := {
						ind := {
							audio_conn_id := audio_conn_id,
							frame_nr := frame_nr,
							fqc := fqc,
							rfci := rfci,
							spare := 0,
							data_len := ?,
							data := data
						}
					}
				}
			}
		}
	}
}

template (value) HNBLLIF_Message ts_HNBLLIF_AUDIO_CONN_DATA_REQ(template (value) uint32_t audio_conn_id,
							      template (value) uint8_t frame_nr,
							      template (value) uint8_t fqc,
							      template (value) uint8_t rfci,
							      template (value) octetstring data) := {
	sapi := HNBLL_IF_SAPI_AUDIO,
	u := {
		audio := {
			prim := HNBLL_IF_AUDIO_MSG_CONN_DATA,
			u := {
				conn_data := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							audio_conn_id := audio_conn_id,
							frame_nr := frame_nr,
							fqc := fqc,
							rfci := rfci,
							spare := 0,
							data_len := lengthof(data),
							data := data
						}
					}
				}
			}
		}
	}
}


/**********************
 * GTP SAPI
 **********************/
template (value) HNBLLIF_Message ts_HNBLLIF_GTP_CONN_ESTABLISH_REQ(template (value) uint32_t context_id,
								     template (value) uint32_t remote_tei,
								     template (value) HNBLLIF_AddrType remote_gtpu_address_type,
								     template (value) HNBLLIF_Addr remote_gtpu_addr) := {
	sapi := HNBLL_IF_SAPI_GTP,
	u := {
		gtp := {
			prim := HNBLL_IF_GTP_MSG_CONN_ESTABLISH,
			u := {
				conn_establish := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							context_id := context_id,
							remote_tei := remote_tei,
							reserved := 0,
							remote_gtpu_address_type := remote_gtpu_address_type,
							remote_gtpu_addr := remote_gtpu_addr
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_GTP_CONN_ESTABLISH_CNF(template (present) uint32_t context_id := ?,
								     template (present) uint32_t gtp_conn_id := ?,
								     template (present) uint32_t local_tei := ?,
								     template (present) uint8_t error_code := ?,
								     template (present) HNBLLIF_AddrType local_gtpu_address_type := ?,
								     template (present) HNBLLIF_Addr local_gtpu_addr := ?) := {
	sapi := HNBLL_IF_SAPI_GTP,
	u := {
		gtp := {
			prim := HNBLL_IF_GTP_MSG_CONN_ESTABLISH,
			u := {
				conn_establish := {
					op := HNBLL_IF_OP_CONFIRM,
					u := {
						cnf := {
							context_id := context_id,
							gtp_conn_id := gtp_conn_id,
							local_tei := local_tei,
							error_code := error_code,
							local_gtpu_address_type := local_gtpu_address_type,
							local_gtpu_addr := local_gtpu_addr
						}
					}
				}
			}
		}
	}
}

template (value) HNBLLIF_Message ts_HNBLLIF_GTP_CONN_RELEASE_REQ(template (value) uint32_t gtp_conn_id) := {
	sapi := HNBLL_IF_SAPI_GTP,
	u := {
		gtp := {
			prim := HNBLL_IF_GTP_MSG_CONN_RELEASE,
			u := {
				conn_release := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							gtp_conn_id := gtp_conn_id
						}
					}
				}
			}
		}
	}
}

template (present) HNBLLIF_Message tr_HNBLLIF_GTP_CONN_DATA_IND(template (present) uint32_t gtp_conn_id,
							        template (present) octetstring data := ?) := {
	sapi := HNBLL_IF_SAPI_GTP,
	u := {
		gtp := {
			prim := HNBLL_IF_GTP_MSG_CONN_DATA,
			u := {
				conn_data := {
					op := HNBLL_IF_OP_INDICATION,
					u := {
						ind := {
							gtp_conn_id := gtp_conn_id,
							data_len := ?,
							data := data
						}
					}
				}
			}
		}
	}
}

template (value) HNBLLIF_Message ts_HNBLLIF_GTP_CONN_DATA_REQ(template (value) uint32_t gtp_conn_id,
							      template (value) octetstring data) := {
	sapi := HNBLL_IF_SAPI_GTP,
	u := {
		gtp := {
			prim := HNBLL_IF_GTP_MSG_CONN_DATA,
			u := {
				conn_data := {
					op := HNBLL_IF_OP_REQUEST,
					u := {
						req := {
							gtp_conn_id := gtp_conn_id,
							data_len := lengthof(data),
							data := data
						}
					}
				}
			}
		}
	}
}

} with { encode "RAW" variant "BYTEORDER(first)" };
