/********************************************************************
Copyright ?2007 LGC Wireless, Inc. All rights reserved
File Name: 		aifg_mpp.c
Description:	Message process part of AIFG module
Version:		v9.0.0
Author:			Roy Jiang
Create Date:	2007-3-19

History:
2007-3-19		v9.0.0	Create
2007-7-1		v9.0.1	Apply new port process mechanism
*********************************************************************/
#include "./include/aifg_msg.h"
#include "./include/aifg_var_ext.h"

extern int msc_check_timeslot_avail(int tg_id);

//global message structure definition
aifg_msg_t sd_msg;
aifg_msg_pre_decoded rv_msg;
SP_UiPriPara sccp_msg;

int (*aifg_msg_rv_func_ptr[AIFG_MAX_MESSAGE])(
	BYTE *src, 
	aifg_msg_pre_decoded *dst, 
	BYTE msg_len);
int (*aifg_msg_sd_func_ptr[AIFG_MAX_MESSAGE])(
	aifg_msg_t *src, 
	BYTE *dst);

enum{
	AIFG_PORT_NOT_NEED = -1,
	UPPER_PROC = -1,
	LOCAL_PROC = -2,
};

int aifg_check_timeslot_avail(int tg_id)
{
	return msc_check_timeslot_avail(tg_id);
}
//Message process function definition----------------------------------------------
/*
Purpose:Convert protocol message type ot local message id
Input:	int msg_type: protocol message type
Output:	int: local message id
*/
int aifg_msgtype_to_localid(aifg_pd pd, int msg_type)
{
	aifg_msg_protocol protocol = AIFG_MSG_BSSMAP;
	
	if (pd < AIFG_PD_BSSMAP_GLOBAL)
		protocol = AIFG_MSG_DTAP;

	if(AIFG_MSG_DTAP == protocol){
		msg_type = msg_type & 0x3F;
		switch(pd){
			case AIFG_PD_DTAP_MM:
				switch(msg_type){
					//MM messages
					case AIFG_MSG_T_IMSI_DETACH_IND:
						return AIFG_MSG_ID_IMSI_DETACH_IND;
						break;
					case AIFG_MSG_T_LU_ACCEPT:
						return AIFG_MSG_ID_LU_ACCEPT;
						break;
					case AIFG_MSG_T_LU_REQUEST:
						return AIFG_MSG_ID_LU_REQUEST;
						break;
					case AIFG_MSG_T_AUTH_REQUEST:
						return AIFG_MSG_ID_AUTH_REQUEST;
						break;
					case AIFG_MSG_T_AUTH_RESPONSE:
						return AIFG_MSG_ID_AUTH_RESPONSE;
						break;
					case AIFG_MSG_T_CM_REEST_REQUEST:
						return AIFG_MSG_ID_CM_REEST_REQUEST;
						break;
					case AIFG_MSG_T_LU_REJECT:
						return AIFG_MSG_ID_LU_REJECT;
						break;
					case AIFG_MSG_T_CM_REJECT:
						return AIFG_MSG_ID_CM_REJECT;
						break;
					case AIFG_MSG_T_ABORT:
						return AIFG_MSG_ID_ABORT;
						break;
					case AIFG_MSG_T_MM_STATUS:
						return AIFG_MSG_ID_MM_STATUS;
						break;
					case AIFG_MSG_T_CM_REQUEST:
						return AIFG_MSG_ID_CM_REQUEST;
						break;
					case AIFG_MSG_T_ID_REQUEST:
						return AIFG_MSG_ID_ID_REQUEST;
						break;
					case AIFG_MSG_T_ID_RESPONSE:
						return AIFG_MSG_ID_ID_RESPONSE;
						break;
					case AIFG_MSG_T_TMSI_REALLOC_CMD:
						return AIFG_MSG_ID_TMSI_REALLOC_CMD;
						break;
					case AIFG_MSG_T_AUTH_REJECT:
						return AIFG_MSG_ID_AUTH_REJECT;
						break;
					case AIFG_MSG_T_CM_ACCEPT:
						return AIFG_MSG_ID_CM_ACCEPT;
						break;
					case AIFG_MSG_T_CM_ABORT:
						return AIFG_MSG_ID_CM_ABORT;
						break;
					case AIFG_MSG_T_TMSI_REALLOC_CMP:
						return AIFG_MSG_ID_TMSI_REALLOC_CMP;
						break;
					case AIFG_MSG_T_MM_NULL:
						return AIFG_MSG_ID_MM_NULL;
						break;
					case AIFG_MSG_T_MM_INFO:
						return AIFG_MSG_ID_MM_INFO;
						break;
					default:
						break;
				}
				break;
			case AIFG_PD_DTAP_CC:	//CC
				switch(msg_type){
					case AIFG_MSG_T_PROGRESS:
						return AIFG_MSG_ID_PROGRESS;
						break;
					case AIFG_MSG_T_MODIFY:
						return AIFG_MSG_ID_MODIFY;
						break;
					case AIFG_MSG_T_MODIFY_CMP:
						return AIFG_MSG_ID_MODIFY_CMP;
						break;
					case AIFG_MSG_T_MODIFY_REJECT:
						return AIFG_MSG_ID_MODIFY_REJECT;
						break;
					case AIFG_MSG_T_USER_INFO:
						return AIFG_MSG_ID_USER_INFO;
						break;
					case AIFG_MSG_T_DISCONNECT:
						return AIFG_MSG_ID_DISCONNECT;
						break;
					case AIFG_MSG_T_HOLD_REJECT:
						return AIFG_MSG_ID_HOLD_REJECT;
						break;
					case AIFG_MSG_T_RETRIEVE_REJECT:
						return AIFG_MSG_ID_RETRIEVE_REJECT;			
						break;
					case AIFG_MSG_T_START_DTMF_REJECT:
						return AIFG_MSG_ID_START_DTMF_REJECT;
						break;
					case AIFG_MSG_T_FACILITY:
						return AIFG_MSG_ID_FACILITY;
						break;
					case AIFG_MSG_T_CONGESTION_CTRL:
						return AIFG_MSG_ID_CONGESTION_CTRL;
						break;
					case AIFG_MSG_T_NOTIFY:
						return AIFG_MSG_ID_NOTIFY;
						break;
					case AIFG_MSG_T_START_DTMF:
						return AIFG_MSG_ID_START_DTMF;
						break;
					case AIFG_MSG_T_START_DTMF_ACK:
						return AIFG_MSG_ID_START_DTMF_ACK;
						break;
					case AIFG_MSG_T_STATUS:
						return AIFG_MSG_ID_STATUS;
						break;
					case AIFG_MSG_T_ALERTING:
						return AIFG_MSG_ID_ALERTING;		
						break;
					case AIFG_MSG_T_CALL_CONFIRMED:
						return AIFG_MSG_ID_CALL_CONFIRMED;	
						break;
					case AIFG_MSG_T_CALL_PROCEEDING:
						return AIFG_MSG_ID_CALL_PROCEEDING;
						break;
					case AIFG_MSG_T_CONNECT:
						return AIFG_MSG_ID_CONNECT;	
						break;
					case AIFG_MSG_T_EMERGENCY_SETUP:
						return AIFG_MSG_ID_EMERGENCY_SETUP;	
						break;
					case AIFG_MSG_T_RELEASE:
						return AIFG_MSG_ID_RELEASE;	
						break;
					case AIFG_MSG_T_RELEASE_CMP:
						return AIFG_MSG_ID_RELEASE_CMP;
						break;
					case AIFG_MSG_T_SETUP:
						return AIFG_MSG_ID_SETUP;
						break;
					case AIFG_MSG_T_CONNECT_ACK:
						return AIFG_MSG_ID_CONNECT_ACK;
						break;
					case AIFG_MSG_T_HOLD:
						return AIFG_MSG_ID_HOLD;
						break;
					case AIFG_MSG_T_HOLD_ACK:
						return AIFG_MSG_ID_HOLD_ACK;
						break;
					case AIFG_MSG_T_RETRIEVE:
						return AIFG_MSG_ID_RETRIEVE;
						break;
					case AIFG_MSG_T_RETRIEVE_ACK:
						return AIFG_MSG_ID_RETRIEVE_ACK;
						break;
					case AIFG_MSG_T_STATUS_ENQ:
						return AIFG_MSG_ID_STATUS_ENQ;
						break;
					case AIFG_MSG_T_STOP_DTMF:
						return AIFG_MSG_ID_STOP_DTMF;
						break;
					case AIFG_MSG_T_STOP_DTMF_ACK:
						return AIFG_MSG_ID_STOP_DTMF_ACK;
						break;
					default:
						break;
				}
				break;
			case AIFG_PD_DTAP_SMS:	//SMS messages
				switch(msg_type){
					case AIFG_MSG_T_RP_DATA_NW:
					case AIFG_MSG_T_RP_DATA_MS:
						return AIFG_MSG_ID_RP_DATA;
						break;
					case AIFG_MSG_T_RP_ACK_NW:
					case AIFG_MSG_T_RP_ACK_MS:
						return AIFG_MSG_ID_RP_ACK;
						break;
					case AIFG_MSG_T_RP_ERROR_NW:
					case AIFG_MSG_T_RP_ERROR_MS:
						return AIFG_MSG_ID_RP_ERROR;
						break;
					case AIFG_MSG_T_RP_SMMA:
						return AIFG_MSG_ID_RP_SMMA;
						break;
					default:
						break;
						}
						break;
					case AIFG_PD_DTAP_SS:	//SS messages
						switch(msg_type){
					case AIFG_MSG_T_FACILITY_SS:
						return AIFG_MSG_ID_FACILITY_SS;
						break;
					case AIFG_MSG_T_REGISTER:
						return AIFG_MSG_ID_REGISTER;
						break;
					case AIFG_MSG_T_RELEASE_CMP_SS:
						return AIFG_MSG_ID_RELEASE_CMP_SS;
						break;	
					default:
						break;
				}
				break;
			default:
				break;
		}
	}
	else if(AIFG_MSG_BSSMAP == protocol){
		switch(msg_type){
			case AIFG_MSG_T_ASSIGN_REQ:
				return AIFG_MSG_ID_ASSIGN_REQ;	
			case AIFG_MSG_T_ASSIGN_CMP:
				return AIFG_MSG_ID_ASSIGN_CMP;
				break;
			case AIFG_MSG_T_ASSIGN_FAIL:
				return AIFG_MSG_ID_ASSIGN_FAIL;
				break;
			case AIFG_MSG_T_BLOCK:
				return AIFG_MSG_ID_BLOCK;
				break;
			case AIFG_MSG_T_BLOCK_ACK:
				return AIFG_MSG_ID_BLOCK_ACK;
				break;
			case AIFG_MSG_T_UNBLOCK:
				return AIFG_MSG_ID_UNBLOCK;
				break;
			case AIFG_MSG_T_UNBLOCK_ACK:
				return AIFG_MSG_ID_UNBLOCK_ACK;
				break;
			case AIFG_MSG_T_HO_REQUEST:
				return AIFG_MSG_ID_HO_REQUEST;
				break;
			case AIFG_MSG_T_HO_REQUIRED:
				return AIFG_MSG_ID_HO_REQUIRED;
				break;
			case AIFG_MSG_T_HO_REQ_ACK:
				return AIFG_MSG_ID_HO_REQ_ACK;
				break;
			case AIFG_MSG_T_HO_CMD:
				return AIFG_MSG_ID_HO_CMD;
				break;
			case AIFG_MSG_T_HO_CMP:
				return AIFG_MSG_ID_HO_CMP;
				break;
			case AIFG_MSG_T_HO_SUC:
				return AIFG_MSG_ID_HO_SUC;
				break;
			case AIFG_MSG_T_HO_CAN_ENQ:
				return AIFG_MSG_ID_HO_CAN_ENQ;
				break;
			case AIFG_MSG_T_HO_CAN_RESP:
				return AIFG_MSG_ID_HO_CAN_RESP;
				break;
			case AIFG_MSG_T_HO_FAIL:
				return AIFG_MSG_ID_HO_FAIL;
				break;
			case AIFG_MSG_T_RESRC_REQ:
				return AIFG_MSG_ID_RESRC_REQ;
				break;
			case AIFG_MSG_T_RESRC_IND:
				return AIFG_MSG_ID_RESRC_IND;
				break;
			case AIFG_MSG_T_PAGING:
				return AIFG_MSG_ID_PAGING;
				break;
			case AIFG_MSG_T_CLR_REQ:
				return AIFG_MSG_ID_CLR_REQ;
				break;
			case AIFG_MSG_T_CLR_CMD:
				return AIFG_MSG_ID_CLR_CMD;
				break;
			case AIFG_MSG_T_CLR_CMP:
				return AIFG_MSG_ID_CLR_CMP;
				break;
			case AIFG_MSG_T_RESET:
				return AIFG_MSG_ID_RESET;
				break;
			case AIFG_MSG_T_RESET_ACK:
				return AIFG_MSG_ID_RESET_ACK;
				break;
			case AIFG_MSG_T_HO_PERFORMED:
				return AIFG_MSG_ID_HO_PERFORMED;
				break;
			case AIFG_MSG_T_OVERLOAD:
				return AIFG_MSG_ID_OVERLOAD;
				break;
			case AIFG_MSG_T_MSC_INVK_TRACE:
				return AIFG_MSG_ID_MSC_INVK_TRACE;
				break;
			case AIFG_MSG_T_BSC_INVK_TRACE:
				return AIFG_MSG_ID_BSC_INVK_TRACE;
				break;
			case AIFG_MSG_T_CM_UPDATE:
				return AIFG_MSG_ID_CM_UPDATE;
				break;case AIFG_MSG_T_CIPHER_MODE_CMD:
				return AIFG_MSG_ID_CIPHER_MODE_CMD;
				break;
			case AIFG_MSG_T_CIPHER_MODE_CMP:
				return AIFG_MSG_ID_CIPHER_MODE_CMP;
				break;
			case AIFG_MSG_T_L3_INFO:
				return AIFG_MSG_ID_L3_INFO;
				break;
			case AIFG_MSG_T_QUEUE_IND:
				return AIFG_MSG_ID_QUEUE_IND;
				break;
			case AIFG_MSG_T_SAPI_REJ:
				return AIFG_MSG_ID_SAPI_REJ;
				break;
			case AIFG_MSG_T_HO_REQ_REJ:
				return AIFG_MSG_ID_HO_REQ_REJ;
				break;
			case AIFG_MSG_T_RESET_CC:
				return AIFG_MSG_ID_RESET_CC;
				break;
			case AIFG_MSG_T_RESET_CC_ACK:
				return AIFG_MSG_ID_RESET_CC_ACK;
				break;
			case AIFG_MSG_T_HO_DETECT:
				return AIFG_MSG_ID_HO_DETECT;
				break;
			case AIFG_MSG_T_CC_GROUP_BLK:
				return AIFG_MSG_ID_CC_GROUP_BLK;
				break;
			case AIFG_MSG_T_CC_GROUP_BLK_ACK:
				return AIFG_MSG_ID_CC_GROUP_BLK_ACK;
				break;
			case AIFG_MSG_T_CC_GROUP_UNBLK:
				return AIFG_MSG_ID_CC_GROUP_UNBLK;
				break;
			case AIFG_MSG_T_CC_GROUP_UNBLK_ACK:
				return AIFG_MSG_ID_CC_GROUP_UNBLK_ACK;
				break;
			case AIFG_MSG_T_CONFUSION:
				return AIFG_MSG_ID_CONFUSION;
				break;
			case AIFG_MSG_T_CM_REQUEST:
				return AIFG_MSG_ID_CM_REQUEST;
				break;
			case AIFG_MSG_T_UNEQUIP_CC:
				return AIFG_MSG_ID_UNEQUIP_CC;
				break;
			case AIFG_MSG_T_CIPHER_MODE_REJ:
				return AIFG_MSG_ID_CIPHER_MODE_REJ;
				break;
			case AIFG_MSG_T_LOAD_IND:
				return AIFG_MSG_ID_LOAD_IND;
				break;
			case AIFG_MSG_T_SUSPEND:
				return AIFG_MSG_ID_SUSPEND;
				break;
			case AIFG_MSG_T_RESUME:
				return AIFG_MSG_ID_RESUME;
				break;
			case AIFG_MSG_T_CHANGE_CC:
				return AIFG_MSG_ID_CHANGE_CC;
				break;
			case AIFG_MSG_T_CHANGE_CC_ACK:
				return AIFG_MSG_ID_CHANGE_CC_ACK;
				break;
				//case AIFG_MSG_T_LSA_INFO:
				//	return AIFG_MSG_ID_LSA_INFO;
				//break;
			case AIFG_MSG_T_LOC_INFO_CMD:
				return AIFG_MSG_ID_LOC_INFO_CMD;
				break;
			case AIFG_MSG_T_LOC_INFO_RPT:
				return AIFG_MSG_ID_LOC_INFO_RPT;
				break;
			default:
				break;
		}
	}

	aifg_event = AIFG_ERR_UNKNOW_MSG;
	return AIFG_ERROR;
}

