/*
 * Generated by asn1c-0.9.28 (http://lionet.info/asn1c)
 * From ASN.1 module "HNBAP-IEs"
 * 	found in "../../asn1/hnbap/HNBAP-IEs.asn"
 * 	`asn1c -gen-PER`
 */

#include "CauseRadioNetwork.h"

int
CauseRadioNetwork_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
	/* Replace with underlying type checker */
	td->check_constraints = asn_DEF_NativeEnumerated.check_constraints;
	return td->check_constraints(td, sptr, ctfailcb, app_key);
}

/*
 * This type is implemented using NativeEnumerated,
 * so here we adjust the DEF accordingly.
 */
static void
CauseRadioNetwork_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
	td->free_struct    = asn_DEF_NativeEnumerated.free_struct;
	td->print_struct   = asn_DEF_NativeEnumerated.print_struct;
	td->check_constraints = asn_DEF_NativeEnumerated.check_constraints;
	td->ber_decoder    = asn_DEF_NativeEnumerated.ber_decoder;
	td->der_encoder    = asn_DEF_NativeEnumerated.der_encoder;
	td->xer_decoder    = asn_DEF_NativeEnumerated.xer_decoder;
	td->xer_encoder    = asn_DEF_NativeEnumerated.xer_encoder;
	td->uper_decoder   = asn_DEF_NativeEnumerated.uper_decoder;
	td->uper_encoder   = asn_DEF_NativeEnumerated.uper_encoder;
	td->aper_decoder   = asn_DEF_NativeEnumerated.aper_decoder;
	td->aper_encoder   = asn_DEF_NativeEnumerated.aper_encoder;
	if(!td->per_constraints)
		td->per_constraints = asn_DEF_NativeEnumerated.per_constraints;
	td->elements       = asn_DEF_NativeEnumerated.elements;
	td->elements_count = asn_DEF_NativeEnumerated.elements_count;
     /* td->specifics      = asn_DEF_NativeEnumerated.specifics;	// Defined explicitly */
}

void
CauseRadioNetwork_free(asn_TYPE_descriptor_t *td,
		void *struct_ptr, int contents_only) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	td->free_struct(td, struct_ptr, contents_only);
}

int
CauseRadioNetwork_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
}

asn_dec_rval_t
CauseRadioNetwork_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		void **structure, const void *bufptr, size_t size, int tag_mode) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}

asn_enc_rval_t
CauseRadioNetwork_encode_der(asn_TYPE_descriptor_t *td,
		void *structure, int tag_mode, ber_tlv_tag_t tag,
		asn_app_consume_bytes_f *cb, void *app_key) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}

asn_dec_rval_t
CauseRadioNetwork_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		void **structure, const char *opt_mname, const void *bufptr, size_t size) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
}

asn_enc_rval_t
CauseRadioNetwork_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
		int ilevel, enum xer_encoder_flags_e flags,
		asn_app_consume_bytes_f *cb, void *app_key) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
}

asn_dec_rval_t
CauseRadioNetwork_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}

asn_enc_rval_t
CauseRadioNetwork_encode_uper(asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints,
		void *structure, asn_per_outp_t *per_out) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->uper_encoder(td, constraints, structure, per_out);
}

asn_enc_rval_t
CauseRadioNetwork_encode_aper(asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints,
		void *structure, asn_per_outp_t *per_out) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->aper_encoder(td, constraints, structure, per_out);
}

asn_dec_rval_t
CauseRadioNetwork_decode_aper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
		asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
	CauseRadioNetwork_1_inherit_TYPE_descriptor(td);
	return td->aper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}