/*
Name: 	aifg_msg_proc
Purpose:Process received AIF message
Input:	aifg_msg *src: Pointer to first byte of raw message
aifg_msg_pre_decoded *dst: target message structure
int sapid: SAP ID
Output:	result
*/
int aifg_msg_proc(BYTE *src, aifg_msg_pre_decoded *dst)
{
	int msg_len = 0, offset = 0;
	int pd, ti;
	aifg_msg_protocol protocol;
	aifg_msg_type msg_type;
	aifg_msg_id msg_id;

	assert(src != NULL);
	assert(dst != NULL);

	memset(&dst->msg, 0, sizeof(dst->msg));

	if ((protocol = src[0]) == 2){
		protocol = 0;	//protocol=2, redirected BSSMAP message
	}

	switch(protocol){
		case AIFG_MSG_DTAP:
			msg_len = src[2] - 2;	//skip pd/ti and msg type
			pd = src[3] & 0x0F;
			if(AIFG_PD_DTAP_MM != pd){
				ti = src[3] >> 4;
				if(ti >= 8)
					ti = ti & 0x07;	//set ti flag to assigned by local
				else
					ti = ti | 0x08;	//set ti flag to assigned by remote
			}
			else
				ti = -1;	//ti not present

			if(AIFG_PD_DTAP_SMS == pd){
				//get RP type
				msg_type = src[4];
				msg_len = src[5];
				if(msg_type == AIFG_MSG_T_CP_DATA)
					msg_id = aifg_msgtype_to_localid(pd, src[6]);
				else{
					dst->id = AIFG_MSG_ID_IGNORED_MSG;	//ignore CP-ACK, CP-ERROR
					goto FINISH;
				}
				offset += 7;
			}
			else{
				msg_id = aifg_msgtype_to_localid(pd, src[4]);
				offset += 5;
			}

			if(AIFG_ERROR == msg_id)
				goto ERR_PROC;

			break;
		case AIFG_MSG_BSSMAP:
			msg_len = src[1] - 1;	//skip msg type
			msg_id = aifg_msgtype_to_localid(AIFG_PD_BSSMAP_GLOBAL, src[2]);
			if(AIFG_ERROR == msg_id)
				goto ERR_PROC;

			if(msg_id <= AIFG_MSG_ID_HO_CAN_RESP)
				pd = AIFG_PD_BSSMAP_GLOBAL;
			else
				pd = AIFG_PD_BSSMAP_DEDICATED;

			ti = -1;
			offset += 3;
			break;
		default:
			//Unknown message, ignore
			aifg_debug_print(-1, AIFG_ERR_UNKNOW_MSG, NULL, 0);
			goto ERR_PROC;
			break;
	}
	if (msg_len < 0 || msg_len >= 256)
		goto ERR_PROC;

	dst->id = msg_id;
	dst->ti = ti;	
	dst->pd = pd;

	//predecode message
	if(NULL != aifg_msg_rv_func_ptr[msg_id]){
		if(AIFG_SUCCEED != (aifg_msg_rv_func_ptr[msg_id])(&(src[offset]), dst, msg_len)){
			aifg_debug_print(-1, AIFG_ERR_ERROR_MSG, NULL, 0);
			goto ERR_PROC;
		}
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

void aifg_msg_redirect(SP_UiPriPara *msg)
{
	BYTE *pdata = NULL;

	if(AIFG_RUN_MODE_SINGLE == dual_server.mode)
		return;

	if (msg->uUiPri == N_UNITDATA_IND)
		pdata = msg->tPriUnion.tPriNUDataInd.tUD.aUserData;
	else
		pdata = msg->tPriUnion.tPriNConnInd.tUD.aUserData;

	if (pdata[0] == 0x02){
		return; //already redirected, discard
	}

	aifg_debug_print(-1, AIFG_EVENT_REDIR_MSG, msg, 0);
	pdata[0] = 0x02; //WXC2 system private BSSAP msg type, used for msg redirect
	PostSp(msg);
}
//End of message process function definition-----------------------------------------



//RV message process functions definition----------------------------------------------
/*
Remark for all message encode functions
Input:	BYTE *src: raw code of message to be processed
aifg_msg_pre_decoded *dst: target struct where the decoded information to be stored in
Output:	int	- result	AIFG_SUCCEED / AIFG_ERROR, detailed info stored in aifg_event
*/
//For embedded DTAP messages in BSSMAP message
int aifg_msg_decode_embeded_l3msg(BYTE *src, aifg_msg_predecode_l3msg *l3msg)
{
	int offset = 1;

	switch(src[offset++]){	//message type
		case AIFG_MSG_T_CM_REQUEST:
			l3msg->id = AIFG_MSG_ID_CM_REQUEST;
			memset(&(l3msg->msg.cmRequest), 0, sizeof(l3msg->msg.cmRequest));

			//CM service type
			l3msg->msg.cmRequest.type.iei = AIFG_IE_ID_DT_CMTYPE;
			l3msg->msg.cmRequest.type.ptr = src + offset;
			l3msg->msg.cmRequest.type.hi_lo_flag = AIFG_LOW_BITS;

			//Ciphering key sequence number - M
			l3msg->msg.cmRequest.cipherKeySeq.iei = AIFG_IE_ID_DT_CIPHERKEY;
			l3msg->msg.cmRequest.cipherKeySeq.ptr = src + offset;
			l3msg->msg.cmRequest.cipherKeySeq.hi_lo_flag = AIFG_HIGH_BITS;
			offset++;

			//Mobile station classmark 2 - M
			l3msg->msg.cmRequest.cm2.iei = AIFG_IE_ID_DT_MSCM2;
			l3msg->msg.cmRequest.cm2.ptr = src + offset;
			offset += src[offset] + 1;

			//Mobile identity - M
			l3msg->msg.cmRequest.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
			l3msg->msg.cmRequest.mobileId.ptr = src + offset;
			offset += src[offset] + 1;

			//Priority
			if((src[offset]&0xF0) == AIFG_IEI_DT_PRIORITYLEVEL){
				l3msg->msg.cmRequest.priority.iei = AIFG_IE_ID_DT_PRIORITYLEVEL;
				l3msg->msg.cmRequest.priority.ptr = src + offset;
			}
			break;

		case AIFG_MSG_T_LU_REQUEST:
			l3msg->id = AIFG_MSG_ID_LU_REQUEST;
			memset(&(l3msg->msg.luRequest), 0, sizeof(l3msg->msg.luRequest));

			//Location updating type - M
			l3msg->msg.luRequest.type.iei = AIFG_IE_ID_DT_LUTYPE;
			l3msg->msg.luRequest.type.ptr = src + offset;
			l3msg->msg.luRequest.type.hi_lo_flag = AIFG_LOW_BITS;

			//Ciphering key sequence number - M
			l3msg->msg.luRequest.cipherKeySeq.iei = AIFG_IE_ID_DT_CIPHERKEY;
			l3msg->msg.luRequest.cipherKeySeq.ptr = src + offset;
			l3msg->msg.luRequest.cipherKeySeq.hi_lo_flag = AIFG_HIGH_BITS;
			offset++;

			//Location area identification - M
			l3msg->msg.luRequest.lai.iei = AIFG_IE_ID_DT_LAI;
			l3msg->msg.luRequest.lai.ptr = src + offset;
			offset += 5;

			//Mobile station classmark 1 - M
			l3msg->msg.luRequest.cm1.iei = AIFG_IE_ID_DT_MSCM1;
			l3msg->msg.luRequest.cm1.ptr = src + offset;
			offset++;

			//Mobile identity - M
			l3msg->msg.luRequest.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
			l3msg->msg.luRequest.mobileId.ptr = src + offset;
			break;

		case AIFG_MSG_T_CM_REEST_REQUEST:
			l3msg->id = AIFG_MSG_ID_CM_REEST_REQUEST;
			memset(&(l3msg->msg.cmReEstReq), 0, sizeof(l3msg->msg.cmReEstReq));

			//Ciphering key sequence number - M
			l3msg->msg.cmReEstReq.cipherKeySeq.iei = AIFG_IE_ID_DT_CIPHERKEY;
			l3msg->msg.cmReEstReq.cipherKeySeq.ptr = src + offset;
			l3msg->msg.cmReEstReq.cipherKeySeq.hi_lo_flag = AIFG_LOW_BITS;
			offset++;

			//Mobile station classmark 2 - M
			l3msg->msg.cmReEstReq.cm2.iei = AIFG_IE_ID_DT_MSCM2;
			l3msg->msg.cmReEstReq.cm2.ptr = src + offset;
			offset += src[offset] + 1;

			//Mobile identity - M
			l3msg->msg.cmReEstReq.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
			l3msg->msg.cmReEstReq.mobileId.ptr = src + offset;
			offset += src[offset] + 1;

			//Location area identification
			if(src[offset] == AIFG_IEI_DT_LAI){
				offset++;	//skip iei
				l3msg->msg.cmReEstReq.lai.iei = AIFG_IE_ID_DT_LAI;
				l3msg->msg.cmReEstReq.lai.ptr = src + offset;
			}
			break;

		case AIFG_MSG_T_PAGING_RESP:
			l3msg->id = AIFG_MSG_ID_PAGING_RESP;
			memset(&(l3msg->msg.pagingResp), 0, sizeof(l3msg->msg.pagingResp));

			//Ciphering key sequence number - M
			l3msg->msg.pagingResp.cipherKeySeq.iei = AIFG_IE_ID_DT_CIPHERKEY;
			l3msg->msg.pagingResp.cipherKeySeq.ptr = src+offset;
			l3msg->msg.pagingResp.cipherKeySeq.hi_lo_flag = AIFG_LOW_BITS;
			offset++;

			//Mobile station classmark 2 - M
			l3msg->msg.pagingResp.cm2.iei = AIFG_IE_ID_DT_MSCM2;
			l3msg->msg.pagingResp.cm2.ptr = src + offset;
			offset += src[offset] + 1;

			//Mobile identity - M
			l3msg->msg.pagingResp.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
			l3msg->msg.pagingResp.mobileId.ptr = src + offset;
			offset += src[offset] + 1;
			break;

		case AIFG_MSG_T_IMSI_DETACH_IND:
			l3msg->id = AIFG_MSG_ID_IMSI_DETACH_IND;
			memset(&(l3msg->msg.imsiDetachInd), 0, sizeof(l3msg->msg.imsiDetachInd));

			//Mobile station classmark 1 - M
			l3msg->msg.imsiDetachInd.cm1.iei = AIFG_IE_ID_DT_MSCM1;
			l3msg->msg.imsiDetachInd.cm1.ptr = src + offset;
			offset++;

			//Mobile identity - M
			l3msg->msg.imsiDetachInd.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
			l3msg->msg.imsiDetachInd.mobileId.ptr = src + offset;
			break;

		case AIFG_MSG_T_RR_HO_CMD:
			//TODO
			break;

		default:
			aifg_event = AIFG_ERR_ERROR_MSG;
			goto ERR_PROC;
			break;
	}

	return AIFG_SUCCEED;

ERR_PROC:
	return AIFG_ERROR;
}

//For assign request
int aifg_msg_rv_assignReq(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.assignReq), 0, sizeof(dst->msg.assignReq));

	//channal type - M
	if(src[offset] != AIFG_IEI_BM_CHANNELTYPE)
		goto ERR_PROC;
	offset++;
	dst->msg.assignReq.channelType.iei = AIFG_IE_ID_BM_CHANNELTYPE;
	dst->msg.assignReq.channelType.ptr = src+offset;
	offset += src[offset] + 1;

	if(offset >= msg_len) goto FINISH;

	//L3 header information
	if(src[offset] == AIFG_IEI_BM_L3HEADERINFO){
		offset++;
		dst->msg.assignReq.l3HeaderInfo.iei = AIFG_IE_ID_BM_L3HEADERINFO;
		dst->msg.assignReq.l3HeaderInfo.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//priority
	if(src[offset] == AIFG_IEI_BM_PRIORITY){
		offset++;
		dst->msg.assignReq.priority.iei = AIFG_IE_ID_BM_PRIORITY;
		dst->msg.assignReq.priority.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//CIC
	if(src[offset] == AIFG_IEI_BM_CIC){
		offset++;
		dst->msg.assignReq.cic.iei = AIFG_IE_ID_BM_CIC;
		dst->msg.assignReq.cic.ptr = src+offset;
		offset += 2;
		if(offset >= msg_len) goto FINISH;
	}

	//DTX flag
	if(src[offset] == AIFG_IEI_BM_DTXFLAG){
		offset++;
		dst->msg.assignReq.dtxFlag.iei = AIFG_IE_ID_BM_DTXFLAG;
		dst->msg.assignReq.dtxFlag.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Interference Band To Be Used
	if(src[offset] == AIFG_IEI_BM_BANDUSED){
		offset++;
		dst->msg.assignReq.bandUsed.iei = AIFG_IE_ID_BM_BANDUSED;
		dst->msg.assignReq.bandUsed.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Classmark Information 2
	if(src[offset] == AIFG_IEI_BM_CLASSMARKINFO2){
		offset++;
		dst->msg.assignReq.cmInfo2.iei = AIFG_IE_ID_BM_CLASSMARKINFO2;
		dst->msg.assignReq.cmInfo2.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Group Call Reference
	if(src[offset] == AIFG_IEI_BM_GROUPCALLREF){
		offset++;
		dst->msg.assignReq.groupRef.iei = AIFG_IE_ID_BM_GROUPCALLREF;
		dst->msg.assignReq.groupRef.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Talker Flag
	if(src[offset] == AIFG_IEI_BM_TALKERFLAG){
		dst->msg.assignReq.talkerFlag.iei = AIFG_IE_ID_BM_TALKERFLAG;
		dst->msg.assignReq.talkerFlag.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Configuration Evolution Indication
	if(src[offset] == AIFG_IEI_BM_CFGEVOIND){
		offset++;
		dst->msg.assignReq.cfgEvoInd.iei = AIFG_IE_ID_BM_CFGEVOIND;
		dst->msg.assignReq.cfgEvoInd.ptr = src+offset;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//for assign complete
int aifg_msg_rv_assignComplete(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.assignComplete), 0, sizeof(dst->msg.assignComplete));

	//RR cause
	if(src[offset] == AIFG_IEI_BM_RRCAUSE){
		offset++;
		dst->msg.assignComplete.rrcause.iei = AIFG_IE_ID_BM_RRCAUSE;
		dst->msg.assignComplete.rrcause.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//CIC
	if(src[offset] == AIFG_IEI_BM_CIC){
		offset++;
		dst->msg.assignComplete.cic.iei = AIFG_IE_ID_BM_CIC;
		dst->msg.assignComplete.cic.ptr = src+offset;
		offset += 2;
		if(offset >= msg_len) goto FINISH;
	}

	//Cell Identifier
	if(src[offset] == AIFG_IEI_BM_CELLID){
		offset++;
		dst->msg.assignComplete.cellId.iei = AIFG_IE_ID_BM_CELLID;
		dst->msg.assignComplete.cellId.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Chosen Channel
	if(src[offset] == AIFG_IEI_BM_CHOSENCHANNEL){
		offset++;
		dst->msg.assignComplete.chosenChannel.iei = AIFG_IE_ID_BM_CHOSENCHANNEL;
		dst->msg.assignComplete.chosenChannel.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Chosen Encryption Algorithm
	if(src[offset] == AIFG_IEI_BM_CHOSENENCRYPT){
		offset++;
		dst->msg.assignComplete.chosenEncrypt.iei = AIFG_IE_ID_BM_CHOSENENCRYPT;
		dst->msg.assignComplete.chosenEncrypt.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Circuit Pool
	if(src[offset] == AIFG_IEI_BM_CIRCUITPOOL){
		offset++;
		dst->msg.assignComplete.circuitPool.iei = AIFG_IE_ID_BM_CIRCUITPOOL;
		dst->msg.assignComplete.circuitPool.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Speech Version (Chosen)
	if(src[offset] == AIFG_IEI_BM_SPEECHVER){
		offset++;
		dst->msg.assignComplete.speechVer.iei = AIFG_IE_ID_BM_SPEECHVER;
		dst->msg.assignComplete.speechVer.ptr = src+offset;
		offset++;
	}
	if(offset >= msg_len) goto FINISH;

	//LSA Identifier
	if(src[offset] == AIFG_IEI_BM_LSAID){
		offset++;
		dst->msg.assignComplete.lsaId.iei = AIFG_IE_ID_BM_LSAID;
		dst->msg.assignComplete.lsaId.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;
}

//for assign failure
int aifg_msg_rv_assignFailure(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.assignFailure), 0, sizeof(dst->msg.assignFailure));

	//Cause	- M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.assignFailure.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.assignFailure.cause.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//RR cause
	if(src[offset] == AIFG_IEI_BM_RRCAUSE){
		offset++;
		dst->msg.assignFailure.rrcause.iei = AIFG_IE_ID_BM_RRCAUSE;
		dst->msg.assignFailure.rrcause.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Circuit Pool
	if(src[offset] == AIFG_IEI_BM_CIRCUITPOOL){
		offset++;
		dst->msg.assignFailure.circuitPool.iei = AIFG_IE_ID_BM_CIRCUITPOOL;
		dst->msg.assignFailure.circuitPool.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Circuit Pool List
	if(src[offset] == AIFG_IEI_BM_CIRCUITPOOLLIST){
		offset++;
		dst->msg.assignFailure.circuitPoolList.iei = AIFG_IE_ID_BM_CIRCUITPOOLLIST;
		dst->msg.assignFailure.circuitPoolList.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//for block
int aifg_msg_rv_block(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.block), 0, sizeof(dst->msg.block));

	//CIC - M
	if(src[offset] != AIFG_IEI_BM_CIC)
		goto ERR_PROC;
	offset++;
	dst->msg.block.cic.iei = AIFG_IE_ID_BM_CIC;
	dst->msg.block.cic.ptr = src+offset;
	offset += 2;

	//Cause	- M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.block.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.block.cause.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Connection Release Requested
	if(src[offset] == AIFG_IEI_BM_CONNRELREQ){
		dst->msg.block.connectionRelReq.iei = AIFG_IE_ID_BM_CONNRELREQ;
		dst->msg.block.connectionRelReq.ptr = src+offset;
		offset++;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//for block ack
int aifg_msg_rv_blockAck(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	return AIFG_SUCCEED;
}

//for unblock
int aifg_msg_rv_unBlock(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.blockAck), 0, sizeof(dst->msg.blockAck));

	//CIC - M
	if(src[offset] != AIFG_IEI_BM_CIC)
		goto ERR_PROC;
	offset++;
	dst->msg.unblock.cic.iei = AIFG_IE_ID_BM_CIC;
	dst->msg.unblock.cic.ptr = src+offset;
	offset += 2;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//for unblock ack
int aifg_msg_rv_unBlockAck(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{	
	return AIFG_SUCCEED;
}

//for HANDOVER REQUEST
int aifg_msg_rv_HORequest(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HORequest), 0, sizeof(dst->msg.HORequest));

	//channal type - M
	if(src[offset] != AIFG_IEI_BM_CHANNELTYPE)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequest.channelType.iei = AIFG_IE_ID_BM_CHANNELTYPE;
	dst->msg.HORequest.channelType.ptr = src+offset;
	offset += src[offset] + 1;

	//Encryption Information - M
	if(src[offset] != AIFG_IEI_BM_ENCRYPTINFO)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequest.encryptInfo.iei = AIFG_IE_ID_BM_ENCRYPTINFO;
	dst->msg.HORequest.encryptInfo.ptr = src+offset;
	offset += src[offset] + 1;

	//Classmark Information 1 - M
	if(src[offset] == AIFG_IEI_BM_CLASSMARKINFO1){
		offset++;
		dst->msg.HORequest.cmInfo1.iei = AIFG_IE_ID_BM_CLASSMARKINFO1;
		dst->msg.HORequest.cmInfo1.ptr = src+offset;
		offset++;
	}
	else if(src[offset] == AIFG_IEI_BM_CLASSMARKINFO2){
		offset++;
		dst->msg.HORequest.cmInfo2.iei = AIFG_IE_ID_BM_CLASSMARKINFO2;
		dst->msg.HORequest.cmInfo2.ptr = src+offset;
		offset += src[offset] + 1;
	}
	else
		goto ERR_PROC;

	//Cell Identifier (Serving) - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequest.serving_cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.HORequest.serving_cellId.ptr = src+offset;
	offset += src[offset] + 1;

	//Priority
	if(src[offset] == AIFG_IEI_BM_PRIORITY){
		offset++;
		dst->msg.HORequest.priority.iei = AIFG_IE_ID_BM_PRIORITY;
		dst->msg.HORequest.priority.ptr = src+offset;
		offset += src[offset] + 1;
	}

	//CIC
	if(src[offset] == AIFG_IEI_BM_CIC){
		offset++;
		dst->msg.HORequest.cic.iei = AIFG_IE_ID_BM_CIC;
		dst->msg.HORequest.cic.ptr = src+offset;
		offset += 2;
	}

	//Downlink DTX Flag
	if(src[offset] == AIFG_IEI_BM_DTXFLAG){
		offset++;
		dst->msg.HORequest.dtxFlag.iei = AIFG_IE_ID_BM_DTXFLAG;
		dst->msg.HORequest.dtxFlag.ptr = src+offset;
		offset++;
	}

	//Cell Identifier (Target) - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequest.target_cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.HORequest.target_cellId.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Interference Band To Be Used
	if(src[offset] == AIFG_IEI_BM_BANDUSED){
		offset++;
		dst->msg.HORequest.bandUsed.iei = AIFG_IE_ID_BM_BANDUSED;
		dst->msg.HORequest.bandUsed.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Cause
	if(src[offset] == AIFG_IEI_BM_CAUSE){
		offset++;
		dst->msg.HORequest.cause.iei = AIFG_IE_ID_BM_CAUSE;
		dst->msg.HORequest.cause.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Classmark Information 3
	if(src[offset] == AIFG_IEI_BM_CLASSMARKINFO3){
		offset++;
		dst->msg.HORequest.cmInfo3.iei = AIFG_IE_ID_BM_CLASSMARKINFO3;
		dst->msg.HORequest.cmInfo3.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Current Channel type 1
	if(src[offset] == AIFG_IEI_BM_CURCHANNELTYPE1){
		offset++;
		dst->msg.HORequest.curChanneltype1.iei = AIFG_IE_ID_BM_CURCHANNELTYPE1;
		dst->msg.HORequest.curChanneltype1.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Speech Version (Used)
	if(src[offset] == AIFG_IEI_BM_SPEECHVER){
		offset++;
		dst->msg.HORequest.speechVer.iei = AIFG_IE_ID_BM_SPEECHVER;
		dst->msg.HORequest.speechVer.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Group Call Reference
	if(src[offset] == AIFG_IEI_BM_GROUPCALLREF){
		offset++;
		dst->msg.HORequest.groupCallRef.iei = AIFG_IE_ID_BM_GROUPCALLREF;
		dst->msg.HORequest.groupCallRef.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Talker Flag
	if(src[offset] == AIFG_IEI_BM_TALKERFLAG){
		dst->msg.HORequest.talkerFlag.iei = AIFG_IE_ID_BM_TALKERFLAG;
		dst->msg.HORequest.talkerFlag.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Configuration Evolution Indication
	if(src[offset] == AIFG_IEI_BM_CFGEVOIND){
		offset++;
		dst->msg.HORequest.cfgEvoInd.iei = AIFG_IE_ID_BM_CFGEVOIND;
		dst->msg.HORequest.cfgEvoInd.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Chosen Encryption Algorithm (Serving)
	if(src[offset] == AIFG_IEI_BM_CHOSENENCRYPT){
		offset++;
		dst->msg.HORequest.chosenEncrypt.iei = AIFG_IE_ID_BM_CHOSENENCRYPT;
		dst->msg.HORequest.chosenEncrypt.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Old BSS to New BSS Information
	if(src[offset] == AIFG_IEI_BM_BSSOLDTONEW){
		offset++;
		dst->msg.HORequest.oldBssToNew.iei = AIFG_IE_ID_BM_BSSOLDTONEW;
		dst->msg.HORequest.oldBssToNew.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//LSA Information
	if(src[offset] == AIFG_IEI_BM_LSAINFO){
		offset++;
		dst->msg.HORequest.lsaInfo.iei = AIFG_IE_ID_BM_LSAINFO;
		dst->msg.HORequest.lsaInfo.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:	
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}


//for HANDOVER REQUIRED
int aifg_msg_rv_HORequired(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HORequired), 0, sizeof(dst->msg.HORequired));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequired.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.HORequired.cause.ptr = src+offset;
	offset += src[offset] + 1;


	//Response Request
	if(src[offset] == AIFG_IEI_BM_RESPREQ){
		dst->msg.HORequired.respReq.iei = AIFG_IE_ID_BM_RESPREQ;
		dst->msg.HORequired.respReq.ptr = src+offset;
		offset++;
	}

	//Cell Identifier List (Preferred) - M
	if(src[offset] != AIFG_IEI_BM_CELLIDLIST)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequired.cellIdList.iei = AIFG_IE_ID_BM_CELLIDLIST;
	dst->msg.HORequired.cellIdList.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Circuit Pool List
	if(src[offset] == AIFG_IEI_BM_CIRCUITPOOLLIST){
		offset++;
		dst->msg.HORequired.circuitPoolList.iei = AIFG_IE_ID_BM_CIRCUITPOOLLIST;
		dst->msg.HORequired.circuitPoolList.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Current Channel type 1
	if(src[offset] == AIFG_IEI_BM_CURCHANNELTYPE1){
		offset++;
		dst->msg.HORequired.curChannelType1.iei = AIFG_IE_ID_BM_CURCHANNELTYPE1;
		dst->msg.HORequired.curChannelType1.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Speech Version (Used)
	if(src[offset] == AIFG_IEI_BM_SPEECHVER){
		offset++;
		dst->msg.HORequired.speechVer.iei = AIFG_IE_ID_BM_SPEECHVER;
		dst->msg.HORequired.speechVer.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Queueing Indicator
	if(src[offset] == AIFG_IEI_BM_QUEUEIND){
		offset++;
		dst->msg.HORequired.queInd.iei = AIFG_IE_ID_BM_QUEUEIND;
		dst->msg.HORequired.queInd.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Old BSS to New BSS Information
	if(src[offset] == AIFG_IEI_BM_BSSOLDTONEW){
		offset++;
		dst->msg.HORequired.oldBssToNew.iei = AIFG_IE_ID_BM_BSSOLDTONEW;
		dst->msg.HORequired.oldBssToNew.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//for HANDOVER REQUEST ACK
int aifg_msg_rv_HORequestAck(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HORequestAck), 0, sizeof(dst->msg.HORequestAck));

	//Layer 3 Information - M
	if(src[offset] != AIFG_IEI_BM_L3INFO)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequestAck.l3Info.len = src[offset++];
	dst->msg.HORequestAck.l3Info.ptr = src + offset;
	offset += src[offset] + 1;

	//Chosen Channel
	if(src[offset] == AIFG_IEI_BM_CHOSENCHANNEL){
		offset++;
		dst->msg.HORequestAck.chosenChannel.iei = AIFG_IE_ID_BM_CHOSENCHANNEL;
		dst->msg.HORequestAck.chosenChannel.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Chosen Encryption Algorithm
	if(src[offset] == AIFG_IEI_BM_CHOSENENCRYPT){
		offset++;
		dst->msg.HORequestAck.chosenEncrypt.iei = AIFG_IE_ID_BM_CHOSENENCRYPT;
		dst->msg.HORequestAck.chosenEncrypt.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Circuit Pool
	if(src[offset] == AIFG_IEI_BM_CIRCUITPOOL){
		offset++;
		dst->msg.HORequestAck.circuitPool.iei = AIFG_IE_ID_BM_CIRCUITPOOL;
		dst->msg.HORequestAck.circuitPool.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Speech Version
	if(src[offset] == AIFG_IEI_BM_SPEECHVER){
		offset++;
		dst->msg.HORequestAck.speechVer.iei = AIFG_IE_ID_BM_SPEECHVER;
		dst->msg.HORequestAck.speechVer.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//CIC
	if(src[offset] == AIFG_IEI_BM_CIC){
		offset++;
		dst->msg.HORequestAck.cic.iei = AIFG_IE_ID_BM_CIC;
		dst->msg.HORequestAck.cic.ptr = src+offset;
		offset += 2;
		if(offset >= msg_len) goto FINISH;
	}

	//LSA Identifier
	if(src[offset] == AIFG_IEI_BM_LSAID){
		offset++;
		dst->msg.HORequestAck.lsaId.iei = AIFG_IE_ID_BM_LSAID;
		dst->msg.HORequestAck.lsaId.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//for HANDOVER COMMAND
int aifg_msg_rv_HOCmd(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HOCmd), 0, sizeof(dst->msg.HOCmd));

	//Layer 3 Information - M
	if(src[offset] != AIFG_IEI_BM_L3INFO)
		goto ERR_PROC;
	offset++;
	if(AIFG_ERROR == aifg_msg_decode_embeded_l3msg(&(src[offset+1]), &(dst->msg.HOCmd.l3msg)))
		goto ERR_PROC;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Cell Identifier
	if(src[offset] == AIFG_IEI_BM_CELLID){
		offset++;
		dst->msg.HOCmd.cellId.iei = AIFG_IE_ID_BM_CELLID;
		dst->msg.HOCmd.cellId.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//for HANDOVER COMPLETE
int aifg_msg_rv_HOComplete(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HOComplete), 0, sizeof(dst->msg.HOComplete));

	//RR cause
	if(src[offset] == AIFG_IEI_BM_RRCAUSE){
		offset++;
		dst->msg.HOComplete.rrcause.iei = AIFG_IE_ID_BM_RRCAUSE;
		dst->msg.HOComplete.rrcause.ptr = src+offset;
		offset++;
	}

	return AIFG_SUCCEED;
}

//HANDOVER CANDIDATE ENQUIRE
int aifg_msg_rv_HOCandEnq(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HOCandEnq), 0, sizeof(dst->msg.HOCandEnq));

	//Number Of Mss - M
	if(src[offset] != AIFG_IEI_BM_MSNUM)
		goto ERR_PROC;
	offset++;
	dst->msg.HOCandEnq.msNum.iei = AIFG_IE_ID_BM_MSNUM;
	dst->msg.HOCandEnq.msNum.ptr = src+offset;
	offset++;

	//Cell Identifier List - M
	if(src[offset] != AIFG_IEI_BM_CELLIDLIST)
		goto ERR_PROC;
	offset++;
	dst->msg.HOCandEnq.cellIdList.iei = AIFG_IE_ID_BM_CELLIDLIST;
	dst->msg.HOCandEnq.cellIdList.ptr = src+offset;
	offset += src[offset] + 1;

	//Cell Identifier - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.HOCandEnq.cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.HOCandEnq.cellId.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//HANDOVER CANDIDATE RESPONSE
int aifg_msg_rv_HOCandResp(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HOCandResp), 0, sizeof(dst->msg.HOCandResp));

	//Number Of Mss - M
	if(src[offset] != AIFG_IEI_BM_MSNUM)
		goto ERR_PROC;
	offset++;
	dst->msg.HOCandResp.msNum.iei = AIFG_IE_ID_BM_MSNUM;
	dst->msg.HOCandResp.msNum.ptr = src+offset;
	offset++;

	//Cell Identifier - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.HOCandResp.cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.HOCandResp.cellId.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//HANDOVER FAILURE
int aifg_msg_rv_HOFailure(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HOFailure), 0, sizeof(dst->msg.HOFailure));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.HOFailure.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.HOFailure.cause.ptr = src+offset;
	offset += src[offset] + 1;

	//RR cause
	if(src[offset] == AIFG_IEI_BM_RRCAUSE){
		offset++;
		dst->msg.HOFailure.rrcause.iei = AIFG_IE_ID_BM_RRCAUSE;
		dst->msg.HOFailure.rrcause.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Circuit Pool
	if(src[offset] == AIFG_IEI_BM_CIRCUITPOOL){
		offset++;
		dst->msg.HOFailure.circuitPool.iei = AIFG_IE_ID_BM_CIRCUITPOOL;
		dst->msg.HOFailure.circuitPool.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Circuit Pool List
	if(src[offset] == AIFG_IEI_BM_CIRCUITPOOLLIST){
		offset++;
		dst->msg.HOFailure.circuitPoolList.iei = AIFG_IE_ID_BM_CIRCUITPOOLLIST;
		dst->msg.HOFailure.circuitPoolList.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//RESOURCE REQUEST
int aifg_msg_rv_resrcReq(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.resrcReq), 0, sizeof(dst->msg.resrcReq));

	//Periodicity - M
	if(src[offset] != AIFG_IEI_BM_PERIODICITY)
		goto ERR_PROC;
	offset++;
	dst->msg.resrcReq.periodicity.iei = AIFG_IE_ID_BM_PERIODICITY;
	dst->msg.resrcReq.periodicity.ptr = src+offset;
	offset++;

	//Resource Indication Method - M
	if(src[offset] != AIFG_IEI_BM_RESOURCEINDMEHTOD)
		goto ERR_PROC;
	offset++;
	dst->msg.resrcReq.resrcIndMethod.iei = AIFG_IE_ID_BM_RESOURCEINDMEHTOD;
	dst->msg.resrcReq.resrcIndMethod.ptr = src+offset;
	offset++;

	//Cell Identifier - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.resrcReq.cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.resrcReq.cellId.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Extended Resource Indicator
	if(src[offset] == AIFG_IEI_BM_EXTRESOURCEIND){
		offset++;
		dst->msg.resrcReq.extResrcInd.iei = AIFG_IE_ID_BM_EXTRESOURCEIND;
		dst->msg.resrcReq.extResrcInd.ptr = src+offset;
		offset++;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//RESOURCE INDICATION
int aifg_msg_rv_resrcInd(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.resrcInd), 0, sizeof(dst->msg.resrcInd));

	//Resource Indication Method - M
	if(src[offset] != AIFG_IEI_BM_RESOURCEINDMEHTOD)
		goto ERR_PROC;
	offset++;
	dst->msg.resrcInd.resrcIndMethod.iei = AIFG_IE_ID_BM_RESOURCEINDMEHTOD;
	dst->msg.resrcInd.resrcIndMethod.ptr = src+offset;
	offset++;

	//Resource Available
	if(src[offset] == AIFG_IEI_BM_RESOURCEAVAIL){
		offset++;
		dst->msg.resrcInd.resrcAvail.iei = AIFG_IE_ID_BM_RESOURCEAVAIL;
		dst->msg.resrcInd.resrcAvail.ptr = src+offset;
		offset += 20;
	}

	//Cell Identifier - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.resrcInd.cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.resrcInd.cellId.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Total Resource Accessible
	if(src[offset] == AIFG_IEI_BM_TOTALRESOURCE){
		offset++;
		dst->msg.resrcInd.totalResrc.iei = AIFG_IE_ID_BM_TOTALRESOURCE;
		dst->msg.resrcInd.totalResrc.ptr = src+offset;
		offset += 4;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//RESOURCE INDICATION
int aifg_msg_rv_paging(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.paging), 0, sizeof(dst->msg.paging));

	//IMSI - M
	if(src[offset] != AIFG_IEI_BM_IMSI)
		goto ERR_PROC;
	offset++;
	dst->msg.paging.imsi.iei = AIFG_IE_ID_BM_IMSI;
	dst->msg.paging.imsi.ptr = src+offset;
	offset += src[offset] + 1;

	//TMSI
	if(src[offset] == AIFG_IEI_BM_TMSI){
		offset++;
		dst->msg.paging.tmsi.iei = AIFG_IE_ID_BM_TMSI;
		dst->msg.paging.tmsi.ptr = src+offset;
		offset += src[offset] + 1;
	}

	//Cell Identifier List - M
	if(src[offset] != AIFG_IEI_BM_CELLIDLIST)
		goto ERR_PROC;
	offset++;
	dst->msg.paging.cellIdList.iei = AIFG_IE_ID_BM_CELLIDLIST;
	dst->msg.paging.cellIdList.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Channel Needed
	if(src[offset] == AIFG_IEI_BM_CHANNELNEEDED){
		offset++;
		dst->msg.paging.channelNeeded.iei = AIFG_IE_ID_BM_CHANNELNEEDED;
		dst->msg.paging.channelNeeded.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//eMLPP Priority
	if(src[offset] == AIFG_IEI_BM_EMLPP){
		offset++;
		dst->msg.paging.eMLPPpri.iei = AIFG_IE_ID_BM_EMLPP;
		dst->msg.paging.eMLPPpri.ptr = src+offset;
		offset++;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CLEAR REQUEST
int aifg_msg_rv_clearReq(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.clearReq), 0, sizeof(dst->msg.clearReq));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.clearReq.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.clearReq.cause.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CLEAR COMMAND
int aifg_msg_rv_clearCmd(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.clearCmd), 0, sizeof(dst->msg.clearCmd));

	//Layer 3 Header Information
	if(src[offset] == AIFG_IEI_BM_L3HEADERINFO){
		offset++;
		dst->msg.clearCmd.l3HeaderInfo.iei = AIFG_IE_ID_BM_L3HEADERINFO;
		dst->msg.clearCmd.l3HeaderInfo.ptr = src+offset;
		offset += src[offset] + 1;
	}

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.clearCmd.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.clearCmd.cause.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CLEAR COMPLETE
int aifg_msg_rv_clearCmp(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	return AIFG_SUCCEED;
}

//RESET
int aifg_msg_rv_reset(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.reset), 0, sizeof(dst->msg.reset));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE){
		aifg_event = AIFG_ERR_ERROR_MSG;
		goto ERR_PROC;
	}	
	offset++;
	dst->msg.reset.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.reset.cause.ptr = src+offset;

	return AIFG_SUCCEED;

ERR_PROC:
	return AIFG_ERROR;
}

//RESET ACK
int aifg_msg_rv_resetAck(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	return AIFG_SUCCEED;
}

//HANDOVER PERFORMED
int aifg_msg_rv_HOPerformed(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HOPerformed), 0, sizeof(dst->msg.HOPerformed));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.HOPerformed.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.HOPerformed.cause.ptr = src+offset;
	offset += src[offset] + 1;

	//Cell Identifier - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.HOPerformed.cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.HOPerformed.cellId.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Chosen Channel
	if(src[offset] == AIFG_IEI_BM_CHOSENCHANNEL){
		offset++;
		dst->msg.HOPerformed.chosenChannel.iei = AIFG_IE_ID_BM_CHOSENCHANNEL;
		dst->msg.HOPerformed.chosenChannel.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Chosen Encryption Algorithm
	if(src[offset] == AIFG_IEI_BM_CHOSENENCRYPT){
		offset++;
		dst->msg.HOPerformed.chosenEncrypt.iei = AIFG_IE_ID_BM_CHOSENENCRYPT;
		dst->msg.HOPerformed.chosenEncrypt.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Speech Version
	if(src[offset] == AIFG_IEI_BM_SPEECHVER){
		offset++;
		dst->msg.HOPerformed.speechVer.iei = AIFG_IE_ID_BM_SPEECHVER;
		dst->msg.HOPerformed.speechVer.ptr = src+offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	} 

	//LSA Identifier
	if(src[offset] == AIFG_IEI_BM_LSAID){
		offset++;
		dst->msg.HOPerformed.lsaId.iei = AIFG_IE_ID_BM_LSAID;
		dst->msg.HOPerformed.lsaId.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//OVERLOAD
int aifg_msg_rv_overload(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.overload), 0, sizeof(dst->msg.overload));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.overload.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.overload.cause.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Cell Identifier
	if(src[offset] == AIFG_IEI_BM_CELLID){
		offset++;
		dst->msg.overload.cellId.iei = AIFG_IE_ID_BM_CELLID;
		dst->msg.overload.cellId.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//MSC INVOKE TRACE
int aifg_msg_rv_mscTrace(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.mscTrace), 0, sizeof(dst->msg.mscTrace));

	//Trace Type - M
	if(src[offset] != AIFG_IEI_BM_TRACETYPE)
		goto ERR_PROC;
	offset++;
	dst->msg.mscTrace.traceType.iei = AIFG_IE_ID_BM_TRACETYPE;
	dst->msg.mscTrace.traceType.ptr = src+offset;
	offset++;

	//Trigger ID
	if(src[offset] == AIFG_IEI_BM_TRIGGERID){
		offset++;
		dst->msg.mscTrace.triggerId.iei = AIFG_IE_ID_BM_TRIGGERID;
		dst->msg.mscTrace.triggerId.ptr = src+offset;
		offset += src[offset] + 1;
	}

	//Trace Reference - M
	if(src[offset] != AIFG_IEI_BM_TRACEREF)
		goto ERR_PROC;
	offset++;
	dst->msg.mscTrace.traceRef.iei = AIFG_IE_ID_BM_TRACEREF;
	dst->msg.mscTrace.traceRef.ptr = src+offset;
	offset += 2;
	if(offset >= msg_len) goto FINISH;

	//Transactionid
	if(src[offset] == AIFG_IEI_BM_TRANSACTIONID){
		offset++;
		dst->msg.mscTrace.transId.iei = AIFG_IE_ID_BM_TRANSACTIONID;
		dst->msg.mscTrace.transId.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Mobile Identity
	if(src[offset] == AIFG_IEI_BM_MOBILEID){
		offset++;
		dst->msg.mscTrace.mobileId.iei = AIFG_IE_ID_BM_MOBILEID;
		dst->msg.mscTrace.mobileId.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//OMCId
	if(src[offset] == AIFG_IEI_BM_OMCID){
		offset++;
		dst->msg.mscTrace.omcId.iei = AIFG_IE_ID_BM_OMCID;
		dst->msg.mscTrace.omcId.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//BSC INVOKE TRACE
int aifg_msg_rv_bscTrace(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.bscTrace), 0, sizeof(dst->msg.bscTrace));

	//Trace Type - M
	if(src[offset] != AIFG_IEI_BM_TRACETYPE)
		goto ERR_PROC;
	offset++;
	dst->msg.bscTrace.traceType.iei = AIFG_IE_ID_BM_TRACETYPE;
	dst->msg.bscTrace.traceType.ptr = src+offset;
	offset++;

	//Forward Indicator
	if(src[offset] == AIFG_IEI_BM_FORWARDIND){
		offset++;
		dst->msg.bscTrace.forwardInd.iei = AIFG_IE_ID_BM_FORWARDIND;
		dst->msg.bscTrace.forwardInd.ptr = src+offset;
		offset++;
	}

	//Triggerid
	if(src[offset] == AIFG_IEI_BM_TRIGGERID){
		offset++;
		dst->msg.bscTrace.triggerId.iei = AIFG_IE_ID_BM_TRIGGERID;
		dst->msg.bscTrace.triggerId.ptr = src+offset;
		offset += src[offset] + 1;
	}

	//Trace Reference - M
	if(src[offset] != AIFG_IEI_BM_TRACEREF)
		goto ERR_PROC;
	offset++;
	dst->msg.bscTrace.traceRef.iei = AIFG_IE_ID_BM_TRACEREF;
	dst->msg.bscTrace.traceRef.ptr = src+offset;
	offset += 2;
	if(offset >= msg_len) goto FINISH;

	//Transactionid
	if(src[offset] == AIFG_IEI_BM_TRANSACTIONID){
		offset++;
		dst->msg.bscTrace.transId.iei = AIFG_IE_ID_BM_TRANSACTIONID;
		dst->msg.bscTrace.transId.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//OMCId
	if(src[offset] == AIFG_IEI_BM_OMCID){
		offset++;
		dst->msg.bscTrace.omcId.iei = AIFG_IE_ID_BM_OMCID;
		dst->msg.bscTrace.omcId.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CLASSMARK UPDATE
int aifg_msg_rv_cmUpdate(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.cmUpdate), 0, sizeof(dst->msg.cmUpdate));

	//Classmark Information 2
	if(src[offset] != AIFG_IEI_BM_CLASSMARKINFO2)
		goto ERR_PROC;
	offset++;
	dst->msg.cmUpdate.cmInfo2.iei = AIFG_IE_ID_BM_CLASSMARKINFO2;
	dst->msg.cmUpdate.cmInfo2.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Classmark Information 2
	if(src[offset] == AIFG_IEI_BM_CLASSMARKINFO3){
		offset++;
		dst->msg.cmUpdate.cmInfo3.iei = AIFG_IE_ID_BM_CLASSMARKINFO3;
		dst->msg.cmUpdate.cmInfo3.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CIPHER MODE COMMAND
int aifg_msg_rv_cipherModeCmd(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.cipherModeCmd), 0, sizeof(dst->msg.cipherModeCmd));

	//Layer 3 Header Information
	if(src[offset] == AIFG_IEI_BM_L3HEADERINFO){
		offset++;
		dst->msg.cipherModeCmd.l3HeaderInfo.iei = AIFG_IE_ID_BM_L3HEADERINFO;
		dst->msg.cipherModeCmd.l3HeaderInfo.ptr = src+offset;
		offset += src[offset] + 1;
	}

	//Encryption Information - M
	if(src[offset] != AIFG_IEI_BM_ENCRYPTINFO)
		goto ERR_PROC;
	offset++;
	dst->msg.cipherModeCmd.encryptInfo.iei = AIFG_IE_ID_BM_ENCRYPTINFO;
	dst->msg.cipherModeCmd.encryptInfo.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Cipher Response Mode
	if(src[offset] == AIFG_IEI_BM_CIPHERRESPMODE){
		offset++;
		dst->msg.cipherModeCmd.cipherRespMode.iei = AIFG_IE_ID_BM_CIPHERRESPMODE;
		dst->msg.cipherModeCmd.cipherRespMode.ptr = src+offset;
		offset++;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CIPHER MODE COMPLETE
int aifg_msg_rv_cipherModeComp(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.cipherModeCmd), 0, sizeof(dst->msg.cipherModeCmd));

	if(offset >= msg_len) goto FINISH;

	//Layer 3 Header Information
	if(src[offset] == AIFG_IEI_BM_L3MSGCONTENT){
		offset++;
		dst->msg.cipherModeComp.l3MsgCont.iei = AIFG_IE_ID_BM_L3MSGCONTENT;
		dst->msg.cipherModeComp.l3MsgCont.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Chosen Encryption Algorithm
	if(src[offset] == AIFG_IEI_BM_CHOSENENCRYPT){
		offset++;
		dst->msg.cipherModeComp.chosenEncrypt.iei = AIFG_IE_ID_BM_CHOSENENCRYPT;
		dst->msg.cipherModeComp.chosenEncrypt.ptr = src+offset;
		offset++;
	}

FINISH:
	return AIFG_SUCCEED;
}

//COMPLETE LAYER 3 INFORMATION
int aifg_msg_rv_completeL3Info(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.completeL3Info), 0, sizeof(dst->msg.completeL3Info));

	//Cell Identifier - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.completeL3Info.cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.completeL3Info.cellId.ptr = src+offset;
	offset += src[offset] + 1;

	//Layer 3 Information - M
	if(src[offset] != AIFG_IEI_BM_L3INFO)
		goto ERR_PROC;
	offset++;
	if(AIFG_ERROR == aifg_msg_decode_embeded_l3msg(&(src[offset+1]), &(dst->msg.completeL3Info.l3msg)))
		goto ERR_PROC;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Chosen Channel
	if(src[offset] == AIFG_IEI_BM_CHOSENCHANNEL){
		offset++;
		dst->msg.completeL3Info.chosenChannel.iei = AIFG_IE_ID_BM_CHOSENCHANNEL;
		dst->msg.completeL3Info.chosenChannel.ptr = src+offset;
		offset++;
	}

	//LSA Identifier List
	if(src[offset] == AIFG_IEI_BM_LSAIDLIST){
		offset++;
		dst->msg.completeL3Info.lsaIdList.iei = AIFG_IE_ID_BM_LSAIDLIST;
		dst->msg.completeL3Info.lsaIdList.ptr = src+offset;
		offset += src[offset] + 1;
	}

	//Location Information
	if(src[offset] == AIFG_IEI_BM_LOCATIONINFO){
		offset++;
		dst->msg.completeL3Info.locInfo.iei = AIFG_IE_ID_BM_LOCATIONINFO;
		dst->msg.completeL3Info.locInfo.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//SAPI "n" REJECT
int aifg_msg_rv_sapi_n_rej(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.sapi_n_rej), 0, sizeof(dst->msg.sapi_n_rej));

	//DLCI - M
	if(src[offset] != AIFG_IEI_BM_DLCI)
		goto ERR_PROC;
	offset++;
	dst->msg.sapi_n_rej.dlci.iei = AIFG_IE_ID_BM_DLCI;
	dst->msg.sapi_n_rej.dlci.ptr = src+offset;
	offset++;

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.sapi_n_rej.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.sapi_n_rej.cause.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//HANDOVER REQUIRED REJECT
int aifg_msg_rv_HORequiredRej(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.HORequiredRej), 0, sizeof(dst->msg.HORequiredRej));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.HORequiredRej.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.HORequiredRej.cause.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//RESET CIRCUIT
int aifg_msg_rv_resetCircuit(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.resetCircuit), 0, sizeof(dst->msg.resetCircuit));

	//CIC - M
	if(src[offset] != AIFG_IEI_BM_CIC)
		goto ERR_PROC;
	offset++;
	dst->msg.resetCircuit.cic.iei = AIFG_IE_ID_BM_CIC;
	dst->msg.resetCircuit.cic.ptr = src+offset;
	offset += 2;

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.resetCircuit.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.resetCircuit.cause.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//RESET CIRCUIT ACK
int aifg_msg_rv_resetCircuitAck(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	return AIFG_ERROR;
}

//CIRCUIT GROUP BLOCK
int aifg_msg_rv_ccGroupBlock(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.ccGroupBlock), 0, sizeof(dst->msg.ccGroupBlock));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.ccGroupBlock.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.ccGroupBlock.cause.ptr = src+offset;
	offset += src[offset] + 1;

	//CIC - M
	if(src[offset] != AIFG_IEI_BM_CIC)
		goto ERR_PROC;
	offset++;
	dst->msg.ccGroupBlock.cic.iei = AIFG_IE_ID_BM_CIC;
	dst->msg.ccGroupBlock.cic.ptr = src+offset;
	offset += 2;

	//Circuit Identity Code List - M
	if(src[offset] != AIFG_IEI_BM_CICLIST)
		goto ERR_PROC;
	offset++;
	dst->msg.ccGroupBlock.cicList.iei = AIFG_IE_ID_BM_CICLIST;
	dst->msg.ccGroupBlock.cicList.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CIRCUIT GROUP BLOCK ACK
int aifg_msg_rv_ccGroupBlockAck(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	return AIFG_SUCCEED;	
}

//CIRCUIT GROUP UNBLOCK
int aifg_msg_rv_ccGroupUnblock(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.ccGroupUnblock), 0, sizeof(dst->msg.ccGroupUnblock));

	//CIC - M
	if(src[offset] != AIFG_IEI_BM_CIC)
		goto ERR_PROC;
	offset++;
	dst->msg.ccGroupUnblock.cic.iei = AIFG_IE_ID_BM_CIC;
	dst->msg.ccGroupUnblock.cic.ptr = src+offset;
	offset += 2;

	//Circuit Identity Code List - M
	if(src[offset] != AIFG_IEI_BM_CICLIST)
		goto ERR_PROC;
	offset++;
	dst->msg.ccGroupUnblock.cicList.iei = AIFG_IE_ID_BM_CICLIST;
	dst->msg.ccGroupUnblock.cicList.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//CIRCUIT GROUP BLOCK ACK
int aifg_msg_rv_ccGroupUnblockAck(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	return AIFG_SUCCEED;	
}

//CONFUSION
int aifg_msg_rv_confusion(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.confusion), 0, sizeof(dst->msg.confusion));

	//Cause - M
	if(src[offset] != AIFG_IEI_BM_CAUSE)
		goto ERR_PROC;
	offset++;
	dst->msg.confusion.cause.iei = AIFG_IE_ID_BM_CAUSE;
	dst->msg.confusion.cause.ptr = src+offset;
	offset += src[offset] + 1;

	//Diagnostics
	if(src[offset] != AIFG_IEI_BM_DIGNOSTIC)
		goto ERR_PROC;
	offset++;
	dst->msg.confusion.diagnostics.iei = AIFG_IE_ID_BM_DIGNOSTIC;
	dst->msg.confusion.diagnostics.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//UNEQUIPPED CIRCUIT
int aifg_msg_rv_unequippedCircuit(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.upequipCircuit), 0, sizeof(dst->msg.upequipCircuit));

	//CIC - M
	if(src[offset] != AIFG_IEI_BM_CIC)
		goto ERR_PROC;
	offset++;
	dst->msg.upequipCircuit.cic.iei = AIFG_IE_ID_BM_CIC;
	dst->msg.upequipCircuit.cic.ptr = src+offset;
	offset += 2;

	//Circuit Identity Code List
	if(src[offset] != AIFG_IEI_BM_CICLIST)
		goto ERR_PROC;
	offset++;
	dst->msg.upequipCircuit.cicList.iei = AIFG_IE_ID_BM_CICLIST;
	dst->msg.upequipCircuit.cicList.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//LOAD INDICATION
int aifg_msg_rv_loadInd(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.loadInd), 0, sizeof(dst->msg.loadInd));

	//Time Indication - M
	if(src[offset] != AIFG_IEI_BM_TIMEIND)
		goto ERR_PROC;
	offset++;
	dst->msg.loadInd.timeInd.iei = AIFG_IE_ID_BM_TIMEIND;
	dst->msg.loadInd.timeInd.ptr = src+offset;
	offset++;

	//Cell Identifier - M
	if(src[offset] != AIFG_IEI_BM_CELLID)
		goto ERR_PROC;
	offset++;
	dst->msg.loadInd.cellId.iei = AIFG_IE_ID_BM_CELLID;
	dst->msg.loadInd.cellId.ptr = src+offset;
	offset += src[offset] + 1;

	//Cell Identifier List - M
	if(src[offset] != AIFG_IEI_BM_CELLIDLIST)
		goto ERR_PROC;
	offset++;
	dst->msg.loadInd.cellIdList.iei = AIFG_IE_ID_BM_CELLIDLIST;
	dst->msg.loadInd.cellIdList.ptr = src+offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Resource Situation
	if(src[offset] == AIFG_IEI_BM_RESOURCESITUATION){
		offset++;
		dst->msg.loadInd.resrcSit.iei = AIFG_IE_ID_BM_RESOURCESITUATION;
		dst->msg.loadInd.resrcSit.ptr = src+offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Cause
	if(src[offset] == AIFG_IEI_BM_CAUSE){
		offset++;
		dst->msg.loadInd.cause.iei = AIFG_IE_ID_BM_CAUSE;
		dst->msg.loadInd.cause.ptr = src+offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//SUSPEND
int aifg_msg_rv_suspend(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.suspend), 0, sizeof(dst->msg.suspend));

	//DLCI - M
	if(src[offset] != AIFG_IEI_BM_DLCI)
		goto ERR_PROC;
	offset++;
	dst->msg.sapi_n_rej.dlci.iei = AIFG_IE_ID_BM_DLCI;
	dst->msg.sapi_n_rej.dlci.ptr = src+offset;
	offset++;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//LSA INFORMATION
int aifg_msg_rv_lsaInfo(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.lsaInfo), 0, sizeof(dst->msg.lsaInfo));

	//LSA Information
	if(src[offset] != AIFG_IEI_BM_LSAINFO)
		goto ERR_PROC;
	offset++;
	dst->msg.lsaInfo.lsaInfo.iei = AIFG_IE_ID_BM_LSAINFO;
	dst->msg.lsaInfo.lsaInfo.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//Location Information Command
int aifg_msg_rv_locInfoCmd(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.locInfoCmd), 0, sizeof(dst->msg.locInfoCmd));

	//Location Information
	if(src[offset] != AIFG_IEI_BM_LOCATIONINFO)
		goto ERR_PROC;
	offset++;
	dst->msg.locInfoCmd.locInfo.iei = AIFG_IE_ID_BM_LOCATIONINFO;
	dst->msg.locInfoCmd.locInfo.ptr = src+offset;
	offset += src[offset] + 1;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//Location Information Report
int aifg_msg_rv_locInfoReport(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.locInfoReport), 0, sizeof(dst->msg.locInfoReport));

	if(src[offset] == AIFG_IEI_BM_LOCATIONINFO){
		//Location Information
		offset++;
		dst->msg.locInfoReport.locInfo.iei = AIFG_IE_ID_BM_LOCATIONINFO;
		dst->msg.locInfoReport.locInfo.ptr = src+offset;
		offset += src[offset] + 1;
	}
	else if(src[offset] == AIFG_IEI_BM_CAUSE){
		//Cause
		offset++;
		dst->msg.confusion.cause.iei = AIFG_IE_ID_BM_CAUSE;
		dst->msg.confusion.cause.ptr = src+offset;
		offset += src[offset] + 1;
	}
	else
		goto ERR_PROC;

	return AIFG_SUCCEED;	

ERR_PROC:
	aifg_event = AIFG_ERR_ERROR_MSG;
	return AIFG_ERROR;
}

//Authentication request
int aifg_msg_rv_authReq(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.authReq), 0, sizeof(dst->msg.authReq));

	//Ciphering key sequence number - M
	dst->msg.authReq.cipherKeySeq.iei = AIFG_IE_ID_DT_CIPHERKEY;
	dst->msg.authReq.cipherKeySeq.ptr = src+offset;
	dst->msg.authReq.cipherKeySeq.hi_lo_flag = AIFG_LOW_BITS;
	offset++;

	//Auth. parameter RAND - M
	dst->msg.authReq.authParamRAND.iei = AIFG_IE_ID_DT_AUTHRAND;
	dst->msg.authReq.authParamRAND.ptr = src+offset;

	return AIFG_SUCCEED;
}

//Authentication response
int aifg_msg_rv_authResp(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.authResp), 0, sizeof(dst->msg.authResp));

	//Auth. parameter SRES - M
	dst->msg.authResp.authParamSRES.iei = AIFG_IE_ID_DT_AUTHSRES;
	dst->msg.authResp.authParamSRES.ptr = src;

	return AIFG_SUCCEED;
}

//CM service request
int aifg_msg_rv_cmReq(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.cmReq), 0, sizeof(dst->msg.cmReq));

	//CM service type
	dst->msg.cmReq.type.iei = AIFG_IE_ID_DT_CMTYPE;
	dst->msg.cmReq.type.ptr = src + offset;
	dst->msg.cmReq.type.hi_lo_flag = AIFG_LOW_BITS;

	//Ciphering key sequence number - M
	dst->msg.cmReq.cipherKeySeq.iei = AIFG_IE_ID_DT_CIPHERKEY;
	dst->msg.cmReq.cipherKeySeq.ptr = src + offset;
	dst->msg.cmReq.cipherKeySeq.hi_lo_flag = AIFG_HIGH_BITS;
	offset++;

	//Mobile station classmark 2 - M
	dst->msg.cmReq.cm2.iei = AIFG_IE_ID_DT_MSCM2;
	dst->msg.cmReq.cm2.ptr = src + offset;
	offset += src[offset] + 1;

	//Mobile identity - M
	dst->msg.cmReq.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
	dst->msg.cmReq.mobileId.ptr = src + offset;
	offset += src[offset] + 1;

	//Priority
	if((src[offset]&0xF0) == AIFG_IEI_DT_PRIORITYLEVEL){
		dst->msg.cmReq.priority.iei = AIFG_IE_ID_DT_PRIORITYLEVEL;
		dst->msg.cmReq.priority.ptr = src + offset;
	}
	return AIFG_SUCCEED;
}

//CM service reject
int aifg_msg_rv_cmRej(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.cmRej), 0, sizeof(dst->msg.cmRej));

	//Reject cause - M
	dst->msg.cmRej.rejCause.iei = AIFG_IE_ID_DT_REJCAUSE;
	dst->msg.cmRej.rejCause.ptr = src;

	return AIFG_SUCCEED;
}

//Abort
//The same as CM service reject

//Identity request
int aifg_msg_rv_idReq(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.idReq), 0, sizeof(dst->msg.idReq));

	//CM service type
	dst->msg.idReq.type.iei = AIFG_IE_ID_DT_IDTYPE;
	dst->msg.idReq.type.ptr = src;
	dst->msg.idReq.type.hi_lo_flag = AIFG_LOW_BITS;

	return AIFG_SUCCEED;
}

//Identity response
int aifg_msg_rv_idResp(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.idResp), 0, sizeof(dst->msg.idResp));

	//Mobile identity - M
	dst->msg.idResp.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
	dst->msg.idResp.mobileId.ptr = src;

	return AIFG_SUCCEED;
}

//Location updating accept
int aifg_msg_rv_luAccept(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.luAccept), 0, sizeof(dst->msg.luAccept));

	//Location area identification - M
	dst->msg.luAccept.lai.iei = AIFG_IE_ID_DT_LAI;
	dst->msg.luAccept.lai.ptr = src;
	offset += 5;
	if(offset >= msg_len) goto FINISH;

	//Mobile identity
	if(src[offset] == AIFG_IEI_DT_MOBILEID){
		offset++;	//skip iei
		dst->msg.luAccept.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
		dst->msg.luAccept.mobileId.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Follow on proceed
	if(src[offset] == AIFG_IEI_DT_FLONPROCEED){
		dst->msg.luAccept.followOnProc.iei = AIFG_IE_ID_DT_FLONPROCEED;
		dst->msg.luAccept.followOnProc.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//CTS permission
	if(src[offset] == AIFG_IEI_DT_CTS){
		offset++;	//skip iei
		dst->msg.luAccept.ctsPerm.iei = AIFG_IE_ID_DT_CTS;
		dst->msg.luAccept.ctsPerm.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Location updating reject
//The same as CM service reject

//MM information
int aifg_msg_rv_mmInfo(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.mmInfo), 0, sizeof(dst->msg.mmInfo));
	if(offset >= msg_len) goto FINISH;

	//Full name for network
	if(src[offset] == AIFG_IEI_DT_FULL_NWNAME){
		offset++;	//skip iei
		dst->msg.mmInfo.fullNetworkName.iei = AIFG_IE_ID_DT_FULL_NWNAME;
		dst->msg.mmInfo.fullNetworkName.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Short name for network
	if(src[offset] == AIFG_IEI_DT_SHORT_NWNAME){
		offset++;	//skip iei
		dst->msg.mmInfo.shortNetworkName.iei = AIFG_IE_ID_DT_SHORT_NWNAME;
		dst->msg.mmInfo.shortNetworkName.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Universal time zone 
	if(src[offset] == AIFG_IEI_DT_TIMEZONE){
		offset++;	//skip iei
		dst->msg.mmInfo.timeZone.iei = AIFG_IE_ID_DT_TIMEZONE;
		dst->msg.mmInfo.timeZone.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Network time and time zone
	if(src[offset] == AIFG_IEI_DT_TZTIME){
		offset++;	//skip iei
		dst->msg.mmInfo.timeZoneAndTime.iei = AIFG_IE_ID_DT_TZTIME;
		dst->msg.mmInfo.timeZoneAndTime.ptr = src + offset;
		offset += 7;
		if(offset >= msg_len) goto FINISH;
	}

	//LSA Identity
	if(src[offset] == AIFG_IEI_DT_LSAID){
		offset++;	//skip iei
		dst->msg.mmInfo.lsaId.iei = AIFG_IE_ID_DT_LSAID;
		dst->msg.mmInfo.lsaId.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//MM status
//The same as CM service reject

//TMSI reallocation command
int aifg_msg_rv_tmsiRealloc(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.tmsiReallocCmd), 0, sizeof(dst->msg.tmsiReallocCmd));

	//Location area identification - M
	dst->msg.tmsiReallocCmd.lai.iei = AIFG_IE_ID_DT_LAI;
	dst->msg.tmsiReallocCmd.lai.ptr = src + offset;
	offset += 5;

	//Mobile identity - M
	dst->msg.tmsiReallocCmd.mobileId.iei = AIFG_IE_ID_DT_MOBILEID;
	dst->msg.tmsiReallocCmd.mobileId.ptr = src + offset;

	return AIFG_SUCCEED;
}

//Alerting
int aifg_msg_rv_alert(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.alert), 0, sizeof(dst->msg.alert));
	if(offset >= msg_len) goto FINISH;

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.alert.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.alert.facility.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Progress indicator
	if(src[offset] == AIFG_IEI_DT_PROGIND){
		offset++;	//Skip iei
		dst->msg.alert.progressInd.iei = AIFG_IE_ID_DT_PROGIND;
		dst->msg.alert.progressInd.ptr = src + offset;
		offset += 3;
		if(offset >= msg_len) goto FINISH;
	}

	//User-user
	if(src[offset] == AIFG_IEI_DT_USERUSER){
		offset++;	//Skip iei
		dst->msg.alert.user_user.iei = AIFG_IE_ID_DT_USERUSER;
		dst->msg.alert.user_user.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
		offset++;	//Skip iei
		dst->msg.alert.ssVer.iei = AIFG_IE_ID_DT_SSVER;
		dst->msg.alert.ssVer.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Call confirmed
int aifg_msg_rv_callConfirm(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.callConfirm), 0, sizeof(dst->msg.callConfirm));
	if(offset >= msg_len) goto FINISH;

	//Repeat Indicator
	if((src[offset] & 0xF0) == AIFG_IEI_DT_REPEATIND){
		dst->msg.callConfirm.reptInd.iei = AIFG_IE_ID_DT_REPEATIND;
		dst->msg.callConfirm.reptInd.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Bearer capability 1
	if(src[offset] == AIFG_IEI_DT_BEARERCAP){
		offset++;	//Skip iei
		dst->msg.callConfirm.bearCap1.iei = AIFG_IE_ID_DT_BEARERCAP;
		dst->msg.callConfirm.bearCap1.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Bearer capability 2
	if(src[offset] == AIFG_IEI_DT_BEARERCAP){
		offset++;	//Skip iei
		dst->msg.callConfirm.bearCap2.iei = AIFG_IE_ID_DT_BEARERCAP;
		dst->msg.callConfirm.bearCap2.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Cause
	if(src[offset] == AIFG_IEI_DT_CAUSE){
		offset++;	//Skip iei
		dst->msg.callConfirm.cause.iei = AIFG_IE_ID_DT_CAUSE;
		dst->msg.callConfirm.cause.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//CC Capabilities
	if(src[offset] == AIFG_IEI_DT_CCCAP){
		offset++;	//Skip iei
		dst->msg.callConfirm.ccCap.iei = AIFG_IE_ID_DT_CCCAP;
		dst->msg.callConfirm.ccCap.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Call proceeding
int aifg_msg_rv_callProceed(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.callProceed), 0, sizeof(dst->msg.callProceed));
	if(offset >= msg_len) goto FINISH;

	//Repeat Indicator
	if((src[offset] & 0xF0) == AIFG_IEI_DT_REPEATIND){
		dst->msg.callProceed.reptInd.iei = AIFG_IE_ID_DT_REPEATIND;
		dst->msg.callProceed.reptInd.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Bearer capability 1
	if(src[offset] == AIFG_IEI_DT_BEARERCAP){
		offset++;	//Skip iei
		dst->msg.callProceed.bearCap1.iei = AIFG_IE_ID_DT_BEARERCAP;
		dst->msg.callProceed.bearCap1.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Bearer capability 2
	if(src[offset] == AIFG_IEI_DT_BEARERCAP){
		offset++;	//Skip iei
		dst->msg.callProceed.bearCap2.iei = AIFG_IE_ID_DT_BEARERCAP;
		dst->msg.callProceed.bearCap2.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.callProceed.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.callProceed.facility.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Progress indicator
	if(src[offset] == AIFG_IEI_DT_PROGIND){
		offset++;	//Skip iei
		dst->msg.callProceed.progressInd.iei = AIFG_IE_ID_DT_PROGIND;
		dst->msg.callProceed.progressInd.ptr = src + offset;
		offset += 3;
		if(offset >= msg_len) goto FINISH;
	}

	//Priority granted
	if((src[offset] & 0xF0) == AIFG_IEI_DT_PRIORITYLEVEL){
		dst->msg.callProceed.priority.iei = AIFG_IE_ID_DT_PRIORITYLEVEL;
		dst->msg.callProceed.priority.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Congestion control
int aifg_msg_rv_congestCtrl(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.congestCtrl), 0, sizeof(dst->msg.congestCtrl));

	//Congestion level
	dst->msg.congestCtrl.congestLev.iei = AIFG_IE_ID_DT_CONGESTLEVEL;
	dst->msg.congestCtrl.congestLev.ptr = src + offset;
	dst->msg.congestCtrl.congestLev.hi_lo_flag = AIFG_LOW_BITS;
	offset++;
	if(offset >= msg_len) goto FINISH;

	//Cause
	if(src[offset] == AIFG_IEI_DT_CAUSE){
		offset++;	//Skip iei
		dst->msg.congestCtrl.cause.iei = AIFG_IE_ID_DT_CAUSE;
		dst->msg.congestCtrl.cause.ptr = src + offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Connect
int aifg_msg_rv_connect(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.connect), 0, sizeof(dst->msg.connect));
	if(offset >= msg_len) goto FINISH;

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.connect.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.connect.facility.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Progress indicator
	if(src[offset] == AIFG_IEI_DT_PROGIND){
		offset++;	//Skip iei
		dst->msg.connect.progressInd.iei = AIFG_IE_ID_DT_PROGIND;
		dst->msg.connect.progressInd.ptr = src + offset;
		offset += 3;
		if(offset >= msg_len) goto FINISH;
	}

	//Connected number
	if(src[offset] == AIFG_IEI_DT_CONNNUM){
		offset++;	//Skip iei
		dst->msg.connect.connNum.iei = AIFG_IE_ID_DT_CONNNUM;
		dst->msg.connect.connNum.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Connected subaddress
	if(src[offset] == AIFG_IEI_DT_CONNSUBADDR){
		offset++;	//Skip iei
		dst->msg.connect.connSubaddr.iei = AIFG_IE_ID_DT_CONNSUBADDR;
		dst->msg.connect.connSubaddr.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//User-user
	if(src[offset] == AIFG_IEI_DT_USERUSER){
		offset++;	//Skip iei
		dst->msg.connect.user_user.iei = AIFG_IE_ID_DT_USERUSER;
		dst->msg.connect.user_user.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
		offset++;	//Skip iei
		dst->msg.connect.ssVer.iei = AIFG_IE_ID_DT_SSVER;
		dst->msg.connect.ssVer.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Disconnect
int aifg_msg_rv_disconnect(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.disconnect), 0, sizeof(dst->msg.disconnect));

	//Cause
	dst->msg.disconnect.cause.iei = AIFG_IE_ID_DT_CAUSE;
	dst->msg.disconnect.cause.ptr = src + offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.disconnect.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.disconnect.facility.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Progress indicator
	if(src[offset] == AIFG_IEI_DT_PROGIND){
		offset++;	//Skip iei
		dst->msg.disconnect.progressInd.iei = AIFG_IE_ID_DT_PROGIND;
		dst->msg.disconnect.progressInd.ptr = src + offset;
		offset += 3;
		if(offset >= msg_len) goto FINISH;
	}

	//User-user
	if(src[offset] == AIFG_IEI_DT_USERUSER){
		offset++;	//Skip iei
		dst->msg.disconnect.user_user.iei = AIFG_IE_ID_DT_USERUSER;
		dst->msg.disconnect.user_user.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
		offset++;	//Skip iei
		dst->msg.disconnect.ssVer.iei = AIFG_IE_ID_DT_SSVER;
		dst->msg.disconnect.ssVer.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//EMERGENCY SETUP
int aifg_msg_rv_eSetup(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.eSetup), 0, sizeof(dst->msg.eSetup));
	if(offset >= msg_len) goto FINISH;

	//Bearer capability
	if(src[offset] == AIFG_IEI_DT_BEARERCAP){
		offset++;	//Skip iei
		dst->msg.eSetup.bearCap.iei = AIFG_IE_ID_DT_BEARERCAP;
		dst->msg.eSetup.bearCap.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Facility
int aifg_msg_rv_facility(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.facility), 0, sizeof(dst->msg.facility));

	//Facility - M
	dst->msg.facility.facility.iei = AIFG_IE_ID_DT_FACILITY;
	dst->msg.facility.facility.ptr = src;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
		offset++;	//Skip iei
		dst->msg.facility.ssVer.iei = AIFG_IE_ID_DT_SSVER;
		dst->msg.facility.ssVer.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Hold Reject
int aifg_msg_rv_holdRej(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.holdRej), 0, sizeof(dst->msg.holdRej));

	//Cause
	dst->msg.holdRej.cause.iei = AIFG_IE_ID_DT_CAUSE;
	dst->msg.holdRej.cause.ptr = src;

	return AIFG_SUCCEED;
}


//Modify
int aifg_msg_rv_modify(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.modify), 0, sizeof(dst->msg.modify));

	//Bearer capability - M
	dst->msg.modify.bearCap.iei = AIFG_IE_ID_DT_BEARERCAP;
	dst->msg.modify.bearCap.ptr = src + offset;
	offset += src[offset] + 1;

	//Low layer comp.
	if(src[offset] == AIFG_IEI_DT_LOWCOM){
		offset++;	//Skip iei
		dst->msg.modify.lowLComp.iei = AIFG_IE_ID_DT_LOWCOM;
		dst->msg.modify.lowLComp.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//High layer comp.
	if(src[offset] == AIFG_IEI_DT_HIGHCOM){
		offset++;	//Skip iei
		dst->msg.modify.highLComp.iei = AIFG_IE_ID_DT_HIGHCOM;
		dst->msg.modify.highLComp.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Reverse call setup direction
	if(src[offset] == AIFG_IEI_DT_REVCALLDIR){
		offset++;	//Skip iei
		dst->msg.modify.revCallSetDir.iei = AIFG_IE_ID_DT_REVCALLDIR;
		dst->msg.modify.revCallSetDir.ptr = src;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Modify complete
//The same as modify

//Modify reject
int aifg_msg_rv_modifyRej(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.modifyRej), 0, sizeof(dst->msg.modifyRej));

	//Bearer capability - M
	dst->msg.modifyRej.bearCap.iei = AIFG_IE_ID_DT_BEARERCAP;
	dst->msg.modifyRej.bearCap.ptr = src + offset;
	offset += src[offset] + 1;

	//Cause - M
	dst->msg.modifyRej.cause.iei = AIFG_IE_ID_DT_CAUSE;
	dst->msg.modifyRej.cause.ptr = src + offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//Low layer comp.
	if(src[offset] == AIFG_IEI_DT_LOWCOM){
		offset++;	//Skip iei
		dst->msg.modifyRej.lowLComp.iei = AIFG_IE_ID_DT_LOWCOM;
		dst->msg.modifyRej.lowLComp.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//High layer comp.
	if(src[offset] == AIFG_IEI_DT_HIGHCOM){
		offset++;	//Skip iei
		dst->msg.modifyRej.highLComp.iei = AIFG_IE_ID_DT_HIGHCOM;
		dst->msg.modifyRej.highLComp.ptr = src + offset;
		offset += src[offset] + 1;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Notify
int aifg_msg_rv_notify(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.notify), 0, sizeof(dst->msg.notify));

	//Notification indicator
	dst->msg.notify.notifyInd.iei = AIFG_IE_ID_DT_NOTIIND;
	dst->msg.notify.notifyInd.ptr = src;

	return AIFG_SUCCEED;
}

//Progress
int aifg_msg_rv_progress(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.progress), 0, sizeof(dst->msg.progress));

	//Progress indicator - M
	dst->msg.progress.progressInd.iei = AIFG_IE_ID_DT_PROGIND;
	dst->msg.progress.progressInd.ptr = src + offset;
	offset += src[offset] + 1;
	if(offset >= msg_len) goto FINISH;

	//User-user
	if(src[offset] == AIFG_IEI_DT_USERUSER){
		offset++;	//Skip iei
		dst->msg.progress.user_user.iei = AIFG_IE_ID_DT_USERUSER;
		dst->msg.progress.user_user.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Release
int aifg_msg_rv_release(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.release), 0, sizeof(dst->msg.release));
	if(offset >= msg_len) goto FINISH;

	//Cause
	if(src[offset] == AIFG_IEI_DT_CAUSE){
		offset++;	//Skip iei
		dst->msg.release.cause1.iei = AIFG_IE_ID_DT_CAUSE;
		dst->msg.release.cause1.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Second cause
	if(src[offset] == AIFG_IEI_DT_CAUSE){
		offset++;	//Skip iei
		dst->msg.release.cause2.iei = AIFG_IE_ID_DT_CAUSE;
		dst->msg.release.cause2.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.release.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.release.facility.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//User-user
	if(src[offset] == AIFG_IEI_DT_USERUSER){
		offset++;	//Skip iei
		dst->msg.release.user_user.iei = AIFG_IE_ID_DT_USERUSER;
		dst->msg.release.user_user.ptr = src + offset;
		offset += src[offset] + 1;	
		if(offset >= msg_len) goto FINISH;	
	}

	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
		offset++;	//Skip iei
		dst->msg.release.ssVer.iei = AIFG_IE_ID_DT_SSVER;
		dst->msg.release.ssVer.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Release complete
int aifg_msg_rv_releaseComp(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.releaseComp), 0, sizeof(dst->msg.releaseComp));
	if(offset >= msg_len) goto FINISH;

	//Cause
	if(src[offset] == AIFG_IEI_DT_CAUSE){
		offset++;	//Skip iei
		dst->msg.releaseComp.cause.iei = AIFG_IE_ID_DT_CAUSE;
		dst->msg.releaseComp.cause.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.releaseComp.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.releaseComp.facility.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//User-user
	if(src[offset] == AIFG_IEI_DT_USERUSER){
		offset++;	//Skip iei
		dst->msg.releaseComp.user_user.iei = AIFG_IE_ID_DT_USERUSER;
		dst->msg.releaseComp.user_user.ptr = src + offset;
		offset += src[offset] + 1;	
		if(offset >= msg_len) goto FINISH;	
	}

	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
		offset++;	//Skip iei
		dst->msg.releaseComp.ssVer.iei = AIFG_IE_ID_DT_SSVER;
		dst->msg.releaseComp.ssVer.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Retrieve reject
//The same as Hold Reject


//Setup
int aifg_msg_rv_setup(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.setup), 0, sizeof(dst->msg.setup));
	if(offset >= msg_len) goto FINISH;

	//BC repeat indicator
	if((src[offset] & 0xF0) == AIFG_IEI_DT_REPEATIND){
		dst->msg.setup.reptInd_bc.iei = AIFG_IE_ID_DT_REPEATIND;
		dst->msg.setup.reptInd_bc.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Bearer capability 1
	if(src[offset] == AIFG_IEI_DT_BEARERCAP){
		offset++;	//Skip iei
		dst->msg.setup.bearCap1.iei = AIFG_IE_ID_DT_BEARERCAP;
		dst->msg.setup.bearCap1.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Bearer capability 2
	if(src[offset] == AIFG_IEI_DT_BEARERCAP){
		offset++;	//Skip iei
		dst->msg.setup.bearCap2.iei = AIFG_IE_ID_DT_BEARERCAP;
		dst->msg.setup.bearCap2.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.setup.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.setup.facility.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Progress indicator
	if(src[offset] == AIFG_IEI_DT_PROGIND){
		offset++;	//Skip iei
		dst->msg.setup.progressInd.iei = AIFG_IE_ID_DT_PROGIND;
		dst->msg.setup.progressInd.ptr = src + offset;
		offset += 3;
		if(offset >= msg_len) goto FINISH;
	}

	//Signal
	if(src[offset] == AIFG_IEI_DT_SIGNAL){
		offset++;	//Skip iei
		dst->msg.setup.signal.iei = AIFG_IE_ID_DT_SIGNAL;
		dst->msg.setup.signal.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Calling party BCD number
	if(src[offset] == AIFG_IEI_DT_CALLERBCD){
		offset++;	//Skip iei
		dst->msg.setup.callingBCD.iei = AIFG_IE_ID_DT_CALLERBCD;
		dst->msg.setup.callingBCD.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Calling party subaddress
	if(src[offset] == AIFG_IEI_DT_CALLERSUBADDR){
		offset++;	//Skip iei
		dst->msg.setup.callingSubaddr.iei = AIFG_IE_ID_DT_CALLERSUBADDR;
		dst->msg.setup.callingSubaddr.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Called party BCD number
	if(src[offset] == AIFG_IEI_DT_CALLEDBCD){
		offset++;	//Skip iei
		dst->msg.setup.calledBCD.iei = AIFG_IE_ID_DT_CALLEDBCD;
		dst->msg.setup.calledBCD.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Called party subaddress
	if(src[offset] == AIFG_IEI_DT_CALLEDSUBADDR){
		offset++;	//Skip iei
		dst->msg.setup.calledSubaddr.iei = AIFG_IE_ID_DT_CALLEDSUBADDR;
		dst->msg.setup.calledSubaddr.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Redirecting party BCD number
	if(src[offset] == AIFG_IEI_DT_REDIRBCD){
		offset++;	//Skip iei
		dst->msg.setup.redirBCD.iei = AIFG_IE_ID_DT_REDIRBCD;
		dst->msg.setup.redirBCD.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Redirecting party sub-address
	if(src[offset] == AIFG_IEI_DT_REDIRSUBADDR){
		offset++;	//Skip iei
		dst->msg.setup.redirSubaddr.iei = AIFG_IE_ID_DT_REDIRSUBADDR;
		dst->msg.setup.redirSubaddr.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//LLC repeat indicator
	if((src[offset] & 0xF0) == AIFG_IEI_DT_REPEATIND){
		dst->msg.setup.reptInd_llc.iei = AIFG_IE_ID_DT_REPEATIND;
		dst->msg.setup.reptInd_llc.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Low layer comp 1
	if(src[offset] == AIFG_IEI_DT_LOWCOM){
		offset++;	//Skip iei
		dst->msg.setup.lowLComp1.iei = AIFG_IE_ID_DT_LOWCOM;
		dst->msg.setup.lowLComp1.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//Low layer comp 2 
	if(src[offset] == AIFG_IEI_DT_LOWCOM){
		offset++;	//Skip iei
		dst->msg.setup.lowLComp2.iei = AIFG_IE_ID_DT_LOWCOM;
		dst->msg.setup.lowLComp2.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//HLC repeat indicator
	if((src[offset] & 0xF0) == AIFG_IEI_DT_REPEATIND){
		dst->msg.setup.reptInd_hlc.iei = AIFG_IE_ID_DT_REPEATIND;
		dst->msg.setup.reptInd_hlc.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//High layer comp 1
	if(src[offset] == AIFG_IEI_DT_HIGHCOM){
		offset++;	//Skip iei
		dst->msg.setup.highLComp1.iei = AIFG_IE_ID_DT_HIGHCOM;
		dst->msg.setup.highLComp1.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//High layer comp 2
	if(src[offset] == AIFG_IEI_DT_HIGHCOM){
		offset++;	//Skip iei
		dst->msg.setup.highLComp2.iei = AIFG_IE_ID_DT_HIGHCOM;
		dst->msg.setup.highLComp2.ptr = src + offset;
		offset += src[offset] + 1;
		if(offset >= msg_len) goto FINISH;
	}

	//User-user
	if(src[offset] == AIFG_IEI_DT_USERUSER){
		offset++;	//Skip iei
		dst->msg.setup.user_user.iei = AIFG_IE_ID_DT_USERUSER;
		dst->msg.setup.user_user.ptr = src + offset;
		offset += src[offset] + 1;	
		if(offset >= msg_len) goto FINISH;	
	}

	//Priority
	if((src[offset] & 0xF0) == AIFG_IEI_DT_PRIORITYLEVEL){
		dst->msg.setup.priority.iei = AIFG_IE_ID_DT_PRIORITYLEVEL;
		dst->msg.setup.priority.ptr = src + offset;
		offset++;
		if(offset >= msg_len) goto FINISH;
	}

	//Alert
	if(src[offset] == AIFG_IEI_DT_ALERTPATTERN){
		offset++;	//Skip iei
		dst->msg.setup.alert.iei = AIFG_IE_ID_DT_ALERTPATTERN;
		dst->msg.setup.alert.ptr = src + offset;
		offset += src[offset] + 1;
	}
	
	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
	offset++;	//Skip iei
	dst->msg.setup.ssVer.iei = AIFG_IE_ID_DT_SSVER;
	dst->msg.setup.ssVer.ptr = src + offset;
	offset += src[offset] + 1;		
	}

	//CLIR suppression
	if(src[offset] == AIFG_IEI_DT_CLIRSUP){
	dst->msg.setup.clirSuppr.iei = AIFG_IE_ID_DT_CLIRSUP;
	dst->msg.setup.clirSuppr.ptr = src + offset;
	offset++;
	}

	//CLIR invocation
	if(src[offset] == AIFG_IEI_DT_CLIRIVO){
	dst->msg.setup.clirInvo.iei = AIFG_IE_ID_DT_CLIRIVO;
	dst->msg.setup.clirInvo.ptr = src + offset;
	offset++;
	}

	//CC capabilities
	if(src[offset] == AIFG_IEI_DT_CCCAP){
	dst->msg.setup.ccCap.iei = AIFG_IE_ID_DT_CCCAP;
	dst->msg.setup.ccCap.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Start DTMF
int aifg_msg_rv_startDTMF(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.startDTMF), 0, sizeof(dst->msg.startDTMF));

	//Keypad facility - M
	dst->msg.startDTMF.keypadFacility.iei = AIFG_IE_ID_DT_KEYPAD;
	dst->msg.startDTMF.keypadFacility.ptr = src + 1;	//skip IEI

	return AIFG_SUCCEED;
}

//Start DTMF Acknowledge
//The same as Start DTMF

//Start DTMF reject
//The same as Hold Reject

//Status
int aifg_msg_rv_status(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.status), 0, sizeof(dst->msg.status));

	//Cause - M
	dst->msg.status.cause.iei = AIFG_IE_ID_DT_CAUSE;
	dst->msg.status.cause.ptr = src + offset;
	offset += src[offset] + 1;

	//Call state - M
	dst->msg.status.callState.iei = AIFG_IE_ID_DT_CALLSTAT;
	dst->msg.status.callState.ptr = src + offset;
	offset++;
	if(offset >= msg_len) goto FINISH;

	//Auxiliary states
	if(src[offset] == AIFG_IEI_DT_AUXSTAT){
		offset++;	//Skip iei
		dst->msg.status.auxState.iei = AIFG_IE_ID_DT_AUXSTAT;
		dst->msg.status.auxState.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//User information
int aifg_msg_rv_userInfo(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.userInfo), 0, sizeof(dst->msg.userInfo));

	//User-user - M
	dst->msg.userInfo.user_user.iei = AIFG_IE_ID_DT_USERUSER;
	dst->msg.userInfo.user_user.ptr = src + offset;
	offset += src[offset] + 1;		
	if(offset >= msg_len) goto FINISH;

	//More data
	if(src[offset] == AIFG_IEI_DT_MOREDATA){
		offset++;	//Skip iei
		dst->msg.userInfo.moreDate.iei = AIFG_IE_ID_DT_MOREDATA;
		dst->msg.userInfo.moreDate.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//Facility SS
int aifg_msg_rv_facilitySS(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.facilitySS), 0, sizeof(dst->msg.facilitySS));

	//Facility
	dst->msg.facilitySS.facility.iei = AIFG_IE_ID_DT_FACILITY;
	dst->msg.facilitySS.facility.ptr = src;

	return AIFG_SUCCEED;
}

//Release Complete SS
int aifg_msg_rv_releaseCompSS(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.releaseCompSS), 0, sizeof(dst->msg.releaseCompSS));

	//Cause
	if(src[offset] == AIFG_IEI_DT_CAUSE){
		offset++;	//Skip iei
		dst->msg.releaseCompSS.cause.iei = AIFG_IE_ID_DT_CAUSE;
		dst->msg.releaseCompSS.cause.ptr = src + offset;
	}

	//Facility
	if(src[offset] == AIFG_IEI_DT_FACILITY){
		offset++;	//Skip iei
		dst->msg.releaseCompSS.facility.iei = AIFG_IE_ID_DT_FACILITY;
		dst->msg.releaseCompSS.facility.ptr = src + offset;
	}

	return AIFG_SUCCEED;
}

//Register
int aifg_msg_rv_register(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.registerSS), 0, sizeof(dst->msg.registerSS));

	//Facility
	if(src[offset] != AIFG_IEI_DT_FACILITY)
		goto ERR_PROC;

	offset++;	//Skip iei
	dst->msg.registerSS.facility.iei = AIFG_IE_ID_DT_FACILITY;
	dst->msg.registerSS.facility.ptr = src + offset;
	offset += src[offset] + 1;
	if(offset >= msg_len)
		goto FINISH;


	//SS version
	if(src[offset] == AIFG_IEI_DT_SSVER){
		offset++;	//Skip iei
		dst->msg.registerSS.ssVer.iei = AIFG_IE_ID_DT_SSVER;
		dst->msg.registerSS.ssVer.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;

ERR_PROC:
	aifg_debug_print(-1, AIFG_ERR_MISS_MANDATORY, dst, 0);
	return AIFG_ERROR;
}

//SMS
//RP DATA
int aifg_msg_rv_rp_data(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.rpData), 0, sizeof(dst->msg.rpData));

	//reference
	dst->msg.rpData.ref = src[offset++];

	//RP-Originator Address
	dst->msg.rpData.moAddr.iei = AIFG_IE_ID_DT_RP_MO_ADDR;
	dst->msg.rpData.moAddr.ptr = src + offset;
	offset += src[offset] + 1;

	//RP-Destination Address
	dst->msg.rpData.mtAddr.iei = AIFG_IE_ID_DT_RP_MT_ADDR;
	dst->msg.rpData.mtAddr.ptr = src + offset;
	offset += src[offset] + 1;

	//RP-User Data
	dst->msg.rpData.data.iei = AIFG_IE_ID_DT_RP_UD;
	dst->msg.rpData.data.ptr = src + offset;

	return AIFG_SUCCEED;
}

////RP SMMA
int aifg_msg_rv_rp_smma(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	memset(&(dst->msg.rpSMMA), 0, sizeof(dst->msg.rpSMMA));

	//reference
	dst->msg.rpSMMA.ref = src[0];
	return AIFG_SUCCEED;
}

//RP ACK
int aifg_msg_rv_rp_ack(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.rpAck), 0, sizeof(dst->msg.rpAck));

	//reference
	dst->msg.rpAck.ref = src[offset++];
	if(offset >= msg_len)
		goto FINISH;

	//RP-User Data
	if(src[offset] == AIFG_IEI_DT_RP_UD){
		dst->msg.rpAck.data.iei = AIFG_IE_ID_DT_RP_UD;
		dst->msg.rpAck.data.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//RP ERROR
int aifg_msg_rv_rp_error(BYTE *src, aifg_msg_pre_decoded *dst, BYTE msg_len)
{
	int offset = 0;
	memset(&(dst->msg.rpError), 0, sizeof(dst->msg.rpError));

	//reference
	dst->msg.rpError.ref = src[offset++];

	//RP-Cause
	dst->msg.rpError.cause.iei = AIFG_IE_ID_DT_RP_CAUSE;
	dst->msg.rpError.cause.ptr = src + offset;
	offset += src[offset] + 1;
	if(offset >= msg_len)
		goto FINISH;

	//RP-User Data
	if(src[offset] == AIFG_IEI_DT_RP_UD){
		dst->msg.rpError.data.iei = AIFG_IE_ID_DT_RP_UD;
		dst->msg.rpError.data.ptr = src + offset;
	}

FINISH:
	return AIFG_SUCCEED;
}

//End of message decode function definition-----------------------------------------

//Message encode functions definition-----------------------------------------------
//For embedded DTAP messages in BSSMAP message
int aifg_msg_encode_embeded_l3msg(aifg_msg_bm_l3msg *l3msg, BYTE *dst)
{
	int offset = 0;

	assert(l3msg != NULL && dst != NULL);

	switch(l3msg->id){
		case AIFG_MSG_ID_CM_REQUEST:
			dst[offset++] = 0x05;	//PD
			dst[offset++] = AIFG_MSG_T_CM_REQUEST;

			//CM serviece type
			assert(l3msg->msg.cmRequest.cmType.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CMTYPE, 
				(ie_u *)&( l3msg->msg.cmRequest.cmType), dst+offset, AIFG_LOW_BITS);

			//ciphering kye sequence number
			assert(l3msg->msg.cmRequest.cipherKey.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CIPHERKEY, 
				(ie_u *)&( l3msg->msg.cmRequest.cipherKey), dst+offset, AIFG_HIGH_BITS);

			//mobile station classmark2
			assert(l3msg->msg.cmRequest.cmInfo2.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MSCM2, 
				(ie_u *)&( l3msg->msg.cmRequest.cmInfo2), dst+offset, 0);

			//mobile identity
			assert(l3msg->msg.cmRequest.mobileId.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID, 
				(ie_u *)&( l3msg->msg.cmRequest.mobileId), dst+offset, 0);

			//priority level
			if(l3msg->msg.cmRequest.priority.flag == 1){
				offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PRIORITYLEVEL, 
					(ie_u *)&( l3msg->msg.cmRequest.priority), dst+offset, 2);
			}
			break;

		case AIFG_MSG_ID_LU_REQUEST:
			dst[offset++] = 0x05;	//PD
			dst[offset++] = AIFG_MSG_T_LU_REQUEST;

			//location updating type
			assert(l3msg->msg.luRequest.luType.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LUTYPE, 
				(ie_u *)&(l3msg->msg.luRequest.luType), dst+offset, 0);

			//ciphering key sequence
			assert(l3msg->msg.luRequest.cipherKey.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CIPHERKEY, 
				(ie_u *)&(l3msg->msg.luRequest.cipherKey), dst+offset, 1);

			//location area identification
			assert(l3msg->msg.luRequest.lai.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LAI, 
				(ie_u *)&(l3msg->msg.luRequest.lai), dst+offset, 0);

			//mobile station classmark1
			assert(l3msg->msg.luRequest.cmInfo1.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MSCM1, 
				(ie_u *)&(l3msg->msg.luRequest.cmInfo1), dst+offset, 0);

			//mobile identity
			assert(l3msg->msg.luRequest.mobileId.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID, 
				(ie_u *)&(l3msg->msg.luRequest.mobileId), dst+offset, 0);
			break;

		case AIFG_MSG_ID_CM_REEST_REQUEST:
			dst[offset++] = 0x05;	//PD
			dst[offset++] = AIFG_MSG_T_CM_REEST_REQUEST;

			//ciphering key sequence number
			assert(l3msg->msg.cmReEstReq.cipherKey.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CIPHERKEY, 
				(ie_u *)&(l3msg->msg.cmReEstReq.cipherKey), dst+offset, 0);
			offset++;

			//mobile station classmark2
			assert(l3msg->msg.cmReEstReq.cmInfo2.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MSCM2, 
				(ie_u *)&(l3msg->msg.cmReEstReq.cmInfo2), dst+offset, 0);

			//mobile identity
			assert(l3msg->msg.cmReEstReq.mobileId.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID, 
				(ie_u *)&(l3msg->msg.cmReEstReq.mobileId), dst+offset, 0);

			//location area identification
			if(l3msg->msg.cmReEstReq.lai.flag == 1){
				offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LAI, 
					(ie_u *)&(l3msg->msg.cmReEstReq.lai), dst+offset, 2);
			}
			break;

		case AIFG_MSG_ID_PAGING_RESP:
			dst[offset++] = 0x06;	//PD
			dst[offset++] = AIFG_MSG_T_PAGING_RESP;

			//ciphering key sequence number
			assert(l3msg->msg.pagingResp.cipherKey.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CIPHERKEY, 
				(ie_u *)&(l3msg->msg.pagingResp.cipherKey), dst+offset, 0);
			offset++;

			//mobile station classmark2
			assert(l3msg->msg.pagingResp.cmInfo2.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MSCM2, 
				(ie_u *)&(l3msg->msg.pagingResp.cmInfo2), dst+offset, 0);

			//mobile identity
			assert(l3msg->msg.pagingResp.mobileId.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID, 
				(ie_u *)&(l3msg->msg.pagingResp.mobileId), dst+offset, 0);			
			break;

		case AIFG_MSG_ID_IMSI_DETACH_IND:
			dst[offset++] = 0x05;	//PD
			dst[offset++] = AIFG_MSG_T_IMSI_DETACH_IND;

			//mobile station classmark1
			assert(l3msg->msg.imsiDetachInd.cmInfo1.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MSCM1, 
				(ie_u *)&(l3msg->msg.imsiDetachInd.cmInfo1), dst+offset, 0);			

			//mobile identity
			assert(l3msg->msg.imsiDetachInd.mobileId.flag == 1);
			offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID,
				(ie_u *)&(l3msg->msg.imsiDetachInd.mobileId), dst+offset, 0);
			break;

		case AIFG_MSG_ID_RR_HO_CMD:
			//TODO
			dst[offset++] = 0x06;	//PD
			break;

		default:
			assert(0);
			goto ERR_PROC;
	}

	return offset;

ERR_PROC:
	return offset;
}

//Assign request
int aifg_msg_sd_assignReq(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_assignReq *assignReq = &(src->msg.assignReq);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_ASSIGN_REQ;

	//Channel type - M
	assert(assignReq->channelType.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHANNELTYPE, (ie_u*)&(assignReq->channelType), dst+offset, 0);

	//Layer 3 Header Information
	if(assignReq->l3HeaderInfo.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_L3HEADERINFO, (ie_u*)&(assignReq->l3HeaderInfo), dst+offset, 0);
	}

	//Priority
	if(assignReq->priority.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_PRIORITY, (ie_u*)&(assignReq->priority), dst+offset, 0);
	}

	//CIC
	if(assignReq->cic.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(assignReq->cic), dst+offset, 0);
	}

	//Downlink DTX Flag
	if(assignReq->dtxFlag.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_DTXFLAG, (ie_u*)&(assignReq->dtxFlag), dst+offset, 0);
	}

	//Interference Band To Be Used
	if(assignReq->bandUsed.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_BANDUSED, (ie_u*)&(assignReq->bandUsed), dst+offset, 0);
	}

	//Classmark Information 2
	if(assignReq->cm2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CLASSMARKINFO2, (ie_u*)&(assignReq->cm2), dst+offset, 0);
	}

	//Group Call Reference
	if(assignReq->groupRef.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_GROUPCALLREF, (ie_u*)&(assignReq->groupRef), dst+offset, 0);
	}

	//Talker Flag
	if(assignReq->talkerFlag.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_GROUPCALLREF, (ie_u*)&(assignReq->talkerFlag), dst+offset, 0);
	}

	//Configuration Evolution Indication
	if(assignReq->cfgEvoInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CFGEVOIND, (ie_u*)&(assignReq->cfgEvoInd), dst+offset, 0);
	}

	return offset;
}

//ASSIGNMENT COMPLETE
int aifg_msg_sd_assignComplete(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_assignComplete *assignComp = &(src->msg.assignComplete);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_ASSIGN_CMP;

	//RR Cause
	if(assignComp->rrCause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RRCAUSE, (ie_u*)&(assignComp->rrCause),dst+offset, 0);
	}

	//CIC
	if(assignComp->cic.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(assignComp->cic), dst+offset, 0);
	}

	//Cell Identifier
	if(assignComp->cellId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, (ie_u*)&(assignComp->cellId), dst+offset, 0);
	}

	//Chosen Channel
	if(assignComp->chosenChannel.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENCHANNEL, (ie_u*)&(assignComp->chosenChannel), dst+offset, 0);
	}

	//Chosen Encryption Algorithm
	if(assignComp->chosenEncrypt.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENENCRYPT, (ie_u*)&(assignComp->chosenEncrypt), dst+offset, 0);
	}

	//Circuit Pool
	if(assignComp->circuitPool.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIRCUITPOOL, (ie_u*)&(assignComp->circuitPool), dst+offset, 0);
	}

	//Speech Version (Chosen)
	if(assignComp->speechVer.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_SPEECHVER, (ie_u*)&(assignComp->speechVer), dst+offset, 0);
	}

	//LSA Identifier
	if(assignComp->lsaId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LSAID, (ie_u*)&(assignComp->lsaId), dst+offset, 0);
	}

	return offset;
}

//ASSIGNMENT FAILURE
int aifg_msg_sd_assignFailure(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_assignFailure *assignFail = &(src->msg.assignFailure);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_ASSIGN_FAIL;

	//Cause
	assert(assignFail->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, (ie_u*)&(assignFail->cause), dst+offset, 0);

	//RR Cause
	if(assignFail->rrCause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RRCAUSE, (ie_u*)&(assignFail->rrCause),dst+offset, 0);
	}

	//Circuit Pool
	if(assignFail->circuitPool.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIRCUITPOOL, (ie_u*)&(assignFail->circuitPool), dst+offset, 0);
	}

	//Circuit Pool List
	if(assignFail->circuitPoolList.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIRCUITPOOLLIST, (ie_u*)&(assignFail->circuitPoolList), dst+offset, 0);
	}

	return offset;
}

//BLOCK
int aifg_msg_sd_block(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_block *block = &(src->msg.block);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_BLOCK;

	//CIC
	assert(block->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(block->cic),dst+offset, 0);

	//Cause
	assert(block->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, (ie_u*)&(block->cause), dst+offset, 0);

	//Connection Release Requested
	if(block->connRelReq.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CONNRELREQ, (ie_u*)&(block->connRelReq), dst+offset, 0);
	}

	return offset;
}

//BLOCKING ACKNOWLEDGE
int aifg_msg_sd_blockAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_blockAck *blockAck = &(src->msg.blockAck);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_BLOCK_ACK;

	//CIC
	assert(blockAck->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(blockAck->cic),dst+offset, 0);

	return offset;
}

//UNBLOCK
int aifg_msg_sd_unblock(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_unblock *unblock = &(src->msg.unblock);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_UNBLOCK;

	//CIC
	assert(unblock->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(unblock->cic),dst+offset, 0);

	return offset;
}

//UNBLOCK ACKNOWLEDGE
int aifg_msg_sd_unblockAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_unblockAck *unblockAck = &(src->msg.unblockAck);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_UNBLOCK_ACK;

	//CIC
	assert(unblockAck->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(unblockAck->cic),dst+offset, 0);

	return offset;
}