static asn_per_constraints_t asn_PER_type_CauseRadioNetwork_constr_1 GCC_NOTUSED = {
	{ APC_CONSTRAINED | APC_EXTENSIBLE,  4,  4,  0l,  13l }	/* (0..13,...) */,
	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
	0, 0	/* No PER value map */
};
static const asn_INTEGER_enum_map_t asn_MAP_CauseRadioNetwork_value2enum_1[] = {
	{ 0,	8,	"overload" },
	{ 1,	21,	"unauthorised-Location" },
	{ 2,	16,	"unauthorised-HNB" },
	{ 3,	22,	"hNB-parameter-mismatch" },
	{ 4,	19,	"invalid-UE-identity" },
	{ 5,	26,	"uE-not-allowed-on-this-HNB" },
	{ 6,	15,	"uE-unauthorised" },
	{ 7,	23,	"connection-with-UE-lost" },
	{ 8,	14,	"ue-RRC-release" },
	{ 9,	18,	"hNB-not-registered" },
	{ 10,	11,	"unspecified" },
	{ 11,	6,	"normal" },
	{ 12,	12,	"uE-relocated" },
	{ 13,	28,	"ue-registered-in-another-HNB" },
	{ 14,	34,	"no-neighbour-information-available" },
	{ 15,	45,	"iurh-connection-to-that-neighbour-not-Allowed" }
	/* This list is extensible */
};
static const unsigned int asn_MAP_CauseRadioNetwork_enum2value_1[] = {
	7,	/* connection-with-UE-lost(7) */
	9,	/* hNB-not-registered(9) */
	3,	/* hNB-parameter-mismatch(3) */
	4,	/* invalid-UE-identity(4) */
	15,	/* iurh-connection-to-that-neighbour-not-Allowed(15) */
	14,	/* no-neighbour-information-available(14) */
	11,	/* normal(11) */
	0,	/* overload(0) */
	5,	/* uE-not-allowed-on-this-HNB(5) */
	12,	/* uE-relocated(12) */
	6,	/* uE-unauthorised(6) */
	8,	/* ue-RRC-release(8) */
	13,	/* ue-registered-in-another-HNB(13) */
	2,	/* unauthorised-HNB(2) */
	1,	/* unauthorised-Location(1) */
	10	/* unspecified(10) */
	/* This list is extensible */
};
static const asn_INTEGER_specifics_t asn_SPC_CauseRadioNetwork_specs_1 = {
	asn_MAP_CauseRadioNetwork_value2enum_1,	/* "tag" => N; sorted by tag */
	asn_MAP_CauseRadioNetwork_enum2value_1,	/* N => "tag"; sorted by N */
	16,	/* Number of elements in the maps */
	15,	/* Extensions before this member */
	1,	/* Strict enumeration */
	0,	/* Native long size */
	0
};
static const ber_tlv_tag_t asn_DEF_CauseRadioNetwork_tags_1[] = {
	(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
};
asn_TYPE_descriptor_t asn_DEF_CauseRadioNetwork = {
	"CauseRadioNetwork",
	"CauseRadioNetwork",
	CauseRadioNetwork_free,
	CauseRadioNetwork_print,
	CauseRadioNetwork_constraint,
	CauseRadioNetwork_decode_ber,
	CauseRadioNetwork_encode_der,
	CauseRadioNetwork_decode_xer,
	CauseRadioNetwork_encode_xer,
	CauseRadioNetwork_decode_uper,
	CauseRadioNetwork_encode_uper,
	CauseRadioNetwork_decode_aper,
	CauseRadioNetwork_encode_aper,
	0,	/* Use generic outmost tag fetcher */
	asn_DEF_CauseRadioNetwork_tags_1,
	sizeof(asn_DEF_CauseRadioNetwork_tags_1)
		/sizeof(asn_DEF_CauseRadioNetwork_tags_1[0]), /* 1 */
	asn_DEF_CauseRadioNetwork_tags_1,	/* Same as above */
	sizeof(asn_DEF_CauseRadioNetwork_tags_1)
		/sizeof(asn_DEF_CauseRadioNetwork_tags_1[0]), /* 1 */
	&asn_PER_type_CauseRadioNetwork_constr_1,
	0, 0,	/* Defined elsewhere */
	&asn_SPC_CauseRadioNetwork_specs_1	/* Additional specs */
};