//HANDOVER REQUEST
int aifg_msg_sd_HORequest(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HORequest *HOReq = &(src->msg.HORequest);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_REQUEST;

	//CHANNEL TYPE
	assert(HOReq->channelType.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHANNELTYPE, (ie_u*)&(HOReq->channelType),dst+offset, 0);

	//Encryption Information
	assert(HOReq->encryptInfo.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_ENCRYPTINFO, (ie_u*)&(HOReq->encryptInfo),dst+offset, 0);

	//Classmark information
	if(HOReq->cmInfo.cm2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CLASSMARKINFO2, (ie_u*)&(HOReq->cmInfo.cm2),dst+offset, 0);
	}else if(HOReq->cmInfo.cm1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CLASSMARKINFO1, (ie_u*)&(HOReq->cmInfo.cm1),dst+offset, 0);
	}else{
		//should never runs to here
		assert(0);
	}

	//Cell Identifier (Serving)
	assert(HOReq->servingCellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, (ie_u*)&(HOReq->servingCellId),dst+offset, 0);

	//Priority
	if(HOReq->priority.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_PRIORITY, (ie_u*)&(HOReq->priority),dst+offset, 0);
	}

	//Circuit Identity Code
	if(HOReq->cic.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(HOReq->cic),dst+offset, 0);
	}

	//Downlink DTX Flag
	if(HOReq->dtxFlag.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_DTXFLAG, (ie_u*)&(HOReq->dtxFlag),dst+offset, 0);
	}

	//Cell Identifier (Target)
	assert(HOReq->targetCellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, (ie_u*)&(HOReq->targetCellId),dst+offset, 0);

	//Interference Band To Be Used
	if(HOReq->bandUsed.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_BANDUSED, (ie_u*)&(HOReq->bandUsed),dst+offset, 0);
	}

	//Cause
	if(HOReq->cause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, (ie_u*)&(HOReq->cause),dst+offset, 0);
	}

	//Classmark Information 3
	//	if(HOReq->c.flag == 1){
	//		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, (ie_u*)&(HOReq->cause),dst+offset, 0);
	//	}

	//Current Channel type 1
	if(HOReq->curChannelType1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CURCHANNELTYPE1, (ie_u*)&(HOReq->curChannelType1),dst+offset, 0);
	}

	//Speech Version (Used)
	if(HOReq->speechVer.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_SPEECHVER, (ie_u*)&(HOReq->speechVer),dst+offset, 0);
	}

	//Group Call Reference
	if(HOReq->gourpRef.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_GROUPCALLREF, (ie_u*)&(HOReq->gourpRef),dst+offset, 0);
	}

	//Talker Flag
	if(HOReq->talkerFlag.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TALKERFLAG, (ie_u*)&(HOReq->talkerFlag),dst+offset, 0);
	}

	//Configuration Evolution Indication
	if(HOReq->cfgEvoInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CFGEVOIND, (ie_u*)&(HOReq->cfgEvoInd),dst+offset, 0);
	}

	//Chosen Encryption Algorithm (Serving)
	if(HOReq->chosenEncrypt.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENENCRYPT, (ie_u*)&(HOReq->chosenEncrypt),dst+offset, 0);
	}

	//Old BSS to New BSS Information
	if(HOReq->bssOldtoNew.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_BSSOLDTONEW, (ie_u*)&(HOReq->bssOldtoNew),dst+offset, 0);
	}

	//LSA Information
	if(HOReq->lsaInfo.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LSAINFO, (ie_u*)&(HOReq->lsaInfo),dst+offset, 0);
	}

	return offset;
}

//HANDOVER REQUIRED
int aifg_msg_sd_HORequired(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HORequired *HORequired = &(src->msg.HORequired);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_REQUIRED;

	//Cause
	assert(HORequired->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, (ie_u*)&(HORequired->cause),dst+offset, 0);

	//Response Request
	if(HORequired->respReq.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RESPREQ, (ie_u*)&(HORequired->respReq),dst+offset, 0);
	}

	//Cell Identifier List (Preferred)
	assert(HORequired->prefer_cidList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLIDLIST, 
		(ie_u*)&(HORequired->prefer_cidList),dst+offset, 0);

	//Circuit Pool List
	if(HORequired->circuitPoolList.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIRCUITPOOLLIST, 
			(ie_u*)&(HORequired->circuitPoolList),dst+offset, 0);
	}

	//Current Channel type 1
	if(HORequired->curChannelType1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CURCHANNELTYPE1, 
			(ie_u*)&(HORequired->curChannelType1),dst+offset, 0);
	}

	//Speech Version (Used)
	if(HORequired->speechVer.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_SPEECHVER, 
			(ie_u*)&(HORequired->speechVer),dst+offset, 0);
	}

	//Queueing Indicator
	if(HORequired->queuingInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_QUEUEIND, 
			(ie_u*)&(HORequired->queuingInd),dst+offset, 0);
	}

	//Old BSS to New BSS Information
	if(HORequired->bssOldtoNew.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_BSSOLDTONEW, 
			(ie_u*)&(HORequired->bssOldtoNew),dst+offset, 0);
	}

	return offset;
}

//HANDOVER REQUEST ACKNOWLEDGE
int aifg_msg_sd_HORequestAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HORequestAck *HOReqAck  = &(src->msg.HORequestAck);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_REQ_ACK;

	//Layer 3 Information
	dst[offset++] = AIFG_IEI_BM_L3INFO;
	dst[offset++] = HOReqAck->l3Info.len;
	memcpy(dst+offset, HOReqAck->l3Info.ptr, HOReqAck->l3Info.len);
	offset += HOReqAck->l3Info.len;

	//Chosen Channel
	if(HOReqAck->chosenChannel.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENCHANNEL, (ie_u*)&(HOReqAck->chosenChannel),dst+offset, 0);
	}

	//Chosen Encryption Algorithm
	if(HOReqAck->chosenEncrypt.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENENCRYPT, (ie_u*)&(HOReqAck->chosenEncrypt),dst+offset, 0);
	}

	//Circuit Pool
	if(HOReqAck->circuitPool.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIRCUITPOOL, (ie_u*)&(HOReqAck->circuitPool),dst+offset, 0);
	}

	//Speech Version (Chosen)
	if(HOReqAck->speechVer.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_SPEECHVER, (ie_u*)&(HOReqAck->speechVer),dst+offset, 0);
	}

	//Circuit Identity Code
	if(HOReqAck->cic.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(HOReqAck->cic),dst+offset, 0);
	}

	//LSA Identifier
	if(HOReqAck->lsaId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LSAID, (ie_u*)&(HOReqAck->lsaId),dst+offset, 0);
	}

	return offset;
}

//HANDOVER COMMAND
int aifg_msg_sd_HOCmd(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HOCmd *HOCmd  = &(src->msg.HOCmd);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_CMD;
	//Layer 3 Information
	dst[offset++] = AIFG_IEI_BM_L3INFO;
	dst[offset++] = HOCmd->l3Info.len;
	memcpy(dst+offset, HOCmd->l3Info.ptr, HOCmd->l3Info.len);
	offset += HOCmd->l3Info.len;

	//Cell Identifier
	if(HOCmd->cellId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, (ie_u*)&(HOCmd->cellId),dst+offset, 0);
	}

	return offset;
}

//HANDOVER COMPLETE
int aifg_msg_sd_HOComplete(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HOComplete *HOcomplete  = &(src->msg.HOComplete);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_CMP;

	//RR Cause
	if(HOcomplete->rrCause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RRCAUSE, (ie_u*)&(HOcomplete->rrCause),dst+offset, 0);
	}

	return offset;
}

//HANDOVER SUCCEEDED
int aifg_msg_sd_HOSucceed(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;

	dst[offset++] = AIFG_MSG_T_HO_SUC;

	return offset;
}

//HANDOVER CANDIDATE ENQUIRE
int aifg_msg_sd_HOCandEnq(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HOCandidateEnq *HOCandEnq  = &(src->msg.HOCandidateEnq);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_CAN_ENQ;

	//Number Of Mss
	assert(HOCandEnq->msNum.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_MSNUM, 
		(ie_u*)&(HOCandEnq->msNum),dst+offset, 0);

	//Cell Identifier List
	assert(HOCandEnq->cidList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLIDLIST, 
		(ie_u*)&(HOCandEnq->cidList),dst+offset, 0);

	//Cell Identifier
	assert(HOCandEnq->cellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, 
		(ie_u*)&(HOCandEnq->cellId),dst+offset, 0);

	return offset;
}

//HANDOVER CANDIDATE RESPONSE
int aifg_msg_sd_HOCandResp(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HOCandidateResp *HOCandResp  = &(src->msg.HOCandidateResp);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_CAN_RESP;

	//Number Of Mss
	assert(HOCandResp->msNum.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_MSNUM, 
		(ie_u*)&(HOCandResp->msNum),dst+offset, 0);

	//Cell Identifier
	assert(HOCandResp->cellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, 
		(ie_u*)&(HOCandResp->cellId),dst+offset, 0);

	return offset;
}

//HANDOVER FAILURE
int aifg_msg_sd_HOFailure(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HOFailure *HOFailure = &(src->msg.HOFailure);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_FAIL;

	//Cause
	assert(HOFailure->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(HOFailure->cause), dst+offset, 0);

	//RR Cause
	if(HOFailure->rrCause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RRCAUSE, 
			(ie_u*)&(HOFailure->rrCause),dst+offset, 0);
	}

	//Circuit Pool
	if(HOFailure->circuitPool.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIRCUITPOOL, 
			(ie_u*)&(HOFailure->circuitPool), dst+offset, 0);
	}

	//Circuit Pool List
	if(HOFailure->circuitPoolList.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIRCUITPOOLLIST, 
			(ie_u*)&(HOFailure->circuitPoolList), dst+offset, 0);
	}

	return offset;
}

//RESOURCE REQUEST
int aifg_msg_sd_resrcReq(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_resrcReq *resrcReq = &(src->msg.resourceReq);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RESRC_REQ;

	//Periodicity
	assert(resrcReq->periodicity.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_PERIODICITY, 
		(ie_u*)&(resrcReq->periodicity), dst+offset, 0);

	//Resource Indication Method
	assert(resrcReq->resrcIndMethod.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RESOURCEINDMEHTOD, 
		(ie_u*)&(resrcReq->resrcIndMethod),dst+offset, 0);

	//Cell Identifier
	assert(resrcReq->cellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID,
		(ie_u*)&(resrcReq->cellId), dst+offset, 0);

	//Extended Resource Indicator
	if(resrcReq->extResrcInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_EXTRESOURCEIND, 
			(ie_u*)&(resrcReq->extResrcInd), dst+offset, 0);
	}

	return offset;
}

//RESOURCE INDICATION
int aifg_msg_sd_resrcInd(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_resrcInd *resrcInd = &(src->msg.resourceInd);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RESRC_IND;

	//Resource Indication Method
	assert(resrcInd->resrcIndMethod.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RESOURCEINDMEHTOD, 
		(ie_u*)&(resrcInd->resrcIndMethod),dst+offset, 0);

	//Resource Available
	if(resrcInd->resrcAvail.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RESOURCEAVAIL, 
			(ie_u*)&(resrcInd->resrcAvail), dst+offset, 0);
	}

	//Cell Identifier
	assert(resrcInd->cellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, 
		(ie_u*)&(resrcInd->cellId), dst+offset, 0);

	//Total Resource Accessible
	if(resrcInd->totalResrc.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TOTALRESOURCE, 
			(ie_u*)&(resrcInd->totalResrc), dst+offset, 0);
	}

	return offset;
}

//PAGING
int aifg_msg_sd_paging(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_paging *paging = &(src->msg.paging);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_PAGING;

	//IMSI
	assert(paging->imsi.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_IMSI, (ie_u*)&(paging->imsi),dst+offset, 0);

	//TMSI
	if(paging->tmsi.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TMSI, 
			(ie_u*)&(paging->tmsi), dst+offset, 0);
	}

	//Cell Identifier List
	assert(paging->cidList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLIDLIST, 
		(ie_u*)&(paging->cidList), dst+offset, 0);

	//Channel Needed
	if(paging->channelNeeded.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHANNELNEEDED, 
			(ie_u*)&(paging->channelNeeded), dst+offset, 0);
	}

	//eMLPP Priority
	if(paging->eMLPP.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_EMLPP, 
			(ie_u*)&(paging->eMLPP), dst+offset, 0);
	}

	return offset;
}

//CLEAR REQUEST
int aifg_msg_sd_clearReq(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_clearReq *clearReq = &(src->msg.clearReq);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CLR_REQ;

	//Cause
	assert(clearReq->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(clearReq->cause),dst+offset, 0);

	return offset;
}

//CLEAR COMMAND
int aifg_msg_sd_clearCmd(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_clearCmd *clearCmd = &(src->msg.clearCmd);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CLR_CMD;

	//Layer 3 Header Information
	if(clearCmd->l3HeaderInfo.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_L3HEADERINFO, 
			(ie_u*)&(clearCmd->l3HeaderInfo), dst+offset, 0);
	}

	//Cause
	assert(clearCmd->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(clearCmd->cause),dst+offset, 0);

	return offset;
}

//CLEAR COMPLETE
int aifg_msg_sd_clearComplete(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;

	dst[offset++] = AIFG_MSG_T_CLR_CMP;

	return offset;
}

//RESET
int aifg_msg_sd_reset(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_reset *reset = &(src->msg.reset);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RESET;

	//Cause
	assert(reset->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, (ie_u*)&(reset->cause),dst+offset, 0);

	return offset;
}

//RESET ACKNOWLEDGE
int aifg_msg_sd_resetAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;

	dst[offset++] = AIFG_MSG_T_RESET_ACK;

	return offset;
}


//HANDOVER PERFORMED
int aifg_msg_sd_HOPerformed(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HOPerformed *HOPerformed = &(src->msg.HOPerformed);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_PERFORMED;

	//Cause
	assert(HOPerformed->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(HOPerformed->cause),dst+offset, 0);

	//Cell Identifier
	assert(HOPerformed->cellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, 
		(ie_u*)&(HOPerformed->cellId),dst+offset, 0);

	//Chosen Channel
	if(HOPerformed->chosenChannel.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENCHANNEL, 
			(ie_u*)&(HOPerformed->chosenChannel), dst+offset, 0);
	}

	//Chosen Encryption Algorithm
	assert(HOPerformed->chosenEncrypt.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENENCRYPT, 
		(ie_u*)&(HOPerformed->chosenEncrypt), dst+offset, 0);

	//Speech Version (Chosen)
	if(HOPerformed->speechVer.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_SPEECHVER, 
			(ie_u*)&(HOPerformed->speechVer), dst+offset, 0);
	}

	//LSA Identifier
	if(HOPerformed->lsaId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LSAID, 
			(ie_u*)&(HOPerformed->lsaId), dst+offset, 0);
	}

	return offset;
}

//OVERLOAD
int aifg_msg_sd_overload(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_overload *overload = &(src->msg.overload);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_OVERLOAD;

	//Cause
	assert(overload->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(overload->cause),dst+offset, 0);

	//Cell Identifier
	if(overload->cellId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, 
			(ie_u*)&(overload->cellId),dst+offset, 0);
	}

	return offset;
}

//MSC INVOKE TRACE
int aifg_msg_sd_mscTrace(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_mscInvokeTrace *mscTrace = &(src->msg.mscInvokeTrace);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_MSC_INVK_TRACE;

	//Trace Type
	assert(mscTrace->traceType.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRACETYPE, 
		(ie_u*)&(mscTrace->traceType),dst+offset, 0);

	//Triggerid
	if(mscTrace->tiggerId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRIGGERID, 
			(ie_u*)&(mscTrace->tiggerId),dst+offset, 0);
	}

	//Trace Reference
	assert(mscTrace->traceRef.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRACEREF, 
		(ie_u*)&(mscTrace->traceRef),dst+offset, 0);

	//Transactionid
	if(mscTrace->transId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRANSACTIONID, 
			(ie_u*)&(mscTrace->transId),dst+offset, 0);
	}

	//Mobile Identity
	if(mscTrace->mobileId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_MOBILEID, 
			(ie_u*)&(mscTrace->mobileId),dst+offset, 0);
	}

	//OMCId
	if(mscTrace->omcId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_OMCID, 
			(ie_u*)&(mscTrace->omcId),dst+offset, 0);
	}

	return offset;
}

//BSS INVOKE TRACE
int aifg_msg_sd_bscTrace(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_bscInvokeTrace *bscTrace = &(src->msg.bscInvokeTrace);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_BSC_INVK_TRACE;

	//Trace Type
	assert(bscTrace->traceType.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRACETYPE, 
		(ie_u*)&(bscTrace->traceType),dst+offset, 0);

	//Forward Indicator
	if(bscTrace->forwardInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_FORWARDIND, 
			(ie_u*)&(bscTrace->forwardInd),dst+offset, 0);
	}

	//Triggerid
	if(bscTrace->tiggerId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRIGGERID, 
			(ie_u*)&(bscTrace->tiggerId),dst+offset, 0);
	}

	//Trace Reference
	assert(bscTrace->traceRef.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRACEREF, 
		(ie_u*)&(bscTrace->traceRef),dst+offset, 0);

	//Transactionid
	if(bscTrace->transId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TRANSACTIONID, 
			(ie_u*)&(bscTrace->transId),dst+offset, 0);
	}

	//OMCId
	if(bscTrace->omcId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_OMCID, 
			(ie_u*)&(bscTrace->omcId),dst+offset, 0);
	}

	return offset;
}

//CLASSMARK UPDATE
int aifg_msg_sd_cmUpdate(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_cmUpdate *cmUpdate = &(src->msg.cmUpdate);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CM_UPDATE;

	//Classmark Information Type 2
	assert(cmUpdate->cm2.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CLASSMARKINFO2, 
		(ie_u*)&(cmUpdate->cm2),dst+offset, 0);

	//Classmark Information Type 3
	//	if(cmUpdate->forwardInd.flag == 1){
	//		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_FORWARDIND, 
	//					(ie_u*)&(cmUpdate->forwardInd),dst+offset, 0);
	//	}

	return offset;
}

//CIPHER MODE COMMAND
int aifg_msg_sd_cipherModeCmd(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_cipherModeCmd *cipherModeCmd = &(src->msg.cipherModeCmd);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CIPHER_MODE_CMD;

	//Layer 3 Header Information
	if(cipherModeCmd->l3HeaderInfo.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_L3HEADERINFO, 
			(ie_u*)&(cipherModeCmd->l3HeaderInfo),dst+offset, 0);
	}

	//Encryption Information
	assert(cipherModeCmd->encryptInfo.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_ENCRYPTINFO, 
		(ie_u*)&(cipherModeCmd->encryptInfo),dst+offset, 0);

	//Cipher Response Mode
	if(cipherModeCmd->cipherRespMode.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIPHERRESPMODE, 
			(ie_u*)&(cipherModeCmd->cipherRespMode),dst+offset, 0);
	}

	return offset;
}

//CIPHER MODE COMPLETE
int aifg_msg_sd_cipherModeComplete(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_cipherModeComplete *cipherModeComplete = &(src->msg.cipherModeComplete);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CIPHER_MODE_CMP;

	//Layer 3 Message Contents
	if(cipherModeComplete->l3Info.flag == 1){
		strncpy((char*)dst+offset, (const char*)cipherModeComplete->l3Info.ptr, cipherModeComplete->l3Info.len);
		offset += cipherModeComplete->l3Info.len;
	}

	//Chosen Encryption Algorithm
	if(cipherModeComplete->chosenEncrypt.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENENCRYPT, 
			(ie_u*)&(cipherModeComplete->chosenEncrypt),dst+offset, 0);
	}

	return offset;
}

//COMPLETE LAYER 3 INFORMATION
int aifg_msg_sd_completeL3Info(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_completeL3Info *completeL3Info = &(src->msg.completeL3Info);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_L3_INFO;

	//Cell Identifier
	assert(completeL3Info->cellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, 
		(ie_u*)&(completeL3Info->cellId),dst+offset, 0);

	//Layer 3 Information, transparent transfer
	dst[offset++] = AIFG_IEI_BM_L3INFO;
	dst[offset++] = completeL3Info->l3Info.len;
	memcpy(dst+offset, completeL3Info->l3Info.ptr, completeL3Info->l3Info.len);
	offset += completeL3Info->l3Info.len;

	/*
	dst[offset++] = AIFG_IEI_BM_L3INFO;
	offset++;	//skip length
	l3msg_len += aifg_msg_encode_embeded_l3msg(&completeL3Info->l3Info, dst+offset);
	dst[offset-1] = l3msg_len;
	offset += l3msg_len;
	*/

	//Chosen Channel
	if(completeL3Info->chosenChannel.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CHOSENCHANNEL, 
			(ie_u*)&(completeL3Info->chosenChannel), dst+offset, 0);
	}

	//LSA Identifier List
	if(completeL3Info->lsaIdList.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LSAIDLIST, 
			(ie_u*)&(completeL3Info->lsaIdList), dst+offset, 0);
	}

	//Location Information
	if(completeL3Info->locInfo.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LOCATIONINFO, 
			(ie_u*)&(completeL3Info->locInfo), dst+offset, 0);
	}

	return offset;
}

//QUEUEING INDICATION
int aifg_msg_sd_queueInd(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;

	dst[offset++] = AIFG_MSG_T_QUEUE_IND;

	return offset;
}

//SAPI "n" REJECT

int aifg_msg_sd_sapi_n_rej(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_SAPI_n_Reject *SAPI_n_Reject = &(src->msg.SAPI_n_Reject);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_SAPI_REJ;

	//DLCI
	assert(SAPI_n_Reject->dlci.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_DLCI, 
		(ie_u*)&(SAPI_n_Reject->dlci),dst+offset, 0);

	//Cause
	assert(SAPI_n_Reject->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(SAPI_n_Reject->cause),dst+offset, 0);

	return offset;
}

//HANDOVER REQUIRED REJECT
int aifg_msg_sd_HORequiredRej(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_HOReject *HOReject = &(src->msg.HOReject);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HO_REQ_REJ;

	//Cause
	assert(HOReject->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(HOReject->cause),dst+offset, 0);

	return offset;
}

//RESET CIRCUIT
int aifg_msg_sd_resetCircuit(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_resetCircuit *resetCircuit = &(src->msg.resetCircuit);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RESET_CC;

	//CIC
	assert(resetCircuit->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, 
		(ie_u*)&(resetCircuit->cic),dst+offset, 0);

	//Cause
	assert(resetCircuit->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(resetCircuit->cause),dst+offset, 0);

	return offset;
}

//RESET CIRCUIT ACKNOWLEDGE
int aifg_msg_sd_resetCircuitAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_resetCircuitAck *resetCircuitAck = &(src->msg.resetCircuitAck);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RESET_CC_ACK;

	//CIC
	assert(resetCircuitAck->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, 
		(ie_u*)&(resetCircuitAck->cic),dst+offset, 0);

	return offset;
}

//HANDOVER DETECT
int aifg_msg_sd_HODetect(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;

	dst[offset++] = AIFG_MSG_T_HO_DETECT;

	return offset;
}

//CIRCUIT GROUP BLOCK
int aifg_msg_sd_ccGrpBlk(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_circuitGrpBlk *circuitGrpBlk = &(src->msg.ccGroupBlock);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CC_GROUP_BLK;

	//Cause
	assert(circuitGrpBlk->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(circuitGrpBlk->cause),dst+offset, 0);

	//CIC
	assert(circuitGrpBlk->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, 
		(ie_u*)&(circuitGrpBlk->cic),dst+offset, 0);

	//Circuit Identity Code List
	assert(circuitGrpBlk->cicList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CICLIST, 
		(ie_u*)&(circuitGrpBlk->cicList),dst+offset, 0);

	return offset;
}

//CIRCUIT GROUP BLOCKING ACKNOWLEDGE
int aifg_msg_sd_ccGroupBlockAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_circuitGrpBlkAck *circuitGrpBlkAck = &(src->msg.ccGroupBlockAck);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CC_GROUP_BLK_ACK;

	//CIC
	assert(circuitGrpBlkAck->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, 
		(ie_u*)&(circuitGrpBlkAck->cic),dst+offset, 0);

	//Circuit Identity Code List
	assert(circuitGrpBlkAck->cicList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CICLIST, 
		(ie_u*)&(circuitGrpBlkAck->cicList),dst+offset, 0);

	return offset;
}

//CIRCUIT GROUP UNBLOCK
int aifg_msg_sd_ccGroupUnblock(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_circuitGrpUnblk *circuitGrpUnblk = &(src->msg.ccGroupUnblock);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CC_GROUP_UNBLK;

	//CIC
	assert(circuitGrpUnblk->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, 
		(ie_u*)&(circuitGrpUnblk->cic),dst+offset, 0);

	//Circuit Identity Code List
	assert(circuitGrpUnblk->cicList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CICLIST, 
		(ie_u*)&(circuitGrpUnblk->cicList),dst+offset, 0);

	return offset;
}

//CIRCUIT GROUP UNBLOCKING ACKNOWLEDGE
int aifg_msg_sd_ccGroupUnblockAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_circuitGrpUnblkAck *circuitGrpUnblkAck = &(src->msg.ccGroupUnblockAck);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CC_GROUP_UNBLK_ACK;

	//CIC
	assert(circuitGrpUnblkAck->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, 
		(ie_u*)&(circuitGrpUnblkAck->cic),dst+offset, 0);

	//Circuit Identity Code List
	assert(circuitGrpUnblkAck->cicList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CICLIST, 
		(ie_u*)&(circuitGrpUnblkAck->cicList),dst+offset, 0);

	return offset;
}

//CONFUSION
int aifg_msg_sd_confusion(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_confusion *confusion = &(src->msg.confusion);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CONFUSION;

	//Cause
	assert(confusion->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(confusion->cause),dst+offset, 0);

	//Diagnostics
	assert(confusion->diagnostics.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_DIGNOSTIC, 
		(ie_u*)&(confusion->diagnostics),dst+offset, 0);

	return offset;
}

//CLASSMARK REQUEST
int aifg_msg_sd_classmarkReq(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;

	dst[offset++] = AIFG_MSG_T_CLASSMARK_REQ;

	return offset;
}

//UNEQUIPPED CIRCUIT
int aifg_msg_sd_unequippedCircuit(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_unequippedCircuit *unequippedCircuit = &(src->msg.unequippedCircuit);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_UNEQUIP_CC;

	//CIC
	assert(unequippedCircuit->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, 
		(ie_u*)&(unequippedCircuit->cic),dst+offset, 0);

	//Circuit Identity Code List
	if(unequippedCircuit->cicList.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CICLIST, 
			(ie_u*)&(unequippedCircuit->cicList),dst+offset, 0);
	}

	return offset;
}

//CIPHER MODE REJECT
int aifg_msg_sd_cipherModeRej(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_cipherModeReject *cipherModeReject = &(src->msg.cipherModeReject);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CIPHER_MODE_REJ;

	//Cause
	assert(cipherModeReject->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
		(ie_u*)&(cipherModeReject->cause),dst+offset, 0);

	return offset;
}

//LOAD INDICATION
int aifg_msg_sd_loadInd(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_loadIndication *loadInd = &(src->msg.loadInd);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_LOAD_IND;

	//Time Indication
	assert(loadInd->timeInd.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_TIMEIND, 
		(ie_u*)&(loadInd->timeInd),dst+offset, 0);

	//Cell Identifier
	assert(loadInd->cellId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLID, 
		(ie_u*)&(loadInd->cellId),dst+offset, 0);

	//Cell Identifier List(Target)
	assert(loadInd->cidList.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CELLIDLIST, 
		(ie_u*)&(loadInd->cidList), dst+offset, 0); 

	//Resource Situation
	if(loadInd->resrcSit.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_RESOURCESITUATION, 
			(ie_u*)&(loadInd->resrcSit), dst+offset, 0);
	}

	//Cause
	if(loadInd->cause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
			(ie_u*)&(loadInd->cause),dst+offset, 0);
	}

	return offset;
}

//SUSPEND
int aifg_msg_sd_suspend(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_suspend *suspend = &(src->msg.suspend);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_SUSPEND;

	//DLCI
	assert(suspend->dlci.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_DLCI, (ie_u*)&(suspend->dlci),dst+offset, 0);

	return offset;
}

//RESUME
int aifg_msg_sd_resume(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_resume *resume = &(src->msg.resume);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RESUME;

	//DLCI
	assert(resume->dlci.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_DLCI, (ie_u*)&(resume->dlci),dst+offset, 0);

	return offset;
}

//CHANGE CIRCUIT
int aifg_msg_sd_changeCircuit(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_changeCircuit *changeCircuit = &(src->msg.changeCircuit);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CHANGE_CC;

	//Cause
	assert(changeCircuit->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, (ie_u*)&(changeCircuit->cause),dst+offset, 0);

	return offset;
}

//CHANGE CIRCUIT ACKNOWLEDGE
int aifg_msg_sd_changeCircuitAck(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_changeCircuitAck *changeCircuitAck = &(src->msg.changeCircuitAck);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CHANGE_CC_ACK;

	//CIC
	assert(changeCircuitAck->cic.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CIC, (ie_u*)&(changeCircuitAck->cic),dst+offset, 0);

	return offset;
}

/*
//LSA INFORMATION
int aifg_msg_sd_lsaInfo(aifg_msg_t *src, BYTE *dst)
{
int offset = 0;
aifg_msg_bm_lsaInfo *lsaInfo = &(src->msg.lsaInfo);

assert(src != NULL && dst != NULL);

dst[offset++] = AIFG_MSG_T_LSA_INFO;

//LSA Information
assert(lsaInfo->lsaInfo.flag == 1);
offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LSAINFO, (ie_u*)&(lsaInfo->lsaInfo),dst+offset, 0);

return offset;
}
*/

//Location Information Command
int aifg_msg_sd_locCmd(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_locCmd *locCmd = &(src->msg.locCmd);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_LOC_INFO_CMD;

	//Location Information
	assert(locCmd->locInfo.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LOCATIONINFO, 
		(ie_u*)&(locCmd->locInfo), dst+offset, 0);

	return offset;
}

//Location Information Report
int aifg_msg_sd_locReport(aifg_msg_t *src, BYTE *dst)
{
	int offset = 0;
	aifg_msg_bm_locReport *locReport = &(src->msg.locReport);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_LOC_INFO_RPT;

	//Location Information
	if(locReport->locInfo.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_LOCATIONINFO, 
			(ie_u*)&(locReport->locInfo), dst+offset, 0);
	}
	else if(locReport->cause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_BSSMAP, AIFG_IE_ID_BM_CAUSE, 
			(ie_u*)&(locReport->cause), dst+offset, 0);
	}

	else
		assert(0);	//should never runs to here

	return offset;
}

//DTAP---------------------------------------------------------------------------------
int aifg_msg_sd_luAccept(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_luAccept *luAccept = &(src->msg.luAccept);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_LU_ACCEPT;


	//location area identification
	assert(luAccept->lai.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LAI, 
		(ie_u *)&( luAccept->lai), dst+offset, 0);


	//mobile identity
	if(luAccept->mobileId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID, 
			(ie_u *)&( luAccept->mobileId), dst+offset, 2);
	}

	//follow on proceed
	if(luAccept->followOnProceed.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FLONPROCEED, 
			(ie_u *)&( luAccept->followOnProceed), dst+offset, 2);
	}

	//CTS permission
	if(luAccept->CTSPermission.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CTS, 
			(ie_u *)&( luAccept->CTSPermission), dst+offset, 2);
	}

	return offset;
}

//CM service reject
int aifg_msg_sd_cmRej(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_cmReject *cmRej = &(src->msg.cmReject);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CM_REJECT;

	//reject cause
	assert(cmRej->rejectCause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REJCAUSE, (ie_u *)&( cmRej->rejectCause), dst+offset, 0);

	return offset;
}

//location updating reject
int aifg_msg_sd_luReject(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_luReject *luReject = &(src->msg.luReject);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_LU_REJECT;

	//reject cause
	assert(luReject->rejectCause.flag== 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REJCAUSE, (ie_u *)&( luReject->rejectCause), dst+offset, 0);

	return offset;
}

//abort
int aifg_msg_sd_abort(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_abort *abort = &(src->msg.abort);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_ABORT;

	//reject cause
	assert(abort->rejectCause.flag== 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REJCAUSE, (ie_u *)&( abort->rejectCause), dst+offset, 0);

	return offset;
}

//MM status
int aifg_msg_sd_mmStatus(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_mmStatus *mmStatus = &(src->msg.mmStatus);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_MM_STATUS;

	//reject cause
	assert(mmStatus->rejectCause.flag== 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REJCAUSE, (ie_u *)&( mmStatus->rejectCause), dst+offset, 0);

	return offset;
}

//authentication request
int aifg_msg_sd_authReq(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_authRequest *authRequest = &(src->msg.authRequest);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_AUTH_REQUEST;

	//ciphering key sequence number
	assert(authRequest->cipherKey.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CIPHERKEY, (ie_u *)&( authRequest->cipherKey), dst+offset, 0);
	offset++;

	//authentication parameter RAND
	assert(authRequest->authRAND.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_AUTHRAND, (ie_u *)&( authRequest->authRAND), dst+offset, 0);

	return offset;
}

//authentication response
int aifg_msg_sd_authResp(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_authResp *authResp = &(src->msg.authResp);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_AUTH_RESPONSE;

	//authentication parameter SRES
	assert(authResp->authSRES.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_AUTHSRES, (ie_u *)&( authResp->authSRES), dst+offset, 0);

	return offset;
}

//identity request
int aifg_msg_sd_idReq(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_idRequest *idRequest = &(src->msg.idRequest);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_ID_REQUEST;

	//identity type
	assert(idRequest->idType.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_IDTYPE, (ie_u *)&( idRequest->idType), dst+offset, 0);
	offset++;

	return offset;
}

//identity response
int aifg_msg_sd_idResp(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_idResp *idResp = &(src->msg.idResp);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_ID_RESPONSE;

	//mobile identity
	assert(idResp->mobileId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID, (ie_u *)&( idResp->mobileId), dst+offset, 0);

	return offset;
}

//TMSI reallocation command
int aifg_msg_sd_tmsiReallocCmd(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_tmsiCmd *tmsiCmd = &(src->msg.tmsiCmd);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_TMSI_REALLOC_CMD;

	//location area identification
	assert(tmsiCmd->lai.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LAI, (ie_u *)&(tmsiCmd->lai), dst+offset, 0);

	//mobile identity
	assert(tmsiCmd->mobileId.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOBILEID, (ie_u *)&(tmsiCmd->mobileId), dst+offset, 0);

	return offset;
}

//MM infomation
int aifg_msg_sd_mmInfo(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_mmInfo *mmInfo = &(src->msg.mmInfo);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_MM_INFO;

	//full name of network
	if(mmInfo->fullName.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FULL_NWNAME, 
			(ie_u *)&( mmInfo->fullName), dst+offset, 2);
	}

	//short name of network
	if(mmInfo->shortName.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_SHORT_NWNAME, 
			(ie_u *)&( mmInfo->shortName), dst+offset, 2);
	}

	//time zone
	if(mmInfo->timeZone.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_TIMEZONE, 
			(ie_u *)&( mmInfo->timeZone), dst+offset, 2);
	}

	//timezone and time
	if(mmInfo->tzTime.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_TZTIME, 
			(ie_u *)&( mmInfo->tzTime), dst+offset, 2);
	}

	//LSA identifier
	if(mmInfo->lsaId.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LSAID, 
			(ie_u *)&( mmInfo->lsaId), dst+offset, 2);
	}

	return offset;
}

//alerting
int aifg_msg_sd_alert(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_alert *alert = &(src->msg.alert);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_ALERTING;

	//facility
	if(alert->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, (ie_u *)&( alert->facility), dst+offset, 2);
	}

	//progress indicator
	if(alert->progInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PROGIND, (ie_u *)&( alert->progInd), dst+offset, 2);
	}

	//user-user
	if(alert->uu.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER, (ie_u *)&( alert->uu), dst+offset, 2);
	}

	return offset;
}

//call confirmed
int aifg_msg_sd_callConfirm(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_callConfirm *callConfirm = &(src->msg.callConfirm);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CALL_CONFIRMED;

	//repeat indicator
	if(callConfirm->rpInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REPEATIND, (ie_u *)&( callConfirm->rpInd), dst+offset, 2);
	}

	//bearer capability 1
	if(callConfirm->bc1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, (ie_u *)&( callConfirm->bc1), dst+offset, 2);
	}

	//bearer capability 2
	if(callConfirm->bc2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, (ie_u *)&( callConfirm->bc2), dst+offset, 2);
	}

	//cause
	if(callConfirm->cause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, (ie_u *)&( callConfirm->cause), dst+offset, 2);
	}

	//call control capability
	if(callConfirm->ccCap.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CCCAP, (ie_u *)&( callConfirm->ccCap), dst+offset, 2);
	}

	return offset;
}

//call proceeding
int aifg_msg_sd_callProceed(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_callProceed *callProceed = &(src->msg.callProceed);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CALL_PROCEEDING;

	//repeat indicator
	if(callProceed->rpInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REPEATIND, 
			(ie_u *)&( callProceed->rpInd), dst+offset, 2);
	}

	//bearer capability 1
	if(callProceed->bc1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
			(ie_u *)&( callProceed->bc1), dst+offset, 2);
	}

	//bearer capability 2
	if(callProceed->bc2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
			(ie_u *)&( callProceed->bc2), dst+offset, 2);
	}

	//facility
	if(callProceed->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
			(ie_u *)&( callProceed->facility), dst+offset, 2);
	}

	//progress indicator
	if(callProceed->progInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PROGIND, 
			(ie_u *)&( callProceed->progInd), dst+offset, 2);
	}

	//priority level
	if(callProceed->priority.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PRIORITYLEVEL, 
			(ie_u *)&( callProceed->priority), dst+offset, 2);
	}

	return offset;
}

//connect
int aifg_msg_sd_connect(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_connect *connect = &(src->msg.connect);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CONNECT;

	//facility
	if(connect->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
			(ie_u *)&( connect->facility), dst+offset, 2);
	}

	//progress indicator
	if(connect->progInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PROGIND, 
			(ie_u *)&( connect->progInd), dst+offset, 2);
	}

	//connected number
	if(connect->connNum.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CONNNUM, 
			(ie_u *)&( connect->connNum), dst+offset, 2);
	}

	//connected subaddress
	if(connect->connSubAddr.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CONNSUBADDR, 
			(ie_u *)&( connect->connSubAddr), dst+offset, 2);
	}

	//user-user
	if(connect->uu.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER, 
			(ie_u *)&( connect->uu), dst+offset, 2);
	}

	return offset;
}

//emergency setup
int aifg_msg_sd_eSetup(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_eSetup *eSetup = &(src->msg.eSetup);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_EMERGENCY_SETUP;

	//bearer capability
	if(eSetup->bc.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
			(ie_u *)&( eSetup->bc), dst+offset, 2);
	}

	return offset;
}

//progress
int aifg_msg_sd_progress(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_progress *progress = &(src->msg.progress);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_PROGRESS;

	//progress indicator
	assert(progress->progInd.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PROGIND, 
		(ie_u *)&( progress->progInd), dst+offset, 0);

	//user-user
	if(progress->uu.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER, 
			(ie_u *)&( progress->uu), dst+offset, 2);
	}

	return offset;
}

//setup
int aifg_msg_sd_setup(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_setup *setup = &(src->msg.setup);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_SETUP;

	//BC repeat indicator
	if(setup->bc_rpInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REPEATIND,
			(ie_u *)&( setup->bc_rpInd), dst+offset, 2);
	}

	//bearer capability 1
	if(setup->bc1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
			(ie_u *)&( setup->bc1), dst+offset, 2);
	}

	//bearer capability 2
	if(setup->bc2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
			(ie_u *)&( setup->bc2), dst+offset, 2);
	}

	//facility
	if(setup->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
			(ie_u *)&( setup->facility), dst+offset, 2);
	}

	//progress indicator
	if(setup->progInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PROGIND, 
			(ie_u *)&( setup->progInd), dst+offset, 2);
	}	

	//signal
	if(setup->signal.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_SIGNAL,
			(ie_u *)&( setup->signal), dst+offset, 2);
	}

	//calling party BCD number
	if(setup->callingNum.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CALLERBCD,
			(ie_u *)&( setup->callingNum), dst+offset, 2);
	}

	//calling party subaddr
	if(setup->callingSubAddr.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CALLERSUBADDR, 
			(ie_u *)&( setup->callingSubAddr), dst+offset, 2);
	}

	//called party BCD num
	if(setup->calledNum.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CALLEDBCD, 
			(ie_u *)&( setup->calledNum), dst+offset, 2);
	}

	//called party subaddr
	if(setup->calledSubAddr.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CALLEDSUBADDR, 
			(ie_u *)&( setup->calledSubAddr), dst+offset, 2);
	}

	//redirecting party BCD num
	if(setup->redirNum.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REDIRBCD, 
			(ie_u *)&( setup->redirNum), dst+offset, 2);
	}

	//redirecting party subaddr
	if(setup->redirSubAddr.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REDIRSUBADDR,
			(ie_u *)&( setup->redirSubAddr), dst+offset, 2);
	}

	//LLC repeat indicator
	if(setup->llc_rpInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REPEATIND, 
			(ie_u *)&( setup->llc_rpInd), dst+offset, 2);
	}

	//low layer compatability 1
	if(setup->loComp1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LOWCOM, 
			(ie_u *)&( setup->loComp1), dst+offset, 2);
	}

	//low layer compatability 2
	if(setup->loComp2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LOWCOM, 
			(ie_u *)&( setup->loComp2), dst+offset, 2);
	}

	//HLC repeat indicator
	if(setup->hlc_rpInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REPEATIND, 
			(ie_u *)&( setup->hlc_rpInd), dst+offset, 2);
	}

	//high layer compatability 1
	if(setup->hiComp1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_HIGHCOM, 
			(ie_u *)&( setup->hiComp1), dst+offset, 2);
	}

	//high layer compatability 2
	if(setup->hiComp2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_HIGHCOM, 
			(ie_u *)&( setup->hiComp2), dst+offset, 2);
	}

	//user-user
	if(setup->uu.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER, 
			(ie_u *)&( setup->uu), dst+offset, 2);
	}

	//priority level
	if(setup->priority.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PRIORITYLEVEL, 
			(ie_u *)&( setup->priority), dst+offset, 2);
	}

	//alert pattern
	if(setup->alertPattern.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_ALERTPATTERN, 
			(ie_u *)&( setup->alertPattern), dst+offset, 2);
	}

	return offset;
}

//modify
int aifg_msg_sd_modify(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_modify *modify = &(src->msg.modify);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_MODIFY;

	//bearer capability
	assert(modify->bc.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
		(ie_u *)&( modify->bc), dst+offset, 0);

	//low layer comp
	if(modify->loComp.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LOWCOM, 
			(ie_u *)&( modify->loComp), dst+offset, 2);
	}

	//high layer comp
	if(modify->hiComp.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_HIGHCOM,
			(ie_u *)&( modify->hiComp), dst+offset, 2);
	}

	//reverse call setup direction
	if(modify->revCallDir.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REVCALLDIR, 
			(ie_u *)&( modify->revCallDir), dst+offset, 2);
	}

	return offset;
}

//modify complete
int aifg_msg_sd_modifyCmp(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_modifyCmp *modifyCmp = &(src->msg.modifyCmp);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_MODIFY_CMP;

	//bearer capability
	assert(modifyCmp->bc.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
		(ie_u *)&( modifyCmp->bc), dst+offset, 0);

	//low layer comp
	if(modifyCmp->loComp.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LOWCOM, 
			(ie_u *)&( modifyCmp->loComp), dst+offset, 2);
	}

	//high layer comp
	if(modifyCmp->hiComp.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_HIGHCOM, 
			(ie_u *)&( modifyCmp->hiComp), dst+offset, 2);
	}

	//reverse call setup direction
	if(modifyCmp->revCallDir.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_REVCALLDIR, 
			(ie_u *)&( modifyCmp->revCallDir), dst+offset, 2);
	}

	return offset;
}

//modify reject
int aifg_msg_sd_modifyRej(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_modifyRej *modifyRej = &(src->msg.modifyRej);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_MODIFY_REJECT;

	//bearer capability
	assert(modifyRej->bc.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_BEARERCAP, 
		(ie_u *)&( modifyRej->bc), dst+offset, 0);

	//cause
	assert(modifyRej->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
		(ie_u *)&( modifyRej->cause), dst+offset, 0);

	//low layer comp
	if(modifyRej->loComp.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_LOWCOM, 
			(ie_u *)&( modifyRej->loComp), dst+offset, 2);
	}

	//high layer comp
	if(modifyRej->hiComp.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_HIGHCOM, 
			(ie_u *)&( modifyRej->hiComp), dst+offset, 2);
	}

	return offset;
}

//user infomation
int aifg_msg_sd_userInfo(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_userInfo *userInfo = &(src->msg.userInfo);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_USER_INFO;

	//user-user
	assert(userInfo->uu.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER, 
		(ie_u *)&( userInfo->uu), dst+offset, 0);

	//more data
	if(userInfo->moreData.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_MOREDATA, 
			(ie_u *)&( userInfo->moreData), dst+offset, 2);
	}

	return offset;
}

//hold reject
int aifg_msg_sd_holdRej(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_holdRej *holdRej = &(src->msg.holdRej);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HOLD_REJECT;

	//cause
	assert(holdRej->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
		(ie_u *)&( holdRej->cause), dst+offset, 0);

	return offset;
}

//retrieve reject
int aifg_msg_sd_retrieveRej(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_retrieveRej *retrieveRej = &(src->msg.retrieveRej);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RETRIEVE_REJECT;

	//cause
	assert(retrieveRej->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
		(ie_u *)&( retrieveRej->cause), dst+offset, 0);

	return offset;
}

//disconnect
int aifg_msg_sd_disconnect(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;
	aifg_msg_dt_disconnect *disconnect = &(src->msg.disconnect);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_DISCONNECT;

	//cause
	assert(disconnect->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
		(ie_u *)&( disconnect->cause), dst+offset, 0);

	//facility
	if(disconnect->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
			(ie_u *)&( disconnect->facility), dst+offset, 2);
	}

	//progress indicator
	if(disconnect->progInd.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_PROGIND, 
			(ie_u *)&( disconnect->progInd), dst+offset, 2);
	}

	//user-user
	if(disconnect->uu.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER,
			(ie_u *)&( disconnect->uu), dst+offset, 2);
	}

	//SS version
	if(disconnect->ssVer.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_SSVER, 
			(ie_u *)&( disconnect->ssVer), dst+offset, 2);
	}

	return offset;
}

//release
int aifg_msg_sd_release(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_release *release = &(src->msg.release);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RELEASE;

	//cause 1
	if(release->cause1.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
			(ie_u *)&( release->cause1), dst+offset, 2);
	}

	//cause 2
	if(release->cause2.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE,
			(ie_u *)&( release->cause2), dst+offset, 2);
	}

	//facility
	if(release->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
			(ie_u *)&( release->facility), dst+offset, 2);
	}

	//user-user
	if(release->uu.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER, 
			(ie_u *)&( release->uu), dst+offset, 2);
	}

	return offset;
}

//release complete
int aifg_msg_sd_releaseCmp(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_releaseCmp *releaseCmp = &(src->msg.releaseCmp);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RELEASE_CMP;

	//cause 
	if(releaseCmp->cause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
			(ie_u *)&( releaseCmp->cause), dst+offset, 2);
	}

	//facility
	if(releaseCmp->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
			(ie_u *)&( releaseCmp->facility), dst+offset, 2);
	}

	//user-user
	if(releaseCmp->uu.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_USERUSER,
			(ie_u *)&( releaseCmp->uu), dst+offset, 2);
	}

	return offset;
}

//congestion control
int aifg_msg_sd_congestCtrl(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_congestCtrl *congestCtrl = &(src->msg.congestCtrl);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CONGESTION_CTRL;

	//congestion level
	assert(congestCtrl->congestLevel.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CONGESTLEVEL, 
		(ie_u *)&( congestCtrl->congestLevel), dst+offset, 0);
	offset++;

	//cause
	if(congestCtrl->cause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
			(ie_u *)&( congestCtrl->cause), dst+offset, 2);
	}

	return offset;
}

//notify
int aifg_msg_sd_notify(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	aifg_msg_dt_notify *notify = &(src->msg.notify);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_NOTIFY;

	//notification indicator
	assert(notify->notificationInd.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_NOTIIND, 
		(ie_u *)&( notify->notificationInd), dst+offset, 0);

	return offset;
}

//status
int aifg_msg_sd_status(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_status *status = &(src->msg.status);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_STATUS;

	//cause
	assert(status->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
		(ie_u *)&( status->cause), dst+offset, 0);

	//call state
	assert(status->callStat.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CALLSTAT,
		(ie_u *)&( status->callStat), dst+offset, 0);

	//auxiliary states
	if(status->auxStat.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_AUXSTAT, 
			(ie_u *)&( status->auxStat), dst+offset, 2);
	}

	return offset;
}

//start DTMF
int aifg_msg_sd_startDTMF(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_startDTMF *startDTMF = &(src->msg.startDTMF);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_START_DTMF;

	//keypad facility
	assert(startDTMF->keypad.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_KEYPAD, 
		(ie_u *)&( startDTMF->keypad), dst+offset, 2);

	return offset;
}

//start DTMF acknowledge
int aifg_msg_sd_startDTMFAck(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_startDTMF_ack *startDTMF_ack = &(src->msg.startDTMF_ack);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_START_DTMF_ACK;

	//keypad facility
	assert(startDTMF_ack->keypad.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_KEYPAD, 
		(ie_u *)&( startDTMF_ack->keypad), dst+offset, 2);

	return offset;
}

//start DTMF reject
int aifg_msg_sd_startDTMFRej(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_startDTMF_rej *startDTMF_rej = &(src->msg.startDTMF_rej);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_START_DTMF_REJECT;

	//cause
	assert(startDTMF_rej->cause.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, (ie_u *)&( startDTMF_rej->cause), dst+offset, 0);

	return offset;
}

//facility
int aifg_msg_sd_facility(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_facility *facility = &(src->msg.facility);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_FACILITY;

	//facility
	assert(facility->facility.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, (ie_u *)&( facility->facility), dst+offset, 0);

	return offset;
}

//msg_encode with only 3 ies
//authentication reject
int aifg_msg_sd_authRej(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_AUTH_REJECT;

	return offset;
}

//CM service accept
int aifg_msg_sd_cmAccept(aifg_msg_t* src, BYTE *dst)
{  
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CM_ACCEPT;

	return offset;
}

//CM service abort
int aifg_msg_sd_cmAbort(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CM_ABORT;

	return offset;
}

//TMSI reallocation complete
int aifg_msg_sd_tmsiReallocCmp(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_TMSI_REALLOC_CMP;

	return offset;
}

//MM null
int aifg_msg_sd_mmNull(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_MM_NULL;

	return offset;
}

//connect acknowledge
int aifg_msg_sd_connectAck(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_CONNECT_ACK;

	return offset;
}

//hold
int aifg_msg_sd_hold(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HOLD;

	return offset;
}

//hold acknowledge
int aifg_msg_sd_holdAck(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_HOLD_ACK;

	return offset;
}

//retrieve
int aifg_msg_sd_retrieve(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RETRIEVE;

	return offset;
}

//retrieve acknowledge
int aifg_msg_sd_retrieveAck(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RETRIEVE_ACK;

	return offset;
}

//status enquiry
int aifg_msg_sd_statusEnq(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_STATUS_ENQ;

	return offset;
}

//stop DTMF
int aifg_msg_sd_stopDTMF(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_STOP_DTMF;

	return offset;
}

//stop DTMF acknowledge
int aifg_msg_sd_stopDTMFAck(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_STOP_DTMF_ACK;

	return offset;
}

//facility SS
int aifg_msg_sd_facilitySS(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_facilitySS *facilitySS = &(src->msg.facilitySS);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_FACILITY_SS;

	//facility, mandatory but has iei
	assert(facilitySS->facility.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
		(ie_u *)&( facilitySS->facility), dst+offset, 0);

	return offset;
}


//register
int aifg_msg_sd_register(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_register *registerSS = &(src->msg.registerSS);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_REGISTER;

	//facility, mandatory but has iei
	assert(registerSS->facility.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
		(ie_u *)&( registerSS->facility), dst+offset, 2);

	//SS Version
	if(registerSS->ssVer.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_SSVER, 
			(ie_u *)&( registerSS->ssVer), dst+offset, 2);
	}

	return offset;
}

//release complete SS
int aifg_msg_sd_releaseCompSS(aifg_msg_t* src, BYTE *dst)
{   
	int offset = 0;

	aifg_msg_dt_releaseCompSS *releaseCompSS = &(src->msg.releaseCompSS);

	assert(src != NULL && dst != NULL);

	dst[offset++] = AIFG_MSG_T_RELEASE_CMP_SS;

	//Cause
	if(releaseCompSS->cause.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_CAUSE, 
			(ie_u *)&( releaseCompSS->cause), dst+offset, 2);
	}

	//facility
	if(releaseCompSS->facility.flag == 1){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_FACILITY, 
			(ie_u *)&( releaseCompSS->facility), dst+offset, 2);
	}

	return offset;
}

//SMS
//RP DATA
int aifg_msg_sd_rp_data(aifg_msg_t* src, BYTE *dst)
{
	int offset = 0;

	aifg_msg_dt_rpData *rpData = &(src->msg.rpData);

	assert(src != NULL && dst != NULL);

	//CP header
	dst[offset++] = AIFG_MSG_T_CP_DATA;
	offset++;	//skip length

	//RP header
	dst[offset++] = AIFG_MSG_T_RP_DATA_NW;
	dst[offset++] = src->msg.rpData.ref;

	//Originator address element
	assert(rpData->moAddr.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_RP_MO_ADDR, 
		(ie_u *)&( rpData->moAddr), dst+offset, 0);

	//Destination address element
	assert(rpData->mtAddr.flag == 1);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_RP_MT_ADDR, 
		(ie_u *)&( rpData->mtAddr), dst+offset, 0);

	//RP User data
	assert(rpData->data.len > 0);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_RP_UD, 
		(ie_u *)&( rpData->data), dst+offset, 1);

	dst[1] = offset - 2;

	return offset;
}

//RP ACK
int aifg_msg_sd_rp_ack(aifg_msg_t* src, BYTE *dst)
{
	int offset = 0;

	aifg_msg_dt_rpAck *rpAck = &(src->msg.rpAck);

	assert(src != NULL && dst != NULL);

	//CP header
	dst[offset++] = AIFG_MSG_T_CP_DATA;
	offset++;	//skip length

	//RP header
	dst[offset++] = AIFG_MSG_T_RP_ACK_NW;
	dst[offset++] = rpAck->ref;

	//RP User data
	if(rpAck->data.len > 0){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_RP_UD, 
			(ie_u *)&( rpAck->data), dst+offset, 2);
	}

	dst[1] = offset - 2;

	return offset;
}

//RP ERROR
int aifg_msg_sd_rp_error(aifg_msg_t* src, BYTE *dst)
{
	int offset = 0;

	aifg_msg_dt_rpError *rpErr = &(src->msg.rpError);

	assert(src != NULL && dst != NULL);

	//CP header
	dst[offset++] = AIFG_MSG_T_CP_DATA;
	offset++;	//skip length

	//RP header
	dst[offset++] = AIFG_MSG_T_RP_ERROR_NW;
	dst[offset++] = rpErr->ref;

	//RP Cause
	assert(1 == rpErr->cause.flag);
	offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_RP_CAUSE, 
		(ie_u *)&( rpErr->cause), dst+offset, 0);

	//RP User data
	if(rpErr->data.len > 0){
		offset += aifg_ie_encode(AIFG_MSG_DTAP, AIFG_IE_ID_DT_RP_UD, 
			(ie_u *)&( rpErr->data), dst+offset, 2);
	}

	dst[1] = offset - 2;

	return offset;
}

//End of message encode functions definition----------------------------------------

//Interface function of MPP submodule definition--------------------------------------
/*
Name: 	aifg_mpp_init
Purpose:init MPP submodule
Input:	None
Output:	None
*/
enum{AIFG_MSG_DECODE, AIFG_MSG_ENCODE};
void aifg_mpp_init()
{
	//Init message decode function ptr array
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_ASSIGN_REQ]			= aifg_msg_rv_assignReq;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_ASSIGN_CMP]			= aifg_msg_rv_assignComplete;	
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_ASSIGN_FAIL]			= aifg_msg_rv_assignFailure;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_BLOCK]					= aifg_msg_rv_block;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_BLOCK_ACK]				= aifg_msg_rv_blockAck;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_UNBLOCK]				= aifg_msg_rv_unBlock;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_UNBLOCK_ACK]			= aifg_msg_rv_unBlockAck;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_REQUEST]			= aifg_msg_rv_HORequest;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_REQUIRED]			= aifg_msg_rv_HORequired;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_REQ_ACK]			= aifg_msg_rv_HORequestAck;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_CMD]				= aifg_msg_rv_HOCmd;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_CMP]				= aifg_msg_rv_HOComplete;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_SUC]				= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_CAN_ENQ]			= aifg_msg_rv_HOCandEnq;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_CAN_RESP]			= aifg_msg_rv_HOCandResp;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_FAIL]				= aifg_msg_rv_HOFailure;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RESRC_REQ]				= aifg_msg_rv_resrcReq;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RESRC_IND]				= aifg_msg_rv_resrcInd;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_PAGING]				= aifg_msg_rv_paging;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CLR_REQ]				= aifg_msg_rv_clearReq;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CLR_CMD]				= aifg_msg_rv_clearCmd;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CLR_CMP]				= aifg_msg_rv_clearCmp;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RESET]					= aifg_msg_rv_reset;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RESET_ACK]				= aifg_msg_rv_resetAck;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_PERFORMED]			= aifg_msg_rv_HOPerformed;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_OVERLOAD]				= aifg_msg_rv_overload;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_MSC_INVK_TRACE]		= aifg_msg_rv_mscTrace;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_BSC_INVK_TRACE]		= aifg_msg_rv_bscTrace;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CM_UPDATE]				= aifg_msg_rv_cmUpdate;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CIPHER_MODE_CMD]		= aifg_msg_rv_cipherModeCmd;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CIPHER_MODE_CMP]		= aifg_msg_rv_cipherModeComp;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_L3_INFO]				= aifg_msg_rv_completeL3Info;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_QUEUE_IND]				= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_SAPI_REJ]				= aifg_msg_rv_sapi_n_rej;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_REQ_REJ]			= aifg_msg_rv_HORequiredRej;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RESET_CC]				= aifg_msg_rv_resetCircuit;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RESET_CC_ACK]			= aifg_msg_rv_resetCircuitAck;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HO_DETECT]				= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CC_GROUP_BLK]			= aifg_msg_rv_ccGroupBlock;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CC_GROUP_BLK_ACK]		= aifg_msg_rv_ccGroupBlockAck;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CC_GROUP_UNBLK]		= aifg_msg_rv_ccGroupUnblock;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CC_GROUP_UNBLK_ACK]	= aifg_msg_rv_ccGroupUnblockAck;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CONFUSION]				= aifg_msg_rv_confusion;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CM_REQUEST]			= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_UNEQUIP_CC]			= aifg_msg_rv_unequippedCircuit;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CIPHER_MODE_REJ]		= aifg_msg_rv_clearReq;	//the same as clear request
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_LOAD_IND]				= aifg_msg_rv_loadInd;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_SUSPEND]				= aifg_msg_rv_suspend;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RESUME]				= aifg_msg_rv_suspend;	//the same as suspend
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CHANGE_CC]				= NULL;	//not supported
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CHANGE_CC_ACK]			= NULL;	//not supported
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_LSA_INFO]				= NULL; //not supported
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_LOC_INFO_CMD]			= aifg_msg_rv_locInfoCmd;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_LOC_INFO_RPT]			= aifg_msg_rv_locInfoReport;
	////////dtap/////////////
	//mm
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_AUTH_REJECT]      		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_AUTH_REQUEST]     		= aifg_msg_rv_authReq;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_AUTH_RESPONSE]			= aifg_msg_rv_authResp;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CM_REEST_REQUEST] 		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CM_ACCEPT]        		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CM_REJECT]        		= aifg_msg_rv_cmRej;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CM_ABORT]        		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_ABORT]           		= aifg_msg_rv_cmRej;//the same as cm service reject
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CM_REQUEST]       		= aifg_msg_rv_cmReq;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_ID_REQUEST]       		= aifg_msg_rv_idReq;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_ID_RESPONSE]      		= aifg_msg_rv_idResp;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_IMSI_DETACH_IND]		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_LU_ACCEPT]         	= aifg_msg_rv_luAccept;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_LU_REQUEST]        	= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_LU_REJECT]         	= aifg_msg_rv_cmRej;//the same as cm service reject
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_MM_INFO]           	= aifg_msg_rv_mmInfo;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_MM_STATUS]         	= aifg_msg_rv_cmRej;//The same as CM service reject
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_TMSI_REALLOC_CMD]  	= aifg_msg_rv_tmsiRealloc;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_TMSI_REALLOC_CMP]		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_MM_NULL]           	= NULL;
	//cc
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_ALERTING]          	= aifg_msg_rv_alert;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CALL_CONFIRMED]    	= aifg_msg_rv_callConfirm;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CALL_PROCEEDING]   	= aifg_msg_rv_callProceed;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CONGESTION_CTRL]  		= aifg_msg_rv_congestCtrl;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CONNECT]          		= aifg_msg_rv_connect;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_CONNECT_ACK]      		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_DISCONNECT]       		= aifg_msg_rv_disconnect;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_EMERGENCY_SETUP]  		= aifg_msg_rv_eSetup;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_FACILITY]         		= aifg_msg_rv_facility;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HOLD]             		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HOLD_ACK]          	= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_HOLD_REJECT]       	= aifg_msg_rv_holdRej;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_MODIFY]          		= aifg_msg_rv_modify;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_MODIFY_CMP]        	= aifg_msg_rv_modify;//the same as modify
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_MODIFY_REJECT]    		= aifg_msg_rv_modifyRej;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_NOTIFY]           		= aifg_msg_rv_notify;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_PROGRESS]          	= aifg_msg_rv_progress;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RELEASE]          		= aifg_msg_rv_release;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RELEASE_CMP]      		= aifg_msg_rv_releaseComp;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RETRIEVE]         		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RETRIEVE_ACK]     		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RETRIEVE_REJECT]  		= aifg_msg_rv_holdRej;//the same as hold reject
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_SETUP]            		= aifg_msg_rv_setup;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_START_DTMF]       		= aifg_msg_rv_startDTMF;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_START_DTMF_ACK]   		= aifg_msg_rv_startDTMF;//the same as stratDTMF
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_START_DTMF_REJECT]		= aifg_msg_rv_holdRej;//the same as holdReject
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_STATUS]            	= aifg_msg_rv_status;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_STATUS_ENQ]       		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_STOP_DTMF]        		= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_STOP_DTMF_ACK]     	= NULL;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_USER_INFO]         	= aifg_msg_rv_userInfo;
	//ss
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_FACILITY_SS]         	= aifg_msg_rv_facilitySS;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RELEASE_CMP_SS]       	= aifg_msg_rv_releaseCompSS;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_REGISTER]				= aifg_msg_rv_register;
	//sms
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RP_DATA]			 	= aifg_msg_rv_rp_data;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RP_SMMA]				= aifg_msg_rv_rp_smma;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RP_ACK]				= aifg_msg_rv_rp_ack;
	aifg_msg_rv_func_ptr[AIFG_MSG_ID_RP_ERROR]				= aifg_msg_rv_rp_error;

	//Init message encode function ptr array
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_ASSIGN_REQ]			= aifg_msg_sd_assignReq;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_ASSIGN_CMP]			= aifg_msg_sd_assignComplete;	
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_ASSIGN_FAIL]			= aifg_msg_sd_assignFailure;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_BLOCK]					= aifg_msg_sd_block;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_BLOCK_ACK]				= aifg_msg_sd_blockAck;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_UNBLOCK]				= aifg_msg_sd_unblock;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_UNBLOCK_ACK]			= aifg_msg_sd_unblockAck;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_REQUEST]			= aifg_msg_sd_HORequest;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_REQUIRED]			= aifg_msg_sd_HORequired;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_REQ_ACK]			= aifg_msg_sd_HORequestAck;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_CMD]				= aifg_msg_sd_HOCmd;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_CMP]				= aifg_msg_sd_HOComplete;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_SUC]				= aifg_msg_sd_HOSucceed;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_CAN_ENQ]			= aifg_msg_sd_HOCandEnq;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_CAN_RESP]			= aifg_msg_sd_HOCandResp;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_FAIL]				= aifg_msg_sd_HOFailure;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RESRC_REQ]				= aifg_msg_sd_resrcReq;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RESRC_IND]				= aifg_msg_sd_resrcInd;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_PAGING]				= aifg_msg_sd_paging;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CLR_REQ]				= aifg_msg_sd_clearReq;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CLR_CMD]				= aifg_msg_sd_clearCmd;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CLR_CMP]				= aifg_msg_sd_clearComplete;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RESET]					= aifg_msg_sd_reset;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RESET_ACK]				= aifg_msg_sd_resetAck;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_PERFORMED]			= aifg_msg_sd_HOPerformed;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_OVERLOAD]				= aifg_msg_sd_overload;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_MSC_INVK_TRACE]		= aifg_msg_sd_mscTrace;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_BSC_INVK_TRACE]		= aifg_msg_sd_bscTrace;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CM_UPDATE]				= aifg_msg_sd_cmUpdate;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CIPHER_MODE_CMD]		= aifg_msg_sd_cipherModeCmd;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CIPHER_MODE_CMP]		= aifg_msg_sd_cipherModeComplete;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_L3_INFO]				= aifg_msg_sd_completeL3Info;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_QUEUE_IND]				= aifg_msg_sd_queueInd;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_SAPI_REJ]				= aifg_msg_sd_sapi_n_rej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_REQ_REJ]			= aifg_msg_sd_HORequiredRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RESET_CC]				= aifg_msg_sd_resetCircuit;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HO_DETECT]				= aifg_msg_sd_HODetect;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CC_GROUP_BLK]			= aifg_msg_sd_ccGrpBlk;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CC_GROUP_BLK_ACK]		= aifg_msg_sd_ccGroupBlockAck;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CC_GROUP_UNBLK]		= aifg_msg_sd_ccGroupUnblock;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CC_GROUP_UNBLK_ACK]	= aifg_msg_sd_ccGroupUnblockAck;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CONFUSION]				= aifg_msg_sd_confusion;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CLASSMARK_REQ]			= aifg_msg_sd_classmarkReq;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_UNEQUIP_CC]			= aifg_msg_sd_unequippedCircuit;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CIPHER_MODE_REJ]		= aifg_msg_sd_cipherModeRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_LOAD_IND]				= aifg_msg_sd_loadInd;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_SUSPEND]				= aifg_msg_sd_suspend;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RESUME]				= aifg_msg_sd_resume;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CHANGE_CC]				= aifg_msg_sd_changeCircuit;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CHANGE_CC_ACK]			= aifg_msg_sd_changeCircuitAck;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_LSA_INFO]				= NULL;//not supported
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_LOC_INFO_CMD]			= aifg_msg_sd_locCmd;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_LOC_INFO_RPT]			= aifg_msg_sd_locReport;
	////////dtap/////////////                                                  
	//mm                                                                   
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_AUTH_REJECT]      		= aifg_msg_sd_authRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_AUTH_REQUEST]     		= aifg_msg_sd_authReq;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CM_REEST_REQUEST] 		= NULL;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CM_ACCEPT]        		= aifg_msg_sd_cmAccept;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CM_REJECT]        		= aifg_msg_sd_cmRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CM_ABORT]        		= aifg_msg_sd_cmAbort;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_ABORT]           		= aifg_msg_sd_abort;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CM_REQUEST]       		= NULL;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_ID_REQUEST]       		= aifg_msg_sd_idReq;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_ID_RESPONSE]      		= aifg_msg_sd_idResp;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_IMSI_DETACH_IND]		= NULL;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_LU_ACCEPT]         	= aifg_msg_sd_luAccept;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_LU_REQUEST]        	= NULL;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_LU_REJECT]         	= aifg_msg_sd_luReject;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_TMSI_REALLOC_CMD]  	= aifg_msg_sd_tmsiReallocCmd;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_TMSI_REALLOC_CMP]		= aifg_msg_sd_tmsiReallocCmp;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_MM_NULL]           	= aifg_msg_sd_mmNull;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_MM_STATUS]         	= aifg_msg_sd_mmStatus;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_MM_INFO]           	= aifg_msg_sd_mmInfo;
	//cc                                                                   
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_ALERTING]          	= aifg_msg_sd_alert;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CALL_CONFIRMED]    	= aifg_msg_sd_callConfirm;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CALL_PROCEEDING]   	= aifg_msg_sd_callProceed;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CONGESTION_CTRL]  		= aifg_msg_sd_congestCtrl;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CONNECT]          		= aifg_msg_sd_connect;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_CONNECT_ACK]      		= aifg_msg_sd_connectAck;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_DISCONNECT]       		= aifg_msg_sd_disconnect;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_EMERGENCY_SETUP]  		= aifg_msg_sd_eSetup;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_FACILITY]         		= aifg_msg_sd_facility;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HOLD]             		= aifg_msg_sd_hold;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HOLD_ACK]          	= aifg_msg_sd_holdAck;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_HOLD_REJECT]       	= aifg_msg_sd_holdRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_MODIFY]          		= aifg_msg_sd_modify;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_MODIFY_CMP]        	= aifg_msg_sd_modifyCmp;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_MODIFY_REJECT]    		= aifg_msg_sd_modifyRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_NOTIFY]           		= aifg_msg_sd_notify;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_PROGRESS]          	= aifg_msg_sd_progress;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RELEASE]          		= aifg_msg_sd_release;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RELEASE_CMP]      		= aifg_msg_sd_releaseCmp;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RETRIEVE]         		= aifg_msg_sd_retrieve;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RETRIEVE_ACK]     		= aifg_msg_sd_retrieveAck;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RETRIEVE_REJECT]  		= aifg_msg_sd_retrieveRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_SETUP]            		= aifg_msg_sd_setup;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_START_DTMF]       		= aifg_msg_sd_startDTMF;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_START_DTMF_ACK]   		= aifg_msg_sd_startDTMFAck;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_START_DTMF_REJECT]		= aifg_msg_sd_startDTMFRej;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_STATUS]            	= aifg_msg_sd_status;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_STATUS_ENQ]       		= aifg_msg_sd_statusEnq;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_STOP_DTMF]        		= aifg_msg_sd_stopDTMF;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_STOP_DTMF_ACK]     	= aifg_msg_sd_stopDTMFAck;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_USER_INFO]         	= aifg_msg_sd_userInfo;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_FACILITY_SS]        	= aifg_msg_sd_facilitySS;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_REGISTER]			  	= aifg_msg_sd_register;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RELEASE_CMP_SS]        = aifg_msg_sd_releaseCompSS;	
	//SMS
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RP_DATA]				= aifg_msg_sd_rp_data;
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RP_ERROR]			  	= aifg_msg_sd_rp_error;    
	aifg_msg_sd_func_ptr[AIFG_MSG_ID_RP_ACK]				= aifg_msg_sd_rp_ack;	

	return;
}

int aifg_mpp_proc()
{
	int tmp_sapid, tmp_cgid;
	BYTE *raw_msg_ptr = NULL;

	//Read message from sccp
	if(0 == SpSubmit(&sccp_msg, SCCP_SAP_AIFG))
		return AIFG_PROC_FINISH;

	switch(sccp_msg.uUiPri){
		case N_CONNECT_IND:	//CR
			tmp_cgid = aifg_get_cg(sccp_msg.tPriUnion.tPriNConnInd.OPC, sccp_msg.tPriUnion.tPriNConnInd.NetID);
			if (tmp_cgid == -1)
				goto FINISH;	//can not find corresponding CG, discard			

			if(0x04 != (sccp_msg.tPriUnion.tPriNConnInd.uOptFlag & 0x04)){
				aifg_debug_print(-1, AIFG_ERR_NO_UD_IN_CR, &sccp_msg, 0);	//no user data, treat as error
				goto FINISH;
			}

			if(0 != link_info[sccp_msg.wConnId].en_flag)
				goto FINISH;	//duplicated CR, discard

			rv_msg.tg_id = cg[tmp_cgid].tgid;
			raw_msg_ptr = sccp_msg.tPriUnion.tPriNConnInd.tUD.aUserData;
			if(AIFG_MSG_T_L3_INFO == raw_msg_ptr[2])
				tmp_sapid = AIFG_SAP_MSC;
			else if(AIFG_MSG_T_HO_REQUEST == raw_msg_ptr[2])
				tmp_sapid = AIFG_SAP_BSC;
			else{
				aifg_event = AIFG_ERR_UNKNOW_MSG;
				goto ERROR_PROC;
			}
			break;

		case N_CONNECT_CFM:	//CC
			if(0 == link_info[sccp_msg.wConnId].en_flag){
				aifg_debug_print(-1, AIFG_ERR_UNEXPECTED_CC, &sccp_msg, 0);	
				goto FINISH;
			}

			if(0x04 == (sccp_msg.tPriUnion.tPriNConnCfm.uOptFlag & 0x04)
				&& sccp_msg.tPriUnion.tPriNConnCfm.tUD.uDataLen > 0){
				//has user data
				raw_msg_ptr = sccp_msg.tPriUnion.tPriNConnCfm.tUD.aUserData;
				tmp_sapid = link_info[sccp_msg.wConnId].sapid;
			}
			else
				goto FINISH;

			break;

		case N_DATA_IND:	//DT1
			if(0 == link_info[sccp_msg.wConnId].en_flag){
				aifg_debug_print(-1, AIFG_ERR_UNEXPECTED_DT1, &sccp_msg, 0);
				goto FINISH;
			}

			raw_msg_ptr = sccp_msg.tPriUnion.tPriNDataInd.tUD.aUserData;
			tmp_sapid = link_info[sccp_msg.wConnId].sapid;
			break;

		case N_UNITDATA_IND://UDT
			tmp_cgid = aifg_get_cg(sccp_msg.tPriUnion.tPriNUDataInd.tCGA.DPC, sccp_msg.tPriUnion.tPriNUDataInd.tCGA.NetID);
			rv_msg.tg_id = cg[tmp_cgid].tgid;
			if (tmp_cgid == -1){
				//printf error here
				goto FINISH;
			}
			raw_msg_ptr = sccp_msg.tPriUnion.tPriNUDataInd.tUD.aUserData;
			tmp_sapid = cg[tmp_cgid].sapid;
			break;

		case N_DISCONNECT_IND://RLSD or CREF
			if(0 == link_info[sccp_msg.wConnId].en_flag){
				aifg_debug_print(-1, AIFG_ERR_UNEXPECTED_CC, &sccp_msg, 0);
				goto FINISH;
			}
/*
			if(0x04 == (sccp_msg.tPriUnion.tPriNDisconnInd.uOptFlag & 0x04)
				&& sccp_msg.tPriUnion.tPriNDisconnInd.tUD.uDataLen > 0){
				//has user data
				raw_msg_ptr = sccp_msg.tPriUnion.tPriNDisconnInd.tUD.aUserData;
				tmp_sapid = link_info[sccp_msg.wConnId].sapid;
				link_info[sccp_msg.wConnId].cleared = 1;
			}
			else
*/				goto FINISH;
			break;

		default:
			assert(0);	//should never happen
			goto FINISH;
			break;
	}

	if (sap[tmp_sapid].enable == 0)
		goto FINISH;	

	//decode the message and find its process port
	if(AIFG_SAP_BSC == tmp_sapid && AIFG_MSG_DTAP == raw_msg_ptr[0]){
		//Transparently transfer of DTAP message at BSC side
		rv_msg.id = AIFG_MSG_ID_TRANSPARENT_DTAP;
		rv_msg.msg.dtap_msg.len = raw_msg_ptr[2];
		rv_msg.msg.dtap_msg.ptr = raw_msg_ptr + 3; //skip 3 bytes BSSAP header
		rv_msg.aif_port = link_info[sccp_msg.wConnId].cur_port;
	}
	else{
		if(AIFG_SUCCEED != aifg_msg_proc(raw_msg_ptr, &rv_msg))
			goto ERROR_PROC;

		if (rv_msg.id == AIFG_MSG_ID_IGNORED_MSG){
			goto FINISH;
		}		

		//get local port for received msg
		rv_msg.aif_port = -1;
		rv_msg.app_port = -1;
		switch(rv_msg.pd){
			case AIFG_PD_DTAP_MM:
				switch(rv_msg.id){
					case AIFG_MSG_ID_CM_REQUEST:
						if((rv_msg.aif_port = aifg_port_assign(tmp_sapid, -1, sccp_msg.wConnId)) < 0)
							goto ERROR_PROC;
						if(link_info[sccp_msg.wConnId].cur_port == -1 
							|| aifg_pcb[link_info[sccp_msg.wConnId].cur_port].upper_port == -1){
							int i, j, k;
							k = 0;
							for(i=0; i < 3; i++){
								for(j=0; j < AIFG_MAX_TI_PER_LINK; j++){
									if(link_info[sccp_msg.wConnId].ti[i][j].en_flag != 0
										&& link_info[sccp_msg.wConnId].ti[i][j].port != -1
										&& aifg_pcb[link_info[sccp_msg.wConnId].ti[i][j].port].upper_port != -1){
										rv_msg.app_port = aifg_pcb[link_info[sccp_msg.wConnId].ti[i][j].port].upper_port;
										k = 1;
										break;
									}
								}
								if (k == 1)
									break;
							}
						}
						else
							rv_msg.app_port = aifg_pcb[link_info[sccp_msg.wConnId].cur_port].upper_port;	//hand message to current open port
						
						link_info[sccp_msg.wConnId].cur_port = rv_msg.aif_port;
						break;
					default:
						rv_msg.aif_port = link_info[sccp_msg.wConnId].cur_port;
						break;
				}
				break;
			case AIFG_PD_DTAP_SMS:
				//send back cp ack
				sccp_msg.uUiPri = N_DATA_REQ;
				sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData[2] = 2;		//length
				if (sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData[3] > 0x80)//ti
					sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData[3] =
					sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData[3] & 0x7F;
				else
					sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData[3] =
					sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData[3] | 0x80;
				sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData[4] = 0x04;	//msg type
				sccp_msg.tPriUnion.tPriNDataReq.tUD.uDataLen = 5;
				PostSp(&sccp_msg);
				//no break here
			case AIFG_PD_DTAP_CC:	//These are transfered on connection oriented link
			case AIFG_PD_DTAP_SS:
				{
					//find the corresponding local port and open it as current port
					rv_msg.aif_port = aifg_ti2lport(rv_msg.ti, sccp_msg.wConnId, rv_msg.pd);
					if (rv_msg.aif_port == -1){
						//try to use current opened port
						if (link_info[sccp_msg.wConnId].cur_port != -1){
							rv_msg.aif_port = link_info[sccp_msg.wConnId].cur_port;
						}
						else{
							aifg_event = AIFG_ERR_INVALID_TI;
							goto ERROR_PROC;
						}
					}
				}
				break;
			case AIFG_PD_BSSMAP_DEDICATED:
				{
					switch(rv_msg.id){
						case  AIFG_MSG_ID_L3_INFO:
							{
								switch(rv_msg.msg.completeL3Info.l3msg.id){
									case AIFG_MSG_ID_CM_REQUEST:
										if(raw_msg_ptr[0] != 0x02)
										{
											aifg_ie tmp_ie;
											if(aifg_ie_decode(&rv_msg.msg.completeL3Info.l3msg.msg.cmRequest.type, &tmp_ie) < 0)
												goto ERROR_PROC;
																
											if(tmp_ie.param.dt_cmType.value == 1||tmp_ie.param.dt_cmType.value == 2)
											{
												if(aifg_check_timeslot_avail(rv_msg.tg_id)==0)
												{
													aifg_msg_redirect(&sccp_msg);
													goto FINISH;
												}
											}
										}
									case AIFG_MSG_ID_CM_REEST_REQUEST:
										{
											//how to deal with this msg??
										}
										//break;	//treat this as normal service request (as following) msg temporarily
									case AIFG_MSG_ID_IMSI_DETACH_IND:
									case AIFG_MSG_ID_LU_REQUEST:
										{
											//service request msg, assign a new port for the following transaction
											if((rv_msg.aif_port = aifg_port_assign(tmp_sapid, -1, sccp_msg.wConnId)) < 0)
												goto ERROR_PROC;
										}
										break;
									case AIFG_MSG_ID_PAGING_RESP:
										{
											//get the paging port
											aifg_ie tmp_ie;
											BYTE *imsi_ptr;
											BYTE imsi_len;
											aifg_ie_decode(&rv_msg.msg.completeL3Info.l3msg.msg.pagingResp.mobileId, &tmp_ie);
											imsi_ptr = tmp_ie.param.mobileId.id;
											imsi_len = tmp_ie.param.mobileId.id_len;
											if(-1 == (rv_msg.aif_port = aifg_get_paging_port(tmp_cgid, imsi_ptr, imsi_len))){
												//not found, redirect
												aifg_msg_redirect(&sccp_msg);
												goto FINISH;
											}
											//found
											aifg_pcb[rv_msg.aif_port].link_id = sccp_msg.wConnId;
											assert(aifg_pcb[rv_msg.aif_port].stat == AIFG_PORT_PAGING);
										}
										break;
									default:
										break;
								}

								//send back cc
								SP_UiPriPara tmp_msg;
								tmp_msg.uUiPri = N_CONNECT_RSP;
								tmp_msg.wConnId = sccp_msg.wConnId;
								tmp_msg.tPriUnion.tPriNConnRsp.uOptFlag = 0;
								PostSp(&tmp_msg);
								//enable this link
								aifg_add_link(sccp_msg.wConnId, tmp_sapid);
							}
							break;
						case AIFG_MSG_ID_HO_REQUEST:
							{
								//assign a new port for the transaction
								if((rv_msg.aif_port = aifg_port_assign(tmp_sapid, -1, sccp_msg.wConnId)) < 0)
									goto ERROR_PROC;

								//send back cc
								SP_UiPriPara tmp_msg;
								tmp_msg.uUiPri = N_CONNECT_RSP;
								tmp_msg.wConnId = sccp_msg.wConnId;
								tmp_msg.tPriUnion.tPriNConnRsp.uOptFlag = 0;
								PostSp(&tmp_msg);
								//enable this link
								aifg_add_link(sccp_msg.wConnId, tmp_sapid);
							}							
							break;
						default:
							rv_msg.aif_port = link_info[sccp_msg.wConnId].cur_port;
							break;
						}
				}
				break;
			case AIFG_PD_BSSMAP_GLOBAL:
				{
					BYTE redirectFlag = 1;

					switch(rv_msg.id){
						case AIFG_MSG_ID_RESET:
							{
								if ((rv_msg.aif_port = aifg_port_assign(tmp_sapid, tmp_cgid, -1)) < 0)
									goto ERROR_PROC;
								rv_msg.app_port = UPPER_PROC;
							}
							break;
						case AIFG_MSG_ID_RESET_CC:
							{
								SP_UiPriPara tmp_sccp_msg;
								memset(&tmp_sccp_msg, 0, sizeof(tmp_sccp_msg));

								rv_msg.aif_port = AIFG_PORT_NOT_NEED;
								rv_msg.app_port = UPPER_PROC;

								//send back reset cc ack
								sd_msg.id = AIFG_MSG_ID_RESET_CC_ACK;
								sd_msg.msg.resetCircuitAck.cic.flag = 1;
								sd_msg.msg.resetCircuitAck.cic.pcm = 
									(rv_msg.msg.resetCircuit.cic.ptr[0] << 3) 
									| ((rv_msg.msg.resetCircuit.cic.ptr[1] & 0xE0) >> 5);
								sd_msg.msg.resetCircuitAck.cic.timeslot =
									rv_msg.msg.resetCircuit.cic.ptr[1] & 0x1F;
								aifg_send_udt(tmp_cgid, &sd_msg, &tmp_sccp_msg);
							}
							break;
						case AIFG_MSG_ID_BLOCK:
							{
								SP_UiPriPara tmp_sccp_msg;
								memset(&tmp_sccp_msg, 0, sizeof(tmp_sccp_msg));

								rv_msg.aif_port = AIFG_PORT_NOT_NEED;
								rv_msg.app_port = UPPER_PROC;

								//send back block ack
								sd_msg.id = AIFG_MSG_ID_BLOCK_ACK;
								sd_msg.msg.blockAck.cic.flag = 1;
								sd_msg.msg.blockAck.cic.pcm = 
									(rv_msg.msg.block.cic.ptr[0] << 3) 
									| ((rv_msg.msg.block.cic.ptr[1] & 0xE0) >> 5);
								sd_msg.msg.blockAck.cic.timeslot = rv_msg.msg.block.cic.ptr[1] & 0x1F;
								aifg_send_udt(tmp_cgid, &sd_msg, &tmp_sccp_msg);

								rv_msg.aif_port = AIFG_PORT_NOT_NEED;
							}
							break;
						case AIFG_MSG_ID_UNBLOCK:
							{
								SP_UiPriPara tmp_sccp_msg;
								memset(&tmp_sccp_msg, 0, sizeof(tmp_sccp_msg));

								rv_msg.aif_port = AIFG_PORT_NOT_NEED;
								rv_msg.app_port = UPPER_PROC;

								//send back unblock ack
								sd_msg.id = AIFG_MSG_ID_UNBLOCK_ACK;
								sd_msg.msg.blockAck.cic.flag = 1;
								sd_msg.msg.blockAck.cic.pcm = 
									(rv_msg.msg.block.cic.ptr[0] << 3) 
									| ((rv_msg.msg.block.cic.ptr[1] & 0xE0) >> 5);
								sd_msg.msg.blockAck.cic.timeslot = rv_msg.msg.block.cic.ptr[1] & 0x1F;
								aifg_send_udt(tmp_cgid, &sd_msg, &tmp_sccp_msg);
							}
							break;
						case AIFG_MSG_ID_CC_GROUP_BLK:
							{
								aifg_ie tmp_ie;
								SP_UiPriPara tmp_sccp_msg;
								memset(&tmp_sccp_msg, 0, sizeof(tmp_sccp_msg));
								rv_msg.aif_port = AIFG_PORT_NOT_NEED;
								rv_msg.app_port = UPPER_PROC;

								//send back group block ack
								sd_msg.id = AIFG_MSG_ID_CC_GROUP_BLK_ACK;
								sd_msg.msg.ccGroupBlockAck.cic.flag = 1;
								sd_msg.msg.ccGroupBlockAck.cic.pcm = (rv_msg.msg.ccGroupBlock.cic.ptr[0] << 3)
									| ((rv_msg.msg.ccGroupBlock.cic.ptr[1] & 0xE0) >> 5);
								sd_msg.msg.ccGroupBlockAck.cic.timeslot = rv_msg.msg.ccGroupBlock.cic.ptr[1] & 0x1F;
								aifg_ie_decode(&rv_msg.msg.ccGroupBlock.cicList, &tmp_ie);
								memcpy(&sd_msg.msg.ccGroupBlockAck.cicList, &tmp_ie.param.bm_cicList, sizeof(tmp_ie.param.bm_cicList));	
								aifg_send_udt(tmp_cgid, &sd_msg, &tmp_sccp_msg);
							}
							break;
						case AIFG_MSG_ID_CC_GROUP_UNBLK:
							{
								aifg_ie tmp_ie;
								SP_UiPriPara tmp_sccp_msg;
								memset(&tmp_sccp_msg, 0, sizeof(tmp_sccp_msg));
								rv_msg.aif_port = AIFG_PORT_NOT_NEED;
								rv_msg.app_port = UPPER_PROC;

								//send back group unblock ack
								sd_msg.id = AIFG_MSG_ID_CC_GROUP_UNBLK_ACK;
								sd_msg.msg.ccGroupUnblockAck.cic.flag = 1;
								sd_msg.msg.ccGroupUnblockAck.cic.pcm = (rv_msg.msg.ccGroupUnblock.cic.ptr[0] << 3)
									| ((rv_msg.msg.ccGroupUnblock.cic.ptr[1] & 0xE0) >> 5);
								sd_msg.msg.ccGroupUnblockAck.cic.timeslot = rv_msg.msg.ccGroupUnblock.cic.ptr[1] & 0x1F;
								aifg_ie_decode(&rv_msg.msg.ccGroupUnblock.cicList, &tmp_ie);
								memcpy(&sd_msg.msg.ccGroupUnblockAck.cicList, &tmp_ie.param.bm_cicList, sizeof(tmp_ie.param.bm_cicList));	
								aifg_send_udt(tmp_cgid, &sd_msg, &tmp_sccp_msg);
							}
							break;
						case AIFG_MSG_ID_RESET_ACK:
						case AIFG_MSG_ID_RESET_CC_ACK:
						case AIFG_MSG_ID_BLOCK_ACK:
						case AIFG_MSG_ID_UNBLOCK_ACK:
						case AIFG_MSG_ID_CC_GROUP_BLK_ACK:
						case AIFG_MSG_ID_CC_GROUP_UNBLK_ACK:
							rv_msg.aif_port = AIFG_PORT_NOT_NEED;
							rv_msg.app_port = LOCAL_PROC;
							break;
						default:
							redirectFlag = 0;	//no need to redirect to other server
							rv_msg.aif_port = AIFG_PORT_NOT_NEED;
							rv_msg.app_port = UPPER_PROC;
							break;
					}

					if (redirectFlag){
						//redirect to the other server
						aifg_msg_redirect(&sccp_msg);
					}

					//deliver to upper layer application, currently global BSSMAP procedure does not activate a AIFG port
					if(LOCAL_PROC != rv_msg.app_port){
						rv_msg.trace_flag = 0;
						sap[tmp_sapid].callback_func(AIFG_IND_RV_MSG, &rv_msg);
						if (rv_msg.trace_flag == 1)
							aifg_pcb[rv_msg.aif_port].trace_flag = rv_msg.trace_flag;	//app may enable trace by setting rv_msg.trace_flag
						aifg_pcb[rv_msg.aif_port].upper_port = rv_msg.app_port;	//record app port if new assigned
						aifg_debug_print(rv_msg.aif_port, AIFG_EVENT_SD_IND, &rv_msg, 0);
					}
				}
				break;
			default:
				aifg_event = AIFG_ERR_UNKNOW_MSG;
				goto FINISH;
				break;
		}
	}
	aifg_debug_print(rv_msg.aif_port, AIFG_EVENT_RV_MSG, &rv_msg, 0);

	//call port process
	if(AIFG_PORT_NOT_NEED != rv_msg.aif_port){
		if (aifg_pcb[rv_msg.aif_port].stat == AIFG_PORT_IDLE){
			aifg_debug_print(rv_msg.aif_port, AIFG_ERR_MSG_RV_TO_IDLE_PORT, &rv_msg, 0);
			goto ERROR_PROC;
		}
		aifg_port_proc(&aifg_pcb[rv_msg.aif_port], NULL, &rv_msg);

		if(sccp_msg.uUiPri == N_CONNECT_IND || sccp_msg.uUiPri == N_DATA_IND)
			link_info[aifg_pcb[rv_msg.aif_port].link_id].cur_port = rv_msg.aif_port;
	}

FINISH:	
	if (sccp_msg.uUiPri == N_DISCONNECT_IND)
		aifg_del_link(sccp_msg.wConnId);	//release the link
	
	msg_statistics[rv_msg.id][0]++;
	if (rv_msg.id == AIFG_MSG_ID_L3_INFO)
		msg_statistics[rv_msg.msg.completeL3Info.l3msg.id][0]++;	

	return AIFG_PROC_CONTINUE;

ERROR_PROC:
	aifg_debug_print(rv_msg.aif_port, aifg_event, &rv_msg, sccp_msg.wConnId);
	return AIFG_PROC_CONTINUE;
}

//End of interface function definition-----------------------------------------------

//SCCP SAP---------------------------------------------------------------------------
void aifg_send_udt(int cgid, aifg_msg_t *msg, SP_UiPriPara *buf_ptr)
{
	int len = 0;

	aifg_debug_print(msg->aif_port, AIFG_EVENT_SD_MSG, msg, 0);

	if(NULL == buf_ptr)
		buf_ptr = &sccp_msg;

	buf_ptr->tPriUnion.tPriNUDataReq.tUD.aUserData[len++] = AIFG_MSG_BSSMAP;	//Protocol discriminator

	len++;	//skip length

	if(aifg_msg_sd_func_ptr[msg->id] != NULL)
		len += aifg_msg_sd_func_ptr[msg->id](msg, buf_ptr->tPriUnion.tPriNUDataReq.tUD.aUserData+len);

	buf_ptr->tPriUnion.tPriNUDataReq.tUD.aUserData[1] = len-2; //length

	buf_ptr->uUiPri = N_UNITDATA_REQ;
	buf_ptr->uAnsiFlag = 0;
	memset(&buf_ptr->tPriUnion.tPriNUDataReq.tCDA, 0, sizeof(buf_ptr->tPriUnion.tPriNUDataReq.tCDA));
	buf_ptr->tPriUnion.tPriNUDataReq.tUD.uDataLen = len;
	buf_ptr->tPriUnion.tPriNUDataReq.tCDA.DPC = cg[cgid].dpc;
	buf_ptr->tPriUnion.tPriNUDataReq.tCDA.NetID = cg[cgid].ni;
	buf_ptr->tPriUnion.tPriNUDataReq.tCDA.RI = 0x01;	//route on SSN
	buf_ptr->tPriUnion.tPriNUDataReq.tCDA.GTI = 0x00;	//no global tittle
	buf_ptr->tPriUnion.tPriNUDataReq.tCDA.SSN = 0xFE;	//BSSAP
	buf_ptr->tPriUnion.tPriNUDataReq.tCDA.ip = 0xFFFFFFFF;

	memset(&buf_ptr->tPriUnion.tPriNUDataReq.tCGA, 0, sizeof(buf_ptr->tPriUnion.tPriNUDataReq.tCGA));
	buf_ptr->tPriUnion.tPriNUDataReq.tCGA.NetID = cg[cgid].ni;
	buf_ptr->tPriUnion.tPriNUDataReq.tCGA.RI = 0x01;	//route on SSN
	buf_ptr->tPriUnion.tPriNUDataReq.tCGA.GTI = 0x00;	//no global tittle
	buf_ptr->tPriUnion.tPriNUDataReq.tCGA.SSN = 0xFE;	//BSSAP

	PostSp(buf_ptr);
	msg_statistics[msg->id][1]++;

	return;
}

//return new assigned link id
int aifg_send_cr(int sapid, int cgid, aifg_msg_t *msg)
{
	int len = 0;	
	BYTE *sd_buf = sccp_msg.tPriUnion.tPriNConnReq.tUD.aUserData;

	assert(msg->id == AIFG_MSG_ID_L3_INFO || msg->id == AIFG_MSG_ID_HO_REQUEST);

	aifg_debug_print(msg->aif_port, AIFG_EVENT_SD_MSG, msg, 0);

	sd_buf[len++] = AIFG_MSG_BSSMAP;	//Protocol discriminator
	sd_buf[len++] = 0;					//skip length

	if(aifg_msg_sd_func_ptr[msg->id] != NULL)
		sd_buf[1] = aifg_msg_sd_func_ptr[msg->id](msg, &(sd_buf[len]));

	len += sd_buf[1]; //length

	assert(len < SP_MAX_UD);

	sccp_msg.uUiPri = N_CONNECT_REQ;
	sccp_msg.uAnsiFlag = 0;
	memset(&sccp_msg.tPriUnion.tPriNConnReq.tCDA, 0, sizeof(sccp_msg.tPriUnion.tPriNConnReq.tCDA));
	sccp_msg.tPriUnion.tPriNConnReq.tCDA.DPC = cg[cgid].dpc;
	sccp_msg.tPriUnion.tPriNConnReq.tCDA.NetID = cg[cgid].ni;
	sccp_msg.tPriUnion.tPriNConnReq.tCDA.RI = 0x01;		//route on SSN
	sccp_msg.tPriUnion.tPriNConnReq.tCDA.GTI = 0x00;	//no global tittle
	sccp_msg.tPriUnion.tPriNConnReq.tCDA.SSN = 0xFE;	//BSSAP
	sccp_msg.tPriUnion.tPriNConnReq.tCDA.ip = 0xFFFFFFFF;
	sccp_msg.tPriUnion.tPriNConnReq.uOptFlag = 0x08;
	sccp_msg.tPriUnion.tPriNConnReq.tUD.uDataLen = len;

	PostSp(&sccp_msg);
	msg_statistics[msg->id][1]++;
	if (msg->id == AIFG_MSG_ID_L3_INFO){
		int msg_id = aifg_msgtype_to_localid(msg->msg.completeL3Info.l3Info.ptr[0], 
											msg->msg.completeL3Info.l3Info.ptr[1]);
		msg_statistics[msg_id][1]++;
	}

	return sccp_msg.wConnId;
}

void aifg_send_dt1(int linkid, aifg_msg_t *msg, int ti)
{
	int len = 0;
	BYTE *sd_buf = sccp_msg.tPriUnion.tPriNDataReq.tUD.aUserData;

	assert(msg->id != AIFG_MSG_ID_L3_INFO || msg->id != AIFG_MSG_ID_HO_REQUEST);

	aifg_debug_print(msg->aif_port, AIFG_EVENT_SD_MSG, msg, 0);

	if(AIFG_PD_BSSMAP_DEDICATED == msg->pd){
		sd_buf[len++] = AIFG_MSG_BSSMAP;	//Protocol discriminator
		sd_buf[len++] = 0;					//skip length

		if(aifg_msg_sd_func_ptr[msg->id] != NULL)
			sd_buf[1] = aifg_msg_sd_func_ptr[msg->id](msg, &(sd_buf[len]));

		len += sd_buf[1]; //length
		msg_statistics[msg->id][1]++;
	}
	else if(msg->id != AIFG_MSG_ID_TRANSPARENT_DTAP){
		sd_buf[len++] = AIFG_MSG_DTAP;	//Protocol discriminator
		//DLCI
		if (msg->pd == AIFG_PD_DTAP_SMS)
			sd_buf[len++] = 0x03;
		else
			sd_buf[len++] = 0x00;

		sd_buf[len++] = 1;

		//TI and PD
		if(ti != -1 && msg->pd != AIFG_PD_DTAP_MM)
			sd_buf[len++] = msg->pd | (ti << 4);
		else
			sd_buf[len++] = msg->pd;

		if(aifg_msg_sd_func_ptr[msg->id] != NULL)
			sd_buf[2] += aifg_msg_sd_func_ptr[msg->id](msg, &(sd_buf[len]));

		len += sd_buf[2] - 1; //length
		msg_statistics[msg->id][1]++;
	}
	else{
		//transparently transfer of DTAP message at BSC side
		len += msg->msg.dtap_msg.len;
		memcpy(sd_buf, msg->msg.dtap_msg.ptr, msg->msg.dtap_msg.len);
		msg_statistics[aifg_msgtype_to_localid(msg->pd, msg->msg.dtap_msg.ptr[1])][1]++;
	}

	sccp_msg.uUiPri = N_DATA_REQ;
	sccp_msg.wConnId = linkid;
	sccp_msg.tPriUnion.tPriNDataReq.tUD.uDataLen = len;

	PostSp(&sccp_msg);
}

void aifg_send_rlsd(int linkid)
{
	sccp_msg.wConnId = linkid;
	sccp_msg.uUiPri = N_DISCONNECT_REQ;
	sccp_msg.tPriUnion.tPriNDisconnReq.eREA = 0;
	sccp_msg.tPriUnion.tPriNDisconnReq.uOptFlag = 0;

	aifg_debug_print(-1, AIFG_EVENT_LINK_RELEASE, NULL, sccp_msg.wConnId);
	PostSp(&sccp_msg);
}
//End of SCCP SAP--------------------------------------------------------------------

