/*	map coding mobile service c file	*/
/*	written by Liu Zhiguo 2003-03-04	*/
/*	Version 2.0							*/
/*	--------------------------------	*/

#include "map_includes.h"
#include "map_acn.h"


SCCP_ADDR *did_to_sccpAddr(u32 dialogue_id);

int assign_sscsi(char *tag_prefix, struct SsCsi_struct *p_csi, ASN_BUF *asnbuf)
{
	char		tagseq[32];
	int			ii, buflen;

	sprintf(tagseq, "%s.16-1", tag_prefix);
	add_null(tagseq, 0x20, asnbuf);
	if(p_csi->event_list.list_len > CAMELSS_LEN)
		return RER;
		sprintf(tagseq, "%s.16-1.16", tag_prefix);
		add_null(tagseq, 0x20, asnbuf);
	for(ii = 0;ii < p_csi->event_list.list_len; ii++)
	{
		sprintf(tagseq, "%s.16-1.16.4-%d", tag_prefix, ii+1);
		buflen = add_tlv(tagseq, 1, &p_csi->event_list.ss_code[ii], 0x00, asnbuf);
	}
	buflen = p_csi->scf_add[0];
	sprintf(tagseq, "%s.16-1.4-10", tag_prefix);
	buflen = add_tlv(tagseq, buflen, p_csi->scf_add + 1, 0x00, asnbuf);
	return buflen;
}

int extract_sscsi(char *tag_prefix, struct SsCsi_struct *p_csi, ASN_BUF *asnbuf)
{
	char		tagseq[32];
	int			retval = -1, ii = 0;

	while(ii < CAMELSS_LEN)
	{
		sprintf(tagseq, "%s.16.16.4-%d", tag_prefix, ii);
		if((retval = GetTLV(tagseq, 1, &p_csi->event_list.ss_code[ii], 0x00, asnbuf)) < 0)
			break;
		ii ++;
	}
	if(ii == 0)
		return RER;
	sprintf(tagseq, "%s.16.4", tag_prefix);
	if((retval = GetTLV(tagseq, ISDN_LEN, p_csi->scf_add + 1, 0x00, asnbuf)) < 0)
		return RER;
	p_csi->scf_add[0] = retval;
	return ROK;
}

int assign_smscsi(char *tag_prefix, struct SMSCsi_struct *p_csi, ASN_BUF *asnbuf)
{
	char		tagseq[32];
	int			len=0, ii, buflen;

	if((p_csi->param_flag & 0x01) == 0x01)
	{
		if(p_csi->tdpdata_list.tdpdata_len > TDPDATA_NUM)
			return -1;
		for(ii = 0; ii < p_csi->tdpdata_list.tdpdata_len; ii++)	//sms-BCSM Camel TDP Data List
		{
			sprintf(tagseq, "%s.0.16-%d", tag_prefix, ii + 1);
			add_null(tagseq, 0x20, asnbuf);
			sprintf(tagseq, "%s.0.16-%d.0-1", tag_prefix, ii + 1);		
			len = AddInteger(tagseq, p_csi->tdpdata_list.tdp_data[ii].det_point, 0x80, asnbuf);
			sprintf(tagseq, "%s.0.16-%d.1-2", tag_prefix, ii + 1);
			len = AddInteger(tagseq, p_csi->tdpdata_list.tdp_data[ii].service_key, 0x80, asnbuf);
			if((buflen = p_csi->tdpdata_list.tdp_data[ii].scf_add[0]) > ISDN_LEN)
				buflen = ISDN_LEN;
			sprintf(tagseq, "%s.0.16-%d.2-3", tag_prefix, ii + 1);
			len = AddTLV(tagseq, buflen, p_csi->tdpdata_list.tdp_data[ii].scf_add + 1, 0x80, asnbuf);
			sprintf(tagseq, "%s.0.16-%d.3-4", tag_prefix, ii + 1);
			len = AddInteger(tagseq, p_csi->tdpdata_list.tdp_data[ii].def_hand, 0x80, asnbuf);
		}
	}
	if((p_csi->param_flag & 0x02) == 0x02)		//camel capability Handling
	{
		sprintf(tagseq, "%s.1", tag_prefix);
		len = AddInteger(tagseq, p_csi->camel_caphand, 0x80, asnbuf);
	}
	if((p_csi->param_flag & 0x04) == 0x04)		//notificationTOCSE
	{
		sprintf(tagseq, "%s.3", tag_prefix);
		len = add_null(tagseq, 0x80, asnbuf);
	}
	if((p_csi->param_flag & 0x08) == 0x08)		//csiActive
	{
		sprintf(tagseq, "%s.4", tag_prefix);
		len = add_null(tagseq, 0x80, asnbuf);
	}
	return len;
}

int extract_smscsi(char *tag_prefix, struct SMSCsi_struct *p_csi, ASN_BUF *asnbuf)
{
	char	tagseq[32];
	int		retval = -1, ii =0 ;

	p_csi->param_flag = 0;
	while(ii < TDPDATA_NUM)
	{
		sprintf(tagseq, "%s.0.16-%d.0", tag_prefix, ii + 1);
		if((retval = GetInteger(tagseq, (int *)&p_csi->tdpdata_list.tdp_data[ii].det_point, 0x80, asnbuf)) < 0)
			break;
		sprintf(tagseq, "%s.0.16-%d.1", tag_prefix, ii + 1);
		if((retval = GetInteger(tagseq, (int *)&p_csi->tdpdata_list.tdp_data[ii].service_key, 0x80, asnbuf)) < 0)
			break;
		sprintf(tagseq, "%s.0.16-%d.2", tag_prefix, ii + 1);
		if((retval = GetTLV(tagseq, ISDN_LEN, p_csi->tdpdata_list.tdp_data[ii].scf_add + 1, 0x80, asnbuf)) < 0)
			break;
		p_csi->tdpdata_list.tdp_data[ii].scf_add[0] = retval;
		sprintf(tagseq, "%s.0.16-%d.3", tag_prefix, ii + 1);
		if((retval = GetInteger(tagseq, (int *)&p_csi->tdpdata_list.tdp_data[ii].def_hand, 0x80, asnbuf)) < 0)
			break;
		ii ++;
	}
	if(ii > 0)
	{
		p_csi->param_flag |= 0x01;
		p_csi->tdpdata_list.tdpdata_len = ii;
	}
	//camel Capability Handling
	sprintf(tagseq, "%s.1", tag_prefix);
	if(GetInteger(tagseq, (int *)&p_csi->tdpdata_list.tdp_data[ii].def_hand, 0x80, asnbuf) > 0)
		p_csi->param_flag |= 0x02;
	//notificationTOCSE
	sprintf(tagseq, "%s.3", tag_prefix);
	if(get_null(tagseq, asnbuf) >= 0)
	{
		p_csi->param_flag |= 0x04;
		p_csi->notificationToCSE = 1;
	}
	//csi-Active
	sprintf(tagseq, "%s.4", tag_prefix);
	if(get_null(tagseq, asnbuf) >= 0)
	{
		p_csi->param_flag |= 0x08;
		p_csi->csi_Active = 1;
	}
	return 1;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding update loction argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++  */
int assign_uplocarg(struct MapUL_Arg *ul_ptr,u8 *buf ,u8 ver)
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;
	u8			tag1;
	char			tlv1[32];

	asn_encode(buf,&asn_buf);
	flag = ul_ptr->param_flag;
	if (flag & 0x01)	// has IMSI
		buf_len = add_tlv("4-1",IMSI_LEN,ul_ptr->imsi,0x00,&asn_buf);
	else
	{
		mapp_log_debug("update location request lack IMSI");
		return RER;
	}		
	if ( (flag & 0x02) && ( !(flag & 0x20) || ver >1 ) )	// has not MSC number
		buf_len = add_tlv("1-2",ul_ptr->msc_num[0],ul_ptr->msc_num+1,0x80,&asn_buf);
	else
	{
		mapp_log_debug("update location request lack MSISDN");
		return RER;
	}
	
	if (flag & 0x04)	// has not VLR address
		buf_len = add_tlv("4-3",ul_ptr->vlr_num[0],ul_ptr->vlr_num+1,0x00,&asn_buf);
	else
	{
		mapp_log_debug("update location request lack VLR address");
		return RER;
	}
	tag1 = 4;
	if (flag & 0x08)	// has LMSI
	{
		sprintf(tlv1,"10-%d",tag1++);
		buf_len = add_tlv(tlv1,LMSI_LEN,ul_ptr->lmsi,0x80,&asn_buf);
	}
	if (flag & 0x10)	// vlr capability
	{
		if (ul_ptr->vlr_cap.param_flag & 0x01)	// camel phase
		{
			sprintf(tlv1,"6-%d.0",tag1++);
			buf_len = add_tlv(tlv1,3,ul_ptr->vlr_cap.camel_phase,0x80,&asn_buf);
		}
	}
	
	if( (flag & 0x20) && !(flag & 0x02) && (ver == 1) )
		buf_len = add_tlv("0-2",ul_ptr->vlr_num[0],ul_ptr->vlr_num+1,0x00,&asn_buf);
	else
	{
		mapp_log_debug("update location request lack VLR address");
		return RER;
	}
	return buf_len;
} 

int extract_uplocarg(struct	MapUL_Arg *ul_ptr,u32 buf_len,u8 *buf ,u8 ver)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	u32			flag = 0;

	ul_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("4-1",temp_buf,&asn_buf);	// get imsi
	if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)// get IMSI
	{
		flag |= 0x01;
		memcpy(ul_ptr->imsi,temp_buf,len);
	}
	else
	{
		mapp_log_debug("update location indicate error IMSI");
		return RER;		
	}
	len = get_tlv("0", temp_buf,&asn_buf);
	if( len > 2 )
	{
		flag |= 0x20;
		ul_ptr->roaming_num[0] = len;
		memcpy( ul_ptr->roaming_num+1,temp_buf,len);	
	}
	else if ((len = get_tlv("1",temp_buf,&asn_buf)) > 2)	// get MSC number
	{
		flag |= 0x02;
		ul_ptr->msc_num[0] = len;
		memcpy(ul_ptr->msc_num+1,temp_buf,len);
	}
	else
	{
		mapp_log_debug("update location indicate lack MSC number or roaming num");
		return RER;
	}	
	if ((len = get_tlv("4-3",temp_buf,&asn_buf)) > 2)	// get VLR number
	{
		flag |= 0x04;
		ul_ptr->vlr_num[0] = len;
		memcpy(ul_ptr->vlr_num+1,temp_buf,len);
	}
	else
	{
		mapp_log_debug("update location indicate lack VLR number");
		return RER;
	}	
	len = get_tlv("10",temp_buf,&asn_buf);	// get lmsi number
	if (len == LMSI_LEN)
	{
		flag |= 0x08;
		memcpy(ul_ptr->lmsi,temp_buf,LMSI_LEN);
	}
	len = get_tlv("6.0",temp_buf,&asn_buf);		//get camel info
	if (len != -1)
	{
		memcpy(ul_ptr->vlr_cap.camel_phase,temp_buf,3);
		flag |= 0x10;
	}
	ul_ptr->param_flag = flag;
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding update loction response	*/
/*  ++++++++++++++++++++++++++++++++++++++++++  */
int	assign_uplocres(struct MapUL_Res *ul_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	if (ul_ptr->param_flag & 0x01) 
		buf_len = add_tlv("4",ul_ptr->hlr_num[0],ul_ptr->hlr_num+1,0x00,&asn_buf);		
	else
	{
		mapp_log_debug("update location response lack hlr number");
		return RER;
	}	
	return buf_len;
}

int extract_uplocres(struct MapUL_Res *ul_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	ul_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_uplocres buf_len=0");
		return RER;
	}	
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if ((len = get_tlv("4",temp_buf,&asn_buf)) > 2)	// get HLR number
	{
		ul_ptr->param_flag |= 0x01;
		ul_ptr->hlr_num[0] = len;
		memcpy(ul_ptr->hlr_num+1,temp_buf,len);
	}
	else
	{
		mapp_log_debug("update location confirm lack HLR number");
		return RER;
	}
	return ROK;
}



/*	--->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>		MAP V1		<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,---*/


/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send parameters argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_SendParaArg(struct MapSP_Arg *sendpara_ptr,u8 *buf)		// lw_add
{
	ASN_BUF		asn_buf;
	int			flag,buf_len=0;

	int			temp_index;
	int			param_num;
	
	asn_encode(buf,&asn_buf); 
	flag = sendpara_ptr->param_flag;
	//add_null("16", 0x20, &asn_buf);
	buf_len = AddTLV("16",0,NULL,0x20,&asn_buf);
	if( sendpara_ptr->param_flag & 0x01 )
	{
				if(sendpara_ptr->sub_id.choice_flag == 1)//imsi
				{
					buf_len = add_tlv("16.0",IMSI_LEN,sendpara_ptr->sub_id.id_choice.imsi,0x80,&asn_buf);
				}
				else if(sendpara_ptr->sub_id.choice_flag == 2)//tmsi
				{
					
					buf_len = add_tlv("16.1",TMSI_LEN,sendpara_ptr->sub_id.id_choice.tmsi,0x80,&asn_buf);
				}
				else
				{
					mapp_log_debug("sendParameter indicate subscriber id choice error");;//do report err
				}
	}
	else
				{
					mapp_log_debug("sendParameter indicate lack subscriber id ");;//do report err
				}
			//Request Parameter List
	if( sendpara_ptr->param_flag & 0x02 )
	{
				char tag[16];
				param_num = sendpara_ptr->ReqPara_num;
				if( sendpara_ptr->ReqPara_num > 2  )
				{
					mapp_log_debug("sendParameter indicate request parameter list num error");;//do reptor_err;
					param_num = 2;
				}
				//add_null("16", 0x20, &asn_buf);
				buf_len = AddTLV("16.16",0,NULL,0x20,&asn_buf);
				for( temp_index =0 ;temp_index < param_num ;temp_index ++)
				{
					sprintf(tag,"16.16.10-%d",temp_index+1);
					buf_len = add_tlv(tag,1,(u8 *)&sendpara_ptr->ReqPara[temp_index],0x00,&asn_buf);
				}
	}
	else
				{
					mapp_log_debug("sendParameter indicate lack Request Parameter List ");;//do report err
				}
	return buf_len;
}



int extract_SendParaArg(struct	MapSP_Arg *sendpara_ptr,u32 buf_len,u8 *buf)	//lw_add
{
	ASN_BUF		asn_buf;
	int			len,index;
	u8			temp_buf[256];
	
	sendpara_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	
	len = get_tlv("0-1",temp_buf,&asn_buf);	// get IMSI
	if (len ==IMSI_LEN  && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
			sendpara_ptr->param_flag |= 0x01;
			sendpara_ptr->sub_id.choice_flag = 0x01;
			memcpy(sendpara_ptr->sub_id.id_choice.imsi,temp_buf,len);
	}
	
	len = get_tlv("1-1",temp_buf,&asn_buf);	// get TMSI
	if (len == TMSI_LEN)
	{
		sendpara_ptr->param_flag |= 0x01;
		sendpara_ptr->sub_id.choice_flag = 0x02; 
		memcpy(sendpara_ptr->sub_id.id_choice.tmsi,temp_buf,len);
	}
	
	index =0 ;
	while( ( len = get_tlv("16-2.10",temp_buf,&asn_buf) ) == 1  && index < 2 )
	{
		memcpy( sendpara_ptr->ReqPara+index++ , temp_buf , len );	 // get Request parameter
	}
	if( index > 0 )
	{
		sendpara_ptr->param_flag |= 0x02;
		sendpara_ptr->ReqPara_num = index ;
	}
	return ROK;
}



/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send parameters response	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_Sub_Data(Sub_data_struct *sub_data, u8 *buf )
{
	ASN_BUF		asn_buf;
	int			jj,kk;
	u32			flag1;
	u32			flag;
	u32			len;
	int			buf_len=0;
	int			temp_len;
	u8			temp_data[256],temp_buf[256];
	u8			tag1=1,tag2=1,tag3=1,tag4=1,tag5=1;
	char		tlv1[32],tlv2[32],tlv3[32],tlv4[32],tlv5[32];
	struct 		ExtFwdInfo_struct		*fwd_ptr;
	struct		ExtSsData_struct		*ss_ptr;
	struct		ExtCallBarInfo_struct	*callbar_ptr;
	
	asn_encode(buf,&asn_buf);
	flag = sub_data->param_flag;

	if (flag & 0x02)	// MSISDN
	{
		sprintf(tlv1,"1-%d",tag1++);
		buf_len = add_tlv(tlv1,sub_data->msisdn[0],sub_data->msisdn+1,0x80,&asn_buf);
	}
	if (flag & 0x04)	// category
	{
		sprintf(tlv1,"2-%d",tag1++);
		buf_len = add_tlv(tlv1,1,&sub_data->category,0x80,&asn_buf);
	}
	if (flag & 0x08)	// sub status
	{
		sprintf(tlv1,"3-%d",tag1++);
		temp_data[0] = sub_data->sub_status;
		buf_len = add_tlv(tlv1,1,temp_data,0x80,&asn_buf);
	}
	if (flag & 0x20)	// bearer service list
	{
		temp_len = bearer_bittostr(sub_data->bearer_data,temp_data,0);

		if(temp_len > 0)
		{
			sprintf(tlv1,"4-%d",tag1++);

			for (jj = 0;jj < temp_len;jj ++)
			{
				sprintf(tlv2,"%s.4-%d",tlv1,jj+1);
				buf_len = add_tlv(tlv2,1,temp_data+jj,0x00,&asn_buf);
			}
		}
	}
	if (flag & 0x40)	// tele service list
	{
		temp_len = tele_bittostr(sub_data->tele_data,temp_data,0);
		if(temp_len > 0)
		{
			sprintf(tlv1,"6-%d",tag1++);
			for (jj = 0;jj < temp_len;jj++)
			{
				sprintf(tlv2,"%s.4-%d",tlv1,jj+1);
				buf_len = add_tlv(tlv2,1,temp_data+jj,0x00,&asn_buf);
			}
		}
	}
	if (flag & 0x80)	// ss info list	
	{
		sprintf(tlv1,"7-%d",tag1++);
		tag2 = 1;
		if (sub_data->ss_info.param_flag & 0x01)	// fwd info
		{
			fwd_ptr = (ExtFwdInfo_struct *) &sub_data->ss_info.fwd_info;
			for (jj = 0;jj < 4;jj ++)	//tag2
			{
				tag3 = 1;
				kk = 0x01 << jj;
				if (fwd_ptr->param_flag & kk)
				{
					sprintf(tlv2,"%s.0-%d",tlv1,tag2++);
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);	// for ss_code
					buf_len = add_tlv(tlv3,1,&fwd_ptr->ss_code[jj],0x00,&asn_buf);
					sprintf(tlv3,"%s.16-%d",tlv2,tag3++);
					add_null(tlv3,0x20,&asn_buf);
					tag4 = 1;
					sprintf(tlv4,"%s.16-%d",tlv3,tag4);
					add_null(tlv4,0x20,&asn_buf);
					tag5 = 1;
					flag1 = fwd_ptr->fwd_feat[jj].param_flag;
					if (flag1 & 0x01) // bs group
					{
						if (fwd_ptr->fwd_feat[jj].bs_code.param_flag == 1)
						{
							sprintf(tlv5,"%s.2-%d",tlv4,tag5++);
							if (tele_bittostr(fwd_ptr->fwd_feat[jj].bs_code.tele_code,temp_data,1))
								buf_len = add_tlv(tlv5,1,temp_data,0x80,&asn_buf);
						}
						else if(fwd_ptr->fwd_feat[jj].bs_code.param_flag  == 2)
						{
							sprintf(tlv5,"%s.3-%d",tlv4,tag5++);
							if (bearer_bittostr(fwd_ptr->fwd_feat[jj].bs_code.bearer_code,temp_data,1))
								buf_len = add_tlv(tlv5,1,temp_data,0x80,&asn_buf);
						}
					}
					if (flag1 & 0x02)	//ss status
					{
						sprintf(tlv5,"%s.4-%d",tlv4,tag5++);
						buf_len = add_tlv(tlv5,1,&fwd_ptr->fwd_feat[jj].ss_status,0x80,&asn_buf);
					}
					if (flag1 & 0x04) //fwdto_num
					{
						sprintf(tlv5,"%s.5-%d",tlv4,tag5++);
						len = fwd_ptr->fwd_feat[jj].fwdto_num[0];
						buf_len = add_tlv(tlv5,len,fwd_ptr->fwd_feat[jj].fwdto_num+1,0x80,&asn_buf);
					}
					if (flag1 &0x08) //fwd opt
					{
						sprintf(tlv5,"%s.6-%d",tlv4,tag5++);
						buf_len = add_tlv(tlv5,1,&fwd_ptr->fwd_feat[jj].fwd_option,0x80,&asn_buf);
					}
					if (flag1 &0x10) //norc time
					{
						sprintf(tlv5,"%s.7-%d",tlv4,tag5++);
						buf_len = add_tlv(tlv5,1,&fwd_ptr->fwd_feat[jj].norc_time,0x80,&asn_buf);
					}		  	
				}							
			}
		}
		if (sub_data->ss_info.param_flag & 0x02) // call bar info
		{
			callbar_ptr = (ExtCallBarInfo_struct *) &sub_data->ss_info.call_info;
			for (jj = 0;jj < 5;jj ++)
			{
				kk = 0x01 << jj;
				if ((callbar_ptr->param_flag & kk) != 0)
				{
					sprintf(tlv2,"%s.1-%d",tlv1,tag2++);
					tag3 = 1;
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);
					buf_len = add_tlv(tlv3,1,&callbar_ptr->ss_code[jj],0x00,&asn_buf);
					sprintf(tlv3,"%s.16-%d",tlv2,tag3++);
					add_null(tlv3,0x20,&asn_buf);
					tag4 = 1;
					sprintf(tlv4,"%s.16-%d",tlv3,tag4);
					add_null(tlv4,0x20,&asn_buf);
					tag5 = 1;
					if (callbar_ptr->bs_code[jj].param_flag == 2)
					{
						sprintf(tlv5,"%s.2-%d",tlv4,tag5++);
						if (bearer_bittostr(callbar_ptr->bs_code[jj].bearer_code,temp_data,1))
							buf_len = add_tlv(tlv5,1,temp_data,0x80,&asn_buf);
					}
					else if (callbar_ptr->bs_code[jj].param_flag == 1)
					{
						sprintf(tlv5,"%s.3-%d",tlv4,tag5++);
						if (tele_bittostr(callbar_ptr->bs_code[jj].tele_code,temp_data,1))
							buf_len = add_tlv(tlv5,1,temp_data,0x80,&asn_buf);
					}
					sprintf(tlv5,"%s.4-%d",tlv4,tag5++);
					buf_len = add_tlv(tlv5,1,&callbar_ptr->ss_status[jj],0x80,&asn_buf);							
				}
			}
		}
		if (sub_data->ss_info.param_flag & 0x08) // ss data
		{
			ss_ptr = (ExtSsData_struct *)&sub_data->ss_info.ss_data;
			for(jj = 0;jj < 16;jj ++)
			{
				kk = 0x01 << jj;
				if (ss_ptr->param_flag & kk)
				{
					sprintf(tlv2,"%s.3-%d",tlv1,tag2++);
					tag3 = 1;
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);
					buf_len = add_tlv(tlv3,1,&ss_ptr->ss_code[jj],0x00,&asn_buf);
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);
					buf_len = add_tlv(tlv3,1,&ss_ptr->ss_status[jj],0x80,&asn_buf);
					if (ss_ptr->subs_opt[jj].choice_flag == 1)
					{
						sprintf(tlv3,"%s.2-%d",tlv2,tag3++);
						temp_buf[0] = ss_ptr->subs_opt[jj].choice.clires_opt;
						buf_len = add_tlv(tlv3,1,temp_buf,0x80,&asn_buf);
					}
					else if (ss_ptr->subs_opt[jj].choice_flag == 2)
					{
						sprintf(tlv3,"%s.1-%d",tlv2,tag3++);
						temp_buf[0] = ss_ptr->subs_opt[jj].choice.over_cate;
						buf_len = add_tlv(tlv3,1,temp_buf,0x80,&asn_buf);
					}
				}
			}
		}
	}

	if (flag & 0x10)	// odb-data
	{
		if(sub_data->odb_data.param_flag & 0x03)
		{
			sprintf(tlv1,"8-%d",tag1++);
			tag2 = 1;
			if (sub_data->odb_data.param_flag & 0x01)	// ODB general data
			{
				sprintf(tlv2,"%s.3-%d",tlv1,tag2++);
				temp_buf[0] = sub_data->odb_data.odb_general >> 8;
				temp_buf[1] = sub_data->odb_data.odb_general;
				len = bytestrtobitstr(temp_data,temp_buf,6);
				//len = bytestrtobitstr(temp_data,temp_buf,15); /* odb is 6bitstring for version1/2 */
				buf_len = add_tlv(tlv2,len,temp_data,0x00,&asn_buf);
			}
			if (sub_data->odb_data.param_flag & 0x02)	// ODB HPLMN data
			{
				sprintf(tlv2,"%s.3-%d",tlv1,tag2++);
				temp_buf[0] = sub_data->odb_data.odb_hplmn;
				len = bytestrtobitstr(temp_data,temp_buf,4);
				buf_len = add_tlv(tlv2,len,temp_data,0x00,&asn_buf);
			}
		}
	}

	
	if (flag & 0x100)	// roaming restriction due to unsuppoerted feature
	{
		sprintf(tlv1,"9-%d",tag1++);
		buf_len = add_null(tlv1,0x80,&asn_buf);
	}
	if (flag & 0x200)	// regional Subscription Data
	{
		if (sub_data->zc_list.list_len > ZONECODE_LEN)
			return RER;
		for (jj = 0;jj < sub_data->zc_list.list_len;jj ++)
		{
			sprintf(tlv1,"10-%d.4-%d",tag1,jj+1);
			buf_len = add_tlv(tlv1,2,sub_data->zc_list.zone_code[jj],0x00,&asn_buf);
		}
		tag1 ++;
	}
	return buf_len;
}

int extract_Sub_Data(Sub_data_struct *sub_data , u32 buf_len , u8 *buf)
{
	  ASN_BUF	asn_buf;
	int		len,jj,index;
	int		temp_len,ss_mask;
	u32		flag=0;
	u8		tag1;
	char	tlv2[32],tlv3[32];
	u8		temp_buf[256],temp_data[256];
	struct	ExtFwdInfo_struct		*fwd_ptr;
	struct	ExtCallBarInfo_struct	*callbar_ptr;
	struct	ExtSsData_struct		*ss_ptr;
	
	sub_data->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);	// get imsi
	if (len==IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		flag |= 0x01;
		memcpy(sub_data->imsi,temp_buf,len);
	}	
	if ((len=get_tlv("1",temp_buf,&asn_buf)) > 2)
	{
		flag |= 0x02;
		sub_data->msisdn[0] = len;
		memcpy(sub_data->msisdn+1,temp_buf,len);	
	}
	if (get_tlv("2",temp_buf,&asn_buf) > 0)
	{
		flag |= 0x04;
		sub_data->category = temp_buf[0];
	}
	if(get_tlv("3",temp_buf,&asn_buf) > 0)
	{
		flag |= 0x08;
		sub_data->sub_status = temp_buf[0];
	}
	sub_data->odb_data.param_flag = 0;
	len = get_tlv("8.3-1",temp_buf,&asn_buf);	//odb-data->odb->GreneralData
	if (len != -1)
	{
		flag |= 0x10; // odb - data
		sub_data->odb_data.param_flag |= 0x01; //odb general
		jj = bitstrtobytestr(temp_data,temp_buf,len);
		sub_data->odb_data.odb_general = bcdtou32(temp_data,jj);
	}
	len = get_tlv("8.3-2",temp_buf,&asn_buf);
	if (len != -1)
	{
		flag |= 0x10; // odb - data
		sub_data->odb_data.param_flag |= 0x02; // odb hplmn
		jj = bitstrtobytestr(temp_data,temp_buf,len);
		sub_data->odb_data.odb_hplmn = bcdtou32(temp_data,jj);
	}
	temp_len = 0;
	for (jj = 0;jj < BSLIST_LEN;jj ++)	// bearer Service List
	{
		sprintf(tlv2,"4.4-%d",jj+1);
		if (get_tlv(tlv2,temp_buf,&asn_buf) < 1)
			break;
		temp_data[jj] = temp_buf[0];
		temp_len ++;
		flag |= 0x20;
	}
	sub_data->bearer_data = bearer_strtobit(temp_data,temp_len);	
	temp_len = 0;
	for (jj = 0;jj < TSLIST_LEN;jj ++)	// tele Service List
	{
		sprintf(tlv2,"6.4-%d",jj+1);
		if (get_tlv(tlv2,temp_buf,&asn_buf) < 1)
			break;
		temp_data[jj] = temp_buf[0];
		temp_len++;
		flag |= 0x40;
	}
	sub_data->tele_data = tele_strtobit(temp_data,temp_len);
	sub_data->ss_info.param_flag = 0;
	tag1 = 1; ss_mask = 0;
	for(index=0;index<3;index++)
	{
		if (!(ss_mask & 0x01) && get_tlv("7.0",temp_buf,&asn_buf) != -1)	// forwarding info
		{
			flag |= 0x80; // ss info
			sub_data->ss_info.param_flag |= 0x01; // fwd info
			fwd_ptr = (ExtFwdInfo_struct *)&sub_data->ss_info.fwd_info;
			fwd_ptr->param_flag = 0;
			for (jj = 0;jj < 4;jj ++)
			{
				fwd_ptr->fwd_feat[jj].param_flag = 0;
				fwd_ptr->fwd_feat[jj].bs_code.param_flag = 0;
				sprintf(tlv2,"7.0-%d.4",tag1); // ss code
				len = get_tlv(tlv2,temp_buf,&asn_buf);
				if (len > 0)
				{
					fwd_ptr->param_flag |= (0x01 << jj);
					fwd_ptr->ss_code[jj] = temp_buf[0];
					ss_mask |= 0x01;
				}
				else
					break;
				sprintf(tlv2,"7.0-%d.16.16",tag1);	// forward feature
				sprintf(tlv3,"%s.2",tlv2);	// bearer code of bs code
				len = get_tlv(tlv3,temp_buf,&asn_buf);
				if (len > 0)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x01;
					fwd_ptr->fwd_feat[jj].bs_code.param_flag = 2; // bearer
					fwd_ptr->fwd_feat[jj].bs_code.bearer_code = bearer_strtobit(temp_buf,1);
				}
				sprintf(tlv3,"%s.3",tlv2);	// tele code of bs code
				len = get_tlv(tlv3,temp_buf, &asn_buf);
				if (len >= 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x01; // bs code
					fwd_ptr->fwd_feat[jj].bs_code.param_flag = 1;// tele
					fwd_ptr->fwd_feat[jj].bs_code.tele_code = tele_strtobit(temp_buf,1);
				}
				sprintf(tlv3,"%s.4",tlv2);
				if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x02; // ss status
					fwd_ptr->fwd_feat[jj].ss_status = temp_buf[0];
				}
				sprintf(tlv3,"%s.5",tlv2);
				len = get_tlv(tlv3,temp_buf,&asn_buf);
				if (len >= 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x04; // fwd to num
					fwd_ptr->fwd_feat[jj].fwdto_num[0] = len;
					memcpy(fwd_ptr->fwd_feat[jj].fwdto_num+1,temp_buf,len);
				}
				sprintf(tlv3,"%s.6",tlv2);
				if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x08; // fwd opt
					fwd_ptr->fwd_feat[jj].fwd_option = temp_buf[0];
				}
				sprintf(tlv3,"%s.7",tlv2);
				if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x10; // norc time
					fwd_ptr->fwd_feat[jj].norc_time = temp_buf[0];
				}
				tag1 ++;
			}
		}
		if (!(ss_mask & 0x02) && get_tlv("7.1",temp_buf,&asn_buf) != -1)		// call Barring Info
		{
			flag |= 0x80; // ss info
			sub_data->ss_info.param_flag |= 0x02; // call bar info
			callbar_ptr = (ExtCallBarInfo_struct *)&sub_data->ss_info.call_info;
			callbar_ptr->param_flag = 0;
			for (jj = 0;jj < 5;jj ++)
			{
				callbar_ptr->bs_code[jj].param_flag = 0;
				sprintf(tlv2,"7.1-%d.4",tag1);	//callbarringInfo
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					callbar_ptr->param_flag |= (0x01 << jj); // ss code
					callbar_ptr->ss_code[jj] = temp_buf[0];
					ss_mask |= 0x02;
				}
				else
					break;
				sprintf(tlv2,"7.1-%d.16.16",tag1);
				sprintf(tlv3,"%s.4",tlv2);	
				if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
					callbar_ptr->ss_status[jj] = temp_buf[0];
				sprintf(tlv3,"%s.2",tlv2);
				len = get_tlv(tlv3,temp_buf,&asn_buf);
				if (len >= 1)
				{
					callbar_ptr->bs_code[jj].param_flag = 2; // bearer
					callbar_ptr->bs_code[jj].bearer_code = bearer_strtobit(temp_buf,1);
				}
				sprintf(tlv3,"%s.3",tlv2);
				len	= get_tlv(tlv3,temp_buf,&asn_buf);
				if (len >= 1)
				{
					callbar_ptr->bs_code[jj].param_flag = 1; // bearer
					callbar_ptr->bs_code[jj].tele_code = tele_strtobit(temp_buf,1);
				}
				tag1 ++;
			}
		}
		if (!(ss_mask & 0x04) && get_tlv("7.3",temp_buf,&asn_buf) != -1)		// ss_Data
		{
			flag |= 0x80; // ss info
			sub_data->ss_info.param_flag |= 0x08; // ss data
			ss_ptr = (ExtSsData_struct *)&sub_data->ss_info.ss_data;
			ss_ptr->param_flag = 0;
			for(jj = 0;jj < 16;jj ++)
			{
				sprintf(tlv2,"7.3-%d.4-1",tag1);
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					ss_ptr->param_flag |= (0x01 << jj);  
					ss_ptr->ss_code[jj] = temp_buf[0];
					ss_mask |= 0x04;
				}
				else
					break;
				sprintf(tlv2,"7.3-%d.4-2",tag1);	//ss-status
	//			len = get_tlv(tlv2,temp_buf,&asn_buf);
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
					ss_ptr->ss_status[jj] = temp_buf[0];
				ss_ptr->subs_opt[jj].choice_flag = 0;
				sprintf(tlv2,"7.3-%d.2-3",tag1);	//cliRestrictionOption
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					ss_ptr->subs_opt[jj].choice_flag = 1; // clires opt
					ss_ptr->subs_opt[jj].choice.clires_opt = temp_buf[0];
				}
				sprintf(tlv2,"7.3-%d.1-3",tag1);	//overrideCategory
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					ss_ptr->subs_opt[jj].choice_flag = 2; // clires opt
					ss_ptr->subs_opt[jj].choice.over_cate = temp_buf[0];
				}
				sprintf(tlv2,"7.3-%d.2-2",tag1);	// bearer code
				len = get_tlv(tlv2,temp_buf,&asn_buf);
				if (len > 0)
					ss_ptr->bs_code[jj].bearer_code = bearer_strtobit(temp_buf,1);
				sprintf(tlv2,"7.3-%d.3",tag1);	// tele code
				len = get_tlv(tlv2,temp_buf, &asn_buf);
				if (len >= 1)
					ss_ptr->bs_code[jj].tele_code = tele_strtobit(temp_buf,1);
				tag1 ++;
			}
		}
	}
	if (get_null("9",&asn_buf) != -1)	//get roaming restriction data
	{
		flag |= 0x100;
		sub_data->roam_feature = 1;
	}
	len = get_tlv("10",temp_buf,&asn_buf);	//regional Subscription Data
	if (len > 0)
	{
		flag |= 0x200;
		for (jj = 0;jj < ZONECODE_LEN;jj ++)
		{
			sprintf(tlv2,"10.4-%d",jj+1);
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len == 2)
				memcpy(sub_data->zc_list.zone_code[jj],temp_buf,2);
			else
				break;
		}
		sub_data->zc_list.list_len = jj;
	}
	
	sub_data->param_flag = flag;
	return ROK;
}

int assign_SendParaRes(struct MapSP_Res *sp_ptr,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0,param_num,index,temp_len;
	u8			temp_buf[256];
	char		tag[16];
	//char		str[640];
	u8          uSubDataCount = 0 ;
	
	asn_encode(buf,&asn_buf);
	flag = sp_ptr->param_flag;
	
	if (flag & 0x01)	// has sentparalist
	{
		param_num = sp_ptr->sendparamlist_num ;
		if( param_num > 6)
		{
			mapp_log_debug("send param response sentparalist num error, is more than 6");;//do report err
			param_num  = 6 ;
		}
		
		for( index = 0 ; index < param_num ; index++ )
		{
		    if( sp_ptr->sendparalist[index].choice_flag == 4 )
		    {
		    	uSubDataCount++;
		    }
		}
		
		if( uSubDataCount > 2)
		{
			mapp_log_debug("send param response sentparalist sub data is too much, may exceed the supported map message len\r\n");;//do report err
			return buf_len;
		}
		
		buf_len = add_null("16",0x20,&asn_buf);
		for( index=0; index< param_num ; index++)
		{
				switch( sp_ptr->sendparalist[index].choice_flag  )
				{
					case 1: //imsi
						sprintf(tag,"16.0-%d",index+1);
						buf_len = add_tlv(tag,IMSI_LEN,sp_ptr->sendparalist[index].SP_Res_Choice.imsi,0x80,&asn_buf);
						break;
					case 2: // authlist set
						sprintf(tag,"16.1-%d",index+1);
						temp_len = assign_authset( (struct	AuthSet_struct* )&sp_ptr->sendparalist[index].SP_Res_Choice.auth_set, temp_buf );
			      buf_len = add_tlv(tag, temp_len, temp_buf, 0xa0, &asn_buf);
						break;
					case 4: // sub data
						sprintf(tag,"16.2-%d",index+1);
						memset( temp_buf ,0 ,256);
						temp_len = assign_Sub_Data( &sp_ptr->sendparalist[index].SP_Res_Choice.sub_data , temp_buf );
						//Bcd2Str_Space(str, temp_buf, temp_len);
						//printf("\r\nsub data code :[%d]\r\n%s\r\n",temp_len,str);
			      buf_len = add_tlv(tag, temp_len, temp_buf, 0xa0, &asn_buf);
						break;
					case 8: //ki
						sprintf(tag,"16.4-%d",index+1);
						buf_len = add_tlv(tag,16,sp_ptr->sendparalist[index].SP_Res_Choice.ki,0x80,&asn_buf);
						break;
					default:
						break;
				}
		}
	}
	//Bcd2Str_Space(str, buf, buf_len);
	//printf("\r\nSend para Res code :[%d]\r\n%s\r\n",buf_len,str);
	return buf_len;
}

int extract_SendParaRes ( struct MapSP_Res *sp_ptr, u32 buf_len, u8 * buf )     // lw add
{
    ASN_BUF asn_buf;
    int index;
    u8  temp_buf[256];
    int temp_len;
    char tag[16];

    sp_ptr->param_flag = 0;
    
    if( buf_len == 0 )
        return RER;
    if( asn_decode_v3 ( buf, buf_len, &decErr, &asn_buf ) == -1 )
        return RER;
    for ( index = 0; index < 6; index++ )
    {
    	    
     	sprintf(tag,"16.0-%d",index+1);
        if( ( ( temp_len = get_tlv ( tag, temp_buf, &asn_buf ) ) != -1 ) && ( ( temp_buf[IMSI_LEN - 1] & 0xf0 ) == 0xf0 ) )
        {
            sp_ptr->param_flag |= 0x01;
            sp_ptr->sendparamlist_num++;
            sp_ptr->sendparalist[index].choice_flag = 1;
            memcpy ( sp_ptr->sendparalist[index].SP_Res_Choice.imsi, temp_buf, temp_len );
            continue;
        }
	    else
	    {
	        sprintf(tag,"16.1-%d",index+1);
	        if( ( temp_len = get_tlv ( tag, temp_buf, &asn_buf ) ) > 0 )
	        {
	            sp_ptr->param_flag |= 0x01;
	            sp_ptr->sendparamlist_num++;
	            if( ( extract_authset ( ( struct AuthSet_struct * ) &sp_ptr->sendparalist[index].SP_Res_Choice.auth_set, temp_len, temp_buf ) ) != 0 )
	            {
	                sp_ptr->sendparalist[index].choice_flag = 2;
	                continue;
	            }
	        }
		    else
		    {
	            sprintf(tag,"16.2-%d",index+1);
	            if( ( temp_len = get_tlv ( tag, temp_buf, &asn_buf ) ) > 0 )
	            {
	               sp_ptr->param_flag |= 0x01;
	               sp_ptr->sendparamlist_num++;
	               if( ( extract_Sub_Data ( &sp_ptr->sendparalist[index].SP_Res_Choice.sub_data, temp_len, temp_buf ) ) != 0 )
	               {
	                  sp_ptr->sendparalist[index].choice_flag = 4;
	                  continue;
	               }
	            }
			    else
			    {
	               sprintf(tag,"16.4-%d",index+1);
	               if( ( temp_len = get_tlv ( tag, temp_buf, &asn_buf ) ) > 0 )
	               {
	                  sp_ptr->sendparalist[index].choice_flag = 8;
	                  memcpy ( sp_ptr->sendparalist[index].SP_Res_Choice.ki, temp_buf, temp_len );
	                  sp_ptr->sendparamlist_num++;
	                  continue;
	               }
	               else 
	               {
	                  if( 0 == index )
	                  {
	                  	  return RER;
	                  }
	                  else 
	                  {
	                  	  break;
	                  }
	               }
			    }
		    }
        }	    
    }
    //}
    return ROK;
}









/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding noteSubscriberPresent argument*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_NotPresentArg(struct MapNP_Arg *np_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	flag = np_ptr->param_flag;
	if (flag == 0x01)	// has lmsi
	{
		
		buf_len = add_tlv("4",IMSI_LEN,np_ptr->imsi,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("nosubsriberpresent param flag error");
		return -1;
	}

	return buf_len;
}

int extract_NotPresentArg( struct MapNP_Arg *np_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	np_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4",temp_buf,&asn_buf);	// get IMSI
	if (len == IMSI_LEN  && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		np_ptr->param_flag = 0x01;
		memcpy(np_ptr->imsi,temp_buf,len);
	}
	else
	{
		mapp_log_debug("nosubsriberpresent lack imsi or imsi err\r\n");
		return RER;
	}

	return ROK;
}




/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  ProcessUnstructuredSS-Data argument*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_ProcessUSSDArg(struct MapPUSSD_Arg *ussd_ptr, u8 *buf)  // lw add 
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	flag = ussd_ptr->param_flag;
	if (flag == 0x01)	
	{
		
		buf_len = add_tlv("4",ussd_ptr->ussd_len,ussd_ptr->ussd_data,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("Process USSD param flag error");
		return -1;
	}

	return buf_len;
}

int extract_ProcessUSSDArg( struct MapPUSSD_Arg *ussd_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	ussd_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4",temp_buf,&asn_buf);	
	if (len != -1)
	{
		ussd_ptr->param_flag = 0x01;
		ussd_ptr->ussd_len = len;
		memcpy(ussd_ptr->ussd_data,temp_buf,len);
	}
	else
	{
		mapp_log_debug("Process USSD  lack imsi");
		return RER;
	}

	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  ProcessUnstructuredSS-Data ResPonse*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_ProcessUSSDRes(struct MapPUSSD_Res *ussd_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	flag = ussd_ptr->param_flag;
	if (flag == 0x01)	
	{
		buf_len = add_tlv("4",ussd_ptr->ussd_len,ussd_ptr->ussd_data,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("Process USSD param flag error");
		return -1;
	}

	return buf_len;
}

int extract_ProcessUSSDRes( struct MapPUSSD_Res *ussd_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	ussd_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4",temp_buf,&asn_buf);	
	if (len != -1)
	{
		ussd_ptr->param_flag = 0x01;
		ussd_ptr->ussd_len = len;
		memcpy(ussd_ptr->ussd_data,temp_buf,len);
	}
	else
	{
		mapp_log_debug("Process USSD  lack imsi");
		return RER;
	}

	return ROK;
}


/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  BeginSubscriberActivity Argmnet*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_SAArg(struct MapSA_Arg *sa_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	flag = sa_ptr->param_flag;
	if (flag == 0x03)	
	{
		buf_len = add_tlv("4-1",IMSI_LEN+1,sa_ptr->imsi,0x00,&asn_buf);
		buf_len = add_tlv("4-2",9,sa_ptr->Enity_num,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug(" BeginSubscriberActivity param flag error");
		return -1;
	}

	return buf_len;
}

int extract_SAArg( struct MapSA_Arg *sa_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	sa_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4-1",temp_buf,&asn_buf);	
	if (len == IMSI_LEN + 1)
	{
		sa_ptr->param_flag |= 0x01;
		memcpy(sa_ptr->imsi,temp_buf,len);
	}
	else
	{
		mapp_log_debug("Process USSD  lack imsi");
		return RER;
	}

	len = get_tlv("4-2",temp_buf,&asn_buf);	
	if (len != -1)
	{
		sa_ptr->param_flag |= 0x01;
		sa_ptr->enity_len = len;
		memcpy(sa_ptr->Enity_num,temp_buf,len);
	}
	else
	{
		mapp_log_debug("Process USSD  lack Enity_nu");
		return RER;
	}

	return ROK;
}



/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding PerformHandover Argmnet*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_HOArg(struct MapHO_Arg *ho_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	flag = ho_ptr->param_flag;
	if (flag & 0x01)	
	{
		buf_len = add_tlv("4-1",7,ho_ptr->tgt_cellID,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug(" PerformHanover  lack target cell id");
		return -1;
	}

	if (flag & 0x02)	
	{
		buf_len = add_tlv("4-2",7,ho_ptr->srv_cellID,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug(" PerformHanover  lack service cell id");
		return -1;
	}

	if (flag & 0x04)	
	{
		buf_len = add_tlv("4-3",10,ho_ptr->chl_type,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug(" PerformHanover  lack channel type");
		return -1;
	}

	if (flag & 0x08)	
	{
		buf_len = add_tlv("4-4",2,ho_ptr->class_mark,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug(" PerformHanover  lack class mark info");
		return -1;
	}

	if (flag & 0x10)	
	{
		buf_len = add_tlv("11",1,&ho_ptr->ho_priority,0x80,&asn_buf);
	}
	

	if (flag & 0x20)	
	{
		buf_len = add_tlv("12",8,ho_ptr->kc,0x80,&asn_buf);
	}
	

	return buf_len;
}

int extract_HOArg( struct MapHO_Arg *ho_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	ho_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4-1",temp_buf,&asn_buf);	
	if (len == 7)
	{
		ho_ptr->param_flag |= 0x01;
		memcpy(ho_ptr->tgt_cellID,temp_buf,len);
	}
	else
	{
		mapp_log_debug(" PerformHanover  lack target cell id");
	}

	len = get_tlv("4-2",temp_buf,&asn_buf);	
	if (len == 7)
	{
		ho_ptr->param_flag |= 0x02;
		memcpy(ho_ptr->srv_cellID,temp_buf,len);
	}
	else
	{
		mapp_log_debug(" PerformHanover  lack service cell id");
	}

	len = get_tlv("4-3",temp_buf,&asn_buf);	
	if (len == 10)
	{
		ho_ptr->param_flag |= 0x04;
		memcpy(ho_ptr->chl_type,temp_buf,len);
	}
	else
	{
		mapp_log_debug(" PerformHanover  lack channel type");
	}

	len = get_tlv("4-4",temp_buf,&asn_buf);	
	if (len == 2)
	{
		ho_ptr->param_flag |= 0x08;
		memcpy(ho_ptr->class_mark,temp_buf,len);
	}
	else
	{
		mapp_log_debug(" PerformHanover  lack class mark info");
	}

	len = get_tlv("11",temp_buf,&asn_buf);	
	if (len == 1)
	{
		ho_ptr->param_flag |= 0x10;
		memcpy(&ho_ptr->ho_priority,temp_buf,len);
	}
	else
	{
		mapp_log_debug(" PerformHanover  lack handover priority");
	}

	len = get_tlv("12",temp_buf,&asn_buf);	
	if (len == 8)
	{
		ho_ptr->param_flag |= 0x20;
		memcpy(ho_ptr->kc,temp_buf,len);
	}
	else
	{
		mapp_log_debug(" PerformHanover  lack kc");
	}

	return ROK;
}



/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  PerformHandover ResPonse*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_HORes(struct MapHO_Res *ho_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	flag = ho_ptr->param_flag;
	if (flag & 0x01)	
	{
		
		buf_len = add_tlv("4",9,ho_ptr->ho_num,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("handover res lack handovber");
		return -1;
	}

	if (flag & 0x02)	
	{
		
		buf_len = add_tlv("16.2",1,&ho_ptr->access_singal_info.protocol_id,0x00,&asn_buf);
		buf_len = add_tlv("16.4",ho_ptr->access_singal_info.singal_info_len,ho_ptr->access_singal_info.signal_info,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("handover res lack handovber");
		return -1;
	}

	return buf_len;
}

int extract_HORes( struct MapHO_Res *ho_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	ho_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4",temp_buf,&asn_buf);	
	if (len != -1)
	{
		ho_ptr->param_flag |= 0x01;
		memcpy(ho_ptr->ho_num,temp_buf,len);
	}
	else
	{
		mapp_log_debug("performhandover lack handover number");
		return RER;
	}

	len = get_tlv("16",temp_buf,&asn_buf);	
	if (len != -1)
	{
		len = get_tlv("16.2",temp_buf,&asn_buf);
		if( len == 1)
		{
			memcpy(&ho_ptr->access_singal_info.protocol_id , temp_buf ,len);
		}
		else
		{
			mapp_log_debug("performhandover lack protocol_id");
			return RER;
		}

		len = get_tlv("16.4",temp_buf,&asn_buf);
		if( len != -1)
		{
			memcpy(ho_ptr->access_singal_info.signal_info, temp_buf ,len);
			ho_ptr->access_singal_info.singal_info_len= len;
		}
		else
		{
			mapp_log_debug("performhandover lack protocol_id"); 
			return RER;
		}
	}
	else
	{
		mapp_log_debug("performhandover lack access_singal_info");
		return RER;
	}

	return ROK;
}


/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  PreformSubsequenceHandover Arg*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_PFSHOArg(struct MapPFSHO_Arg *psho_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;
	//char		str[512];

	asn_encode(buf,&asn_buf);
	flag = psho_ptr->param_flag;
	if (flag & 0x01)	
	{
		buf_len = add_tlv("4-1",GCID_LEN,psho_ptr->target_id,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("performsubsequenthandover arg lack target id");
		return -1;
	}
	if (flag & 0x02)	
	{
		buf_len = add_tlv("4-2",GCID_LEN,psho_ptr->service_id,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("performsubsequenthandover arg lack service id");
		return -1;
	}
	
	if (flag & 0x04)	
	{
		buf_len = add_tlv("4-3",ISDN_LEN,psho_ptr->msc_num,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("performsubsequenthandover arg lack msc number");
		return -1;
	}
	
	if (flag & 0x08)	
	{
		buf_len = add_tlv("10-4",2,psho_ptr->classmark_info,0x80,&asn_buf);
	}
	
	//Bcd2Str_Space(str, buf, buf_len);
	//printf("\r\nPFSHO arg code :[%d]\r\n%s\r\n",buf_len,str);
	return buf_len;
}

int extract_PFSHOArg( struct MapPFSHO_Arg *psho_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	psho_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4",temp_buf,&asn_buf);	
	if (len == GCID_LEN)
	{
		psho_ptr->param_flag |= 0x01;
		memcpy( psho_ptr->target_id,temp_buf,len);
	}
	else
	{
		mapp_log_debug("performsubsequenthandover res  lack target id");
		return RER;
	}
		
	len = get_tlv("4",temp_buf,&asn_buf);	
	if (len == GCID_LEN) 
	{
		psho_ptr->param_flag |= 0x02;
		memcpy( psho_ptr->service_id,temp_buf,len);
	}
	else
	{
		mapp_log_debug("performsubsequenthandover res  lack service id");
		return RER;
	}

	len = get_tlv("4-3",temp_buf,&asn_buf);	
	if (len <= ISDN_LEN )
	{
		psho_ptr->param_flag |= 0x04;
		psho_ptr->msc_num[0] = len;
		memcpy( psho_ptr->msc_num+1,temp_buf,len);
	}
	else
	{
		mapp_log_debug("performsubsequenthandover res lack msc number");
		return RER;
	}
	
	len = get_tlv("10-4",temp_buf,&asn_buf);	
	if (len == 2 )
	{
		psho_ptr->param_flag |= 0x08;
		memcpy( psho_ptr->classmark_info,temp_buf,len);
	}
	else
	{
		mapp_log_debug("performsubsequenthandover  lack msc number");
		return RER;
	}
	
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  PreformSubsequenceHandover res */
/*  ++++++++++++++++++++++++++++++++++++++++++	*/

int assign_PFSHORes(struct MapPFSHO_Res *psho_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			temp_len;
	u8			temp_buf[256];

	asn_encode(buf,&asn_buf);
	if (psho_ptr->param_flag & 0x01)		// access_sig_info
	{
		temp_len = assign_extsiginfo(&psho_ptr->access_sig_info,temp_buf);
		buf_len = add_tlv("16",temp_len,temp_buf,0x20,&asn_buf);
	}
	return buf_len;
}

int extract_PFSHORes(struct MapPFSHO_Res *psho_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	psho_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	
	len = get_tlv("16",temp_buf,&asn_buf);	// access_sig_info
	if (len != -1)
	{
		if (!extract_extsiginfo(&psho_ptr->access_sig_info,len,temp_buf))
			return RER;
		psho_ptr->param_flag |= 0x01;
	}
	return ROK;
}


/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  NoteInternalHandover Arg */
/*  ++++++++++++++++++++++++++++++++++++++++++	*/

int assign_NIHOArg(struct MapNIHO_Arg *niho_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0,temp_len;
	u8			temp_buf[256];

	asn_encode(buf,&asn_buf);
	flag = niho_ptr->param_flag;
	if (flag & 0x01)	
	{
		buf_len = add_tlv("10-1",1,&niho_ptr->ho_type,0x00,&asn_buf);
	}
	else 
	{
		mapp_log_debug("NoteInternalHandover lack handover type");
		return -1;
	}
	if (flag & 0x02)	
	{
		buf_len = add_tlv("1-2",GCID_LEN,niho_ptr->target_id,0x80,&asn_buf);
	}
	
	if (flag & 0x04)	
	{
		temp_len = assign_extsiginfo(&niho_ptr->channel_id,temp_buf);
		buf_len = add_tlv("2-3",temp_len, temp_buf,0x80,&asn_buf);
	}
	else 
	{
		mapp_log_debug("NoteInternalHandover lack channel id");
		return -1;
	}
	
	//Bcd2Str_Space(temp_buf, buf, buf_len);
	//printf("\r\nNIHO arg code :[%d]\r\n%s\r\n",buf_len,temp_buf);
	return buf_len;
}

int extract_NIHOArg( struct MapNIHO_Arg *niho_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	niho_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("10-1",temp_buf,&asn_buf);	
	if (len == 1)
	{
		niho_ptr->param_flag |= 0x01;
		memcpy( &niho_ptr->ho_type,temp_buf,len);
	}
	else
	{
		mapp_log_debug("NoteInternalHandover  lack handover type");
		return RER;
	}

	len = get_tlv("1",temp_buf,&asn_buf);	
	if (len == GCID_LEN)
	{
		niho_ptr->param_flag |= 0x02;
		memcpy(niho_ptr->target_id,temp_buf,len);
	}
	
	len = get_tlv("2",temp_buf,&asn_buf);	
	if (len != -1 )
	{
		if(!extract_extsiginfo(&niho_ptr->channel_id,len,temp_buf))
			return RER;
		niho_ptr->param_flag |= 0x04;		
	}
	
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding  Tracesubscirberactivity Arg */
/*  ++++++++++++++++++++++++++++++++++++++++++	*/

int assign_TSAArg(struct MapTSA_Arg *tsa_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;
	

	asn_encode(buf,&asn_buf);
	flag = tsa_ptr->param_flag;
	if (flag & 0x01)	
	{
		buf_len = add_tlv("0",IMSI_LEN,tsa_ptr->imsi,0x80,&asn_buf);
	}
	
	if (flag & 0x02)	
	{
		buf_len = add_tlv("1",2,tsa_ptr->trace_ref,0x80,&asn_buf);
	}
	else 
	{
		mapp_log_debug("Tracesubscirberactivity lack call reference");
		return -1;
	}
	
	if (flag & 0x04)	
	{
		buf_len = add_tlv("2",1,&tsa_ptr->trace_type,0x80,&asn_buf);
	}
	else 
	{
		mapp_log_debug("TracesubscirberactivityTracesubscirberactivity lack call type");
		return -1;
	}
	 
	if (flag & 0x08)	
	{
		buf_len = add_tlv("3",tsa_ptr->omc_id_len,tsa_ptr->omc_id,0x80,&asn_buf);
	}
	
	if (flag & 0x10)	
	{
		buf_len = add_tlv("4",3,tsa_ptr->call_ref,0x80,&asn_buf);
	}
	
	
	return buf_len;
}

int extract_TSAArg( struct MapTSA_Arg *tsa_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	tsa_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("0",temp_buf,&asn_buf);	
	if (len == IMSI_LEN)
	{
		tsa_ptr->param_flag |= 0x01;
		memcpy( &tsa_ptr->imsi,temp_buf,len);
	}


	len = get_tlv("1",temp_buf,&asn_buf);	
	if (len == 2)
	{
		tsa_ptr->param_flag |= 0x02;
		memcpy(&tsa_ptr->trace_ref,temp_buf,len);
	}
	
	len = get_tlv("2",temp_buf,&asn_buf);	
	if (len == 1 )
	{
		tsa_ptr->param_flag |= 0x04;
		memcpy(&tsa_ptr->trace_type,temp_buf,len);	
	}
	
	len = get_tlv("3",temp_buf,&asn_buf);	
	if (len != -1 )
	{
		tsa_ptr->param_flag |= 0x08;
		tsa_ptr->omc_id_len = len;
		memcpy(&tsa_ptr->omc_id,temp_buf,len);	
	}
	
	len = get_tlv("4",temp_buf,&asn_buf);	
	if (len == 3 )
	{
		tsa_ptr->param_flag |= 0x04;
		memcpy(&tsa_ptr->call_ref,temp_buf,len);	
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding BeginSubscriberActivity Arg */
/*  ++++++++++++++++++++++++++++++++++++++++++	*/

int assign_BSAArg(struct MapBSA_Arg *bsa_ptr, u8 *buf)  // lw add
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	flag = bsa_ptr->param_flag;
	if (flag & 0x01)	
	{
		buf_len = add_tlv("4-1",IMSI_LEN+1,bsa_ptr->imsi,0x00,&asn_buf);
	}
	
	if (flag & 0x02)	
	{
		buf_len = add_tlv("4-2",bsa_ptr->orgenty_num_len,bsa_ptr->orgenty_num,0x00,&asn_buf);
	}
	return buf_len;
}

int extract_BSAArg( struct MapBSA_Arg *bsa_ptr,u32 buf_len,u8 *buf) // lw add
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	bsa_ptr->param_flag = 0;

	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	len = get_tlv("4-1",temp_buf,&asn_buf);	
	if (len == IMSI_LEN+1)
	{
		bsa_ptr->param_flag |= 0x01;
		memcpy( bsa_ptr->imsi,temp_buf,len);
	}
	
	len = get_tlv("4-2",temp_buf,&asn_buf);	
	if (len != -1)
	{
		bsa_ptr->param_flag |= 0x02;
		bsa_ptr->orgenty_num_len = len; 
		memcpy(&bsa_ptr->orgenty_num,temp_buf,len);
	}
	return ROK;
}


/*	--->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>		MAP V1		<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,---*/
/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding cancel location argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_cancellocarg(struct MapCL_Arg *cl_ptr,u8 *buf,u8 ver)
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;
	u8			temp_buf[256];
	CL_identity	*id;

	asn_encode(buf,&asn_buf);
	flag = cl_ptr->param_flag;
	if( flag & 0x01 )
	{
		id = &cl_ptr->id;
		if( id->choice_flag == 1 )
		{
			buf_len =  add_tlv("4-1",IMSI_LEN,id->choice.imsi,0x00,&asn_buf);
		}
		else if( id->choice_flag == 2 )
		{
			buf_len =  add_null("16", 0x20, &asn_buf);
			buf_len =  add_tlv("16-1.4-1",IMSI_LEN,id->choice.imsi_withlmsi.imsi,0x00,&asn_buf);
			buf_len =  add_tlv("16-1.4-2",4,id->choice.imsi_withlmsi.lmsi,0x00,&asn_buf);
		}
	}	
	else
	{
		mapp_log_debug("cancellocation arg lack identity");
		return RER;
	}

	
//	if( ver !=3  && flag & 0x02 ) 
	if( flag & 0x02 ) 		
	{
		temp_buf[0] = cl_ptr->type;
		buf_len = add_tlv("10-2",1,temp_buf,0x00,&asn_buf);
	}
	
	return buf_len;
}

int extract_cancellocarg(struct MapCL_Arg *cl_ptr,u32 buf_len,u8 *buf,u8 ver)
{
	ASN_BUF		asn_buf;
	int	len1;
	u8			temp_buf1[256],temp_buf2[256];
	CL_identity	*id;
	
	cl_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER; 
	if( ( get_tlv("4-1",temp_buf1,&asn_buf) == IMSI_LEN ) 
			&&   ((temp_buf1[IMSI_LEN-1]&0xf0) == 0xf0 ) )
	{
			id = &cl_ptr->id;
			cl_ptr->param_flag |= 0x01;
			id->choice_flag = 1;
			memcpy( id->choice.imsi , temp_buf1 , IMSI_LEN );
	}
	else
	{
		if( ( get_tlv("16-1.4-1",temp_buf1,&asn_buf) == IMSI_LEN )  &&  ( get_tlv("16-1.4-2",temp_buf2,&asn_buf) == LMSI_LEN ) 
					&& ((temp_buf1[IMSI_LEN-1] & 0xf0 ) == 0xf0 ) )
		{
			id = &cl_ptr->id;
			cl_ptr->param_flag |= 0x01;
			id->choice_flag = 2;
			memcpy( id->choice.imsi_withlmsi.imsi , temp_buf1 , IMSI_LEN);
			memcpy( id->choice.imsi_withlmsi.lmsi , temp_buf2 ,LMSI_LEN);
		}
	}
	
	if( ver !=3 && ( len1 = get_tlv("10-2",temp_buf1,&asn_buf) ) == 1 )
	{
		cl_ptr->param_flag |= 0x02;
		memcpy( &cl_ptr->type,temp_buf1,len1);
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding cancel location response	*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_cancellocres(struct MapCL_Res *cl_ptr,u8 *buf)
{
	return 0;
}

int extract_cancellocres(struct MapCL_Res *cl_ptr,u32 buf_len,u8 *buf)
{
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding purge ms argument		*/
/*  ++++++++++++++++++++++++++++++++++++	*/
int assign_purgemsarg(struct MapPMS_Arg	*pms_ptr,u8 *buf,u8 version)
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0;
	u8			tag1;
	char			tlv1[32];
	
	asn_encode(buf,&asn_buf);
	flag = pms_ptr->param_flag;
	if (flag & 0x01)	// IMSI
		buf_len = add_tlv("4-1",IMSI_LEN,pms_ptr->imsi,0x00,&asn_buf);	// add IMSI parameter
	else
	{
		mapp_log_debug("purgeMS request lack IMSI");
		return RER;
	}
	tag1 = 2;
	if (flag & 0x02)	// VLR address
	{
		if (version == 2)
		{
			sprintf(tlv1,"4-%d",tag1++);
			buf_len = add_tlv(tlv1,pms_ptr->vlr_num[0],pms_ptr->vlr_num+1,0,&asn_buf);
		}
		else
		{
			sprintf(tlv1,"0-%d",tag1++);
			buf_len = add_tlv(tlv1,pms_ptr->vlr_num[0],pms_ptr->vlr_num+1,0x80,&asn_buf);	
		}
	}
	if (flag & 0x04)	// sgsn address
	{
		sprintf(tlv1,"1-%d",tag1++);
		buf_len = add_tlv(tlv1,pms_ptr->sgsn_num[0],pms_ptr->sgsn_num+1,0x80,&asn_buf);
	}
	return buf_len;
}

int extract_purgemsarg(struct MapPMS_Arg *pms_ptr,u32 buf_len,u8 *buf,u8 version)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	
	pms_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_purge MS arg,buf_len=0");
		return RER;
	}
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("4",temp_buf,&asn_buf);	// get IMSI
	if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		pms_ptr->param_flag |= 0x01;
		memcpy(pms_ptr->imsi,temp_buf,len);
	}
	else
	{
		mapp_log_debug("purge ms indicate error IMSI");
		return RER;
	}
	if (version == 2)	// get VLR number
		len = get_tlv("4-2",temp_buf,&asn_buf);
	else
		len = get_tlv("0-2",temp_buf,&asn_buf);
	if (len > 2)
	{
		pms_ptr->param_flag |= 0x02;
		pms_ptr->vlr_num[0] = len;
		memcpy(pms_ptr->vlr_num+1,temp_buf,len);
	}
	if ((len = get_tlv("1",temp_buf,&asn_buf)) > 2)	// get sgsn number
	{
		pms_ptr->param_flag |= 0x04;
		pms_ptr->sgsn_num[0] = len;
		memcpy(pms_ptr->sgsn_num+1,temp_buf,len);
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding purge ms response		*/
/*  ++++++++++++++++++++++++++++++++++++	*/
int assign_purgemsres(struct MapPMS_Res	*pms_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	if (pms_ptr->param_flag & 0x01)	// freeze TMSI
		buf_len = add_null("0",0x80,&asn_buf);
	if (pms_ptr->param_flag & 0x02)	// freeze P-TMSI
		buf_len = add_null("1",0x80,&asn_buf);
	return buf_len;
}

int extract_purgemsres(struct MapPMS_Res *pms_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];

	pms_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if (get_tlv("0",temp_buf,&asn_buf) > 0)	// freeze TMSI
	{
		pms_ptr->param_flag |= 0x01;
		pms_ptr->freeze_tmsi = 1;
	}
	if (get_tlv("1",temp_buf,&asn_buf) > 0)	// freeze P-TMSI
	{
		pms_ptr->param_flag |= 0x02;
		pms_ptr->freeze_ptmsi = 1;
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send identification argument		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_sndidentarg(struct MapSI_Arg *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	if (ptr->param_flag & 0x01)	// TMSI
		buf_len = add_tlv("4",TMSI_LEN,ptr->tmsi,0x00,&asn_buf);
	else
		return RER;
	return buf_len;
}

int extract_sndidentarg(struct MapSI_Arg *ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];

	ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if (get_tlv("4",temp_buf,&asn_buf) == TMSI_LEN)
	{
		ptr->param_flag |= 0x01;
		memcpy(ptr->tmsi,temp_buf,TMSI_LEN);
		return ROK;
	}
	else
		return RER;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send identification response		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_sndidentres(struct MapSI_Res *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			ii;
	int			temp_len;
	u8			temp_buf[256];
	char			tlv2[32];

	asn_encode(buf,&asn_buf);
	if (ptr->param_flag & 0x01)		// IMSI
		buf_len = add_tlv("4",IMSI_LEN,ptr->imsi,0x00,&asn_buf);
	else
		return RER;
	if (ptr->param_flag & 0x02)		// auth list
	{
		for (ii = 0;ii < ptr->authlist.auth_len;ii ++)
		{
			temp_len = assign_authset(&ptr->authlist.auth_set[ii],temp_buf);
			if (temp_len == RER)
				break;
			sprintf(tlv2,"16-%d",ii+1);
			buf_len = add_tlv(tlv2,temp_len,temp_buf,0x20,&asn_buf);
		}
	}
	return buf_len;
}

int extract_sndidentres(struct MapSI_Res *ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];
	int			len;
	int			ii;
	char			tlv2[32];

	ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("4",temp_buf,&asn_buf);
	if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		ptr->param_flag |= 0x01;
		memcpy(ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	for (ii = 0;ii < AUTHLIST_LEN;ii++)
	{
		ptr->authlist.auth_set[ii].param_flag = 0;
		sprintf(tlv2,"16-%d",ii+1);
		len = get_tlv(tlv2,temp_buf,&asn_buf);
		if (len <= 0)	// has not data
			break;
		if (!extract_authset(&ptr->authlist.auth_set[ii],len,temp_buf))
			break;
		ptr->param_flag |= 0x02;
		ptr->authlist.auth_len++;
	}	
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding update GPRS location argument		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_upgprslocarg(struct MapUGL_Arg *ugl_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			temp_len;
	u8			temp_buf[256];

	asn_encode(buf,&asn_buf);
	if (ugl_ptr->param_flag & 0x01)	// IMSI
		buf_len = add_tlv("4-1",IMSI_LEN,ugl_ptr->imsi,0x00,&asn_buf);
	else
		return RER;
	if (ugl_ptr->param_flag & 0x02)	// sgsn number
		buf_len = add_tlv("4-2",ugl_ptr->sgsn_num[0],ugl_ptr->sgsn_num+1,0x00,&asn_buf);
	else
		return RER;
	if (ugl_ptr->param_flag & 0x04)	// sgsn address
		buf_len = add_tlv("4-3",ugl_ptr->sgsn_add[0],ugl_ptr->sgsn_add+1,0x00,&asn_buf);
	else
		return RER;
	
	if (ugl_ptr->param_flag & 0x08)	// sgsn capability
	{
//		buf_len = add_null("0-4", 0xa0, &asn_buf);
		temp_len = assign_sgsnCapability(&ugl_ptr->sgsn_cap, temp_buf);
		if(temp_len != RER)
			buf_len = add_tlv("0-4", temp_len, temp_buf, 0xa0, &asn_buf);
	}
	
	return buf_len;
}

int extract_upgprslocarg(struct MapUGL_Arg *ugl_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	ugl_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("4-1",temp_buf,&asn_buf);	// IMSI
	if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		ugl_ptr->param_flag |= 0x01;
		memcpy(ugl_ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	len = get_tlv("4-2",temp_buf,&asn_buf);	// sgsn number
	if (len > 0 && len <= ISDN_LEN)
	{
		ugl_ptr->param_flag |= 0x02;
		ugl_ptr->sgsn_num[0] = len;
		memcpy(ugl_ptr->sgsn_num+1,temp_buf,len);
	}
	else
		return RER;
	len = get_tlv("4-3",temp_buf,&asn_buf);	// sgsn address
	if (len > 0 && len <= GSN_LEN)
	{
		ugl_ptr->param_flag |= 0x04;
		ugl_ptr->sgsn_add[0] = len;
		memcpy(ugl_ptr->sgsn_add+1,temp_buf,len);
	}
	else
		return RER;
	
	len = get_tlv("0-4",temp_buf,&asn_buf);	// sgsn capability
	if (len > 0)
	{
		ugl_ptr->param_flag |= 0x08;
		extract_sgsnCapability(&ugl_ptr->sgsn_cap, len, temp_buf);
	}
	
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding update GPRS location response		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_upgprslocres(struct MapUGL_Res *ugl_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	if (ugl_ptr->param_flag & 0x01)	// hlr number
		buf_len = add_tlv("4",ugl_ptr->hlr_num[0],ugl_ptr->hlr_num+1,0x00,&asn_buf);
	else
		return RER;
	
	if (ugl_ptr->param_flag & 0x02)	// add capability
	{
		buf_len = add_null("5", 0x80, &asn_buf);
	}
	
	return buf_len;
}

int extract_upgprslocres(struct MapUGL_Res *ugl_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	ugl_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("4",temp_buf,&asn_buf);	// hlr number
	if (len > 0 && len <= ISDN_LEN)
	{
		ugl_ptr->param_flag |= 0x01;
		ugl_ptr->hlr_num[0] = len;
		memcpy(ugl_ptr->hlr_num+1,temp_buf,len);
	}
	else
		return RER;
	
	len = get_tlv("0",temp_buf,&asn_buf);	// add capability
	if (len > 0)
	{
		ugl_ptr->add_cap = 1;
		ugl_ptr->param_flag |= 0x02;
	}
	
	return ROK;
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding provider subscriber info argument	*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_prvsubinfoarg(struct MapPSI_Arg *psi_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	if (psi_ptr->param_flag & 0x01)		// IMSI
		buf_len = add_tlv("0",IMSI_LEN,psi_ptr->imsi,0x80,&asn_buf);
	else
		return RER;
	if (psi_ptr->param_flag & 0x02)		// LMSI
		buf_len = add_tlv("1",LMSI_LEN,psi_ptr->lmsi,0x80,&asn_buf);
	if (psi_ptr->param_flag & 0x04)		// request info
	{
		if (psi_ptr->req_info.param_flag & 0x01)	// location info
			buf_len = add_null("2.0",0x80,&asn_buf);
		if (psi_ptr->req_info.param_flag & 0x02)	// subscriber state
			buf_len = add_null("2.1",0x80,&asn_buf);
	}
	return buf_len;
}

int extract_prvsubinfoarg(struct MapPSI_Arg *psi_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	psi_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);	// IMSI
	if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		psi_ptr->param_flag |= 0x01;
		memcpy(psi_ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	if (get_tlv("1",temp_buf,&asn_buf) == LMSI_LEN)	// lmsi
	{
		psi_ptr->param_flag |= 0x02;
		memcpy(psi_ptr->lmsi,temp_buf,LMSI_LEN);
	}
	if (get_tlv("2.0",temp_buf,&asn_buf) != -1)	// location info
	{
		psi_ptr->param_flag |= 0x04;
		psi_ptr->req_info.param_flag |= 0x01;
		psi_ptr->req_info.loc_info = 1;
	}
	if (get_tlv("2.1",temp_buf,&asn_buf) != -1)	// subscriber state
	{
		psi_ptr->param_flag |= 0x04;
		psi_ptr->req_info.param_flag |= 0x02;
		psi_ptr->req_info.sub_state = 1;
	}
	return ROK;
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding provider subscriber info response	*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_prvsubinfores(struct MapPSI_Res *psi_ptr,u8 *buf)
{
	int			buf_len=0;
	ASN_BUF		asn_buf;
	u_char		info_str[1024];

	if (psi_ptr->param_flag & 0x01)		// subscriber info
	{
		buf_len = assign_subinfo(&psi_ptr->sub_info,buf);
		memcpy(info_str,buf,buf_len%1024);
		AsnEncode(buf,256,&asn_buf);
		buf_len = AddTLV("16",buf_len,info_str,0x20,&asn_buf);
	}
	else
		return RER;
	return buf_len;
}

int extract_prvsubinfores(struct MapPSI_Res *psi_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];
	int			len;

	psi_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if ((len = get_tlv("16",temp_buf,&asn_buf)) <= 0)
	{
		return RER;
	}
	return extract_subinfo(&psi_ptr->sub_info,len,temp_buf);
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding any time interrogation argument	*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_anytimeintarg(struct MapATI_Arg *ati_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			len;

	asn_encode(buf,&asn_buf);
	if (ati_ptr->param_flag & 0x01)	// subscriber ideentity
	{
		if (ati_ptr->sub_ident.choice_flag == 1)	// IMSI
			buf_len = add_tlv("0.0",IMSI_LEN,ati_ptr->sub_ident.choice.imsi,0x80,&asn_buf);
		else if (ati_ptr->sub_ident.choice_flag == 2)	// msisdn
		{
			len = ati_ptr->sub_ident.choice.msisdn[0];
			buf_len = add_tlv("0.1",len,ati_ptr->sub_ident.choice.msisdn+1,0x80,&asn_buf);			
		}
	}
	else
		return RER;
	if (ati_ptr->param_flag & 0x02)	// request info
	{
		if (ati_ptr->req_info.param_flag & 0x01)	// location info
			buf_len = add_null("1.0",0x80,&asn_buf);
		if (ati_ptr->req_info.param_flag & 0x02)	// subscriber state
			buf_len = add_null("1.1",0x80,&asn_buf);
	    if (ati_ptr->req_info.param_flag & 0x04)        // current location
	        buf_len = add_null("1.3",0x80,&asn_buf);
	    if (ati_ptr->req_info.param_flag & 0x08)        // requested domain
	        buf_len = add_null("1.4",0x80,&asn_buf);
	    if (ati_ptr->req_info.param_flag & 0x10)        // imei
	        buf_len = add_null("1.6",0x80,&asn_buf);
	    if (ati_ptr->req_info.param_flag & 0x20)        // ms classmark
	        buf_len = add_null("1.5",0x80,&asn_buf);
	    if (ati_ptr->req_info.param_flag & 0x40)        // mnp requested info
	        buf_len = add_null("1.7",0x80,&asn_buf);
	}
	else
		return RER;
	if (ati_ptr->param_flag & 0x04)	// scf address
		buf_len = add_tlv("3",ati_ptr->scf_add[0],ati_ptr->scf_add+1,0x80,&asn_buf);
	else
		return RER;
	return buf_len;
}

int extract_anytimeintarg(struct MapATI_Arg *ati_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	ati_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if (get_tlv("0",temp_buf,&asn_buf) != -1)
	{
		ati_ptr->param_flag |= 0x01;
		len = get_tlv("0.0",temp_buf,&asn_buf);		// IMSI
		if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
		{
			ati_ptr->sub_ident.choice_flag = 0x01;
			memcpy(ati_ptr->sub_ident.choice.imsi,temp_buf,IMSI_LEN);
		}
		else
		{
			len = get_tlv("0.1",temp_buf,&asn_buf);		// msisdn
			if (len > 0 && len <= ISDN_LEN)
			{
				ati_ptr->sub_ident.choice_flag = 0x02;
				ati_ptr->sub_ident.choice.msisdn[0] = len;
				memcpy(ati_ptr->sub_ident.choice.msisdn+1,temp_buf,len);
			}
			else
				return RER;
		}
	}
	else
		return RER;
	if (get_tlv("1",temp_buf,&asn_buf) != -1)
	{
		if (get_tlv("1.0",temp_buf,&asn_buf) != -1)	// location info
		{
			ati_ptr->param_flag |= 0x02;
			ati_ptr->req_info.param_flag |= 0x01;
			ati_ptr->req_info.loc_info = 1;
		}
		if (get_tlv("1.1",temp_buf,&asn_buf) != -1)	// subscriber state
		{
			ati_ptr->param_flag |= 0x02;
			ati_ptr->req_info.param_flag |= 0x02;
			ati_ptr->req_info.sub_state = 1;
		}
        if (get_tlv("1.3",temp_buf,&asn_buf) != -1) // current location
		{
		    ati_ptr->param_flag |= 0x02;
		    ati_ptr->req_info.param_flag |= 0x04;
		    ati_ptr->req_info.cur_location = 1;
		}
	    if (get_tlv("1.4",temp_buf,&asn_buf) != -1) // requested domain
		{
		    ati_ptr->param_flag |= 0x02;
		    ati_ptr->req_info.param_flag |= 0x08;
		    ati_ptr->req_info.req_domain= 1;
		}
		if (get_tlv("1.6",temp_buf,&asn_buf) != -1) // imei
		{
		    ati_ptr->param_flag |= 0x02;
		    ati_ptr->req_info.param_flag |= 0x10;
		    ati_ptr->req_info.imei = 1;
		}
		if (get_tlv("1.5",temp_buf,&asn_buf) != -1) // ms classmark
		{
		    ati_ptr->param_flag |= 0x02;
		    ati_ptr->req_info.param_flag |= 0x20;
		    ati_ptr->req_info.ms_classmark = 1;
		}
		if (get_tlv("1.7",temp_buf,&asn_buf) != -1) // mnp requested info
		{
		    ati_ptr->param_flag |= 0x02;
		    ati_ptr->req_info.param_flag |= 0x40;
		    ati_ptr->req_info.mnp_req_info = 1;
		}
	}
	else 
		return RER;
	len = get_tlv("3",temp_buf,&asn_buf);
	if (len > 0 && len <= ISDN_LEN)
	{
		ati_ptr->param_flag |= 0x04;
		ati_ptr->scf_add[0] = len;
		memcpy(ati_ptr->scf_add+1,temp_buf,len);
	}
	return ROK;
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding any time interrogate response		*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_anytimeintres(struct MapATI_Res *ati_ptr,u8 *buf)
{
	int			buf_len=0;
	ASN_BUF		asn_buf;
	u_char		info_str[1024];

	if (ati_ptr->param_flag & 0x01)		// subscriber info
	{
		buf_len = assign_subinfo(&ati_ptr->sub_info,buf);
		memcpy(info_str,buf,buf_len%1024);
		AsnEncode(buf,256,&asn_buf);
		buf_len = AddTLV("16",buf_len,info_str,0x20,&asn_buf);
	}
	else
		return RER;
	return buf_len;
}

int extract_anytimeintres(struct MapATI_Res *ati_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];
	int			len;

	ati_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;

	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if ((len = get_tlv("16",temp_buf,&asn_buf)) <= 0)
	{
		return RER;
	}
	ati_ptr->param_flag = 1;
	return extract_subinfo(&ati_ptr->sub_info,len,temp_buf);
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding any time subscription interrogation argument	*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_anytimesubintarg(struct MapATSI_Arg *atsi_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			len;

	asn_encode(buf,&asn_buf);
	if (atsi_ptr->param_flag & 0x01)	// subscriber ideentity
	{
		if (atsi_ptr->sub_ident.choice_flag == 1)	// IMSI
			buf_len = add_tlv("0.0",IMSI_LEN,atsi_ptr->sub_ident.choice.imsi,0x80,&asn_buf);
		else if (atsi_ptr->sub_ident.choice_flag == 2)	// msisdn
		{
			len = atsi_ptr->sub_ident.choice.msisdn[0];
			buf_len = add_tlv("0.1",len,atsi_ptr->sub_ident.choice.msisdn+1,0x80,&asn_buf);			
		}
	}
	else
		return RER;
	return buf_len;
}

int extract_anytimesubintarg(struct MapATSI_Arg *atsi_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	atsi_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if (get_tlv("0",temp_buf,&asn_buf) != -1)
	{
		atsi_ptr->param_flag |= 0x01;
		len = get_tlv("0.0",temp_buf,&asn_buf);		// IMSI
		if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
		{
			atsi_ptr->sub_ident.choice_flag = 0x01;
			memcpy(atsi_ptr->sub_ident.choice.imsi,temp_buf,IMSI_LEN);
		}
		else
		{
			len = get_tlv("0.1",temp_buf,&asn_buf);		// msisdn
			if (len > 0 && len <= ISDN_LEN)
			{
				atsi_ptr->sub_ident.choice_flag = 0x02;
				atsi_ptr->sub_ident.choice.msisdn[0] = len;
				memcpy(atsi_ptr->sub_ident.choice.msisdn+1,temp_buf,len);
			}
			else
				return RER;
		}
	}
	else
		return RER;
	return ROK;
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding any time interrogate response		*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_anytimesubintres(struct MapATSI_Res *atsi_ptr,u8 *buf)
{
	int			buf_len=0;
	ASN_BUF		asn_buf;
	//char		info_str[1024];
	char	       tlv1[32];
	
	AsnEncode(buf,256,&asn_buf);

	if (atsi_ptr->param_flag & 0x01)
	{
		sprintf(tlv1,"4.%d",10);
		buf_len = assign_smscsi(tlv1,&atsi_ptr->subs_info.sms_csi,&asn_buf);
	}
	else
		return RER;
	return buf_len;
}

int extract_anytimesubintres(struct MapATSI_Res *atsi_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];
	int			len;
	char			tlv1[32];

	atsi_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if ((len = get_tlv("4",temp_buf,&asn_buf)) <= 0)
	{
		return RER;
	}
	atsi_ptr->param_flag = 1;
	sprintf(tlv1, "4.%d", 10);
	return extract_smscsi(tlv1, &atsi_ptr->subs_info.sms_csi, &asn_buf);
}

/*	++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding prepare handover argument		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_prehoarg(struct MapPHO_Arg *pho_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			temp_len;
	u8			temp_buf[256];

	asn_encode(buf,&asn_buf);
	if (pho_ptr->param_flag & 0x01)		// target cell id
		buf_len = add_tlv("4",GCID_LEN,pho_ptr->target_id,0x00,&asn_buf);
	if (pho_ptr->param_flag & 0x02)		// ho number not required
		buf_len = add_null("5",0x00,&asn_buf);
	if (pho_ptr->param_flag & 0x04)		// bss apdu
	{
		temp_len = assign_extsiginfo(&pho_ptr->bss_apdu,temp_buf);
		buf_len = add_tlv("16",temp_len,temp_buf,0x20,&asn_buf);
	}
	return buf_len;
}

int extract_prehoarg(struct MapPHO_Arg *pho_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	pho_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if (get_tlv("4",temp_buf,&asn_buf) == GCID_LEN)	// target cell id
	{
		pho_ptr->param_flag |= 0x01;
		memcpy(pho_ptr->target_id,temp_buf,GCID_LEN);
	}
	if (get_tlv("5",temp_buf,&asn_buf) != -1)	// ho number not required
	{
		pho_ptr->param_flag |= 0x02;
		pho_ptr->numnot_require = 1;
	}
	len = get_tlv("16",temp_buf,&asn_buf);	// bss apdu
	if (len != -1)
	{
		if (!extract_extsiginfo(&pho_ptr->bss_apdu,len,temp_buf))
			return RER;
		pho_ptr->param_flag |= 0x04;
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding prepare handover response		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_prehores(struct MapPHO_Res *pho_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			temp_len;
	u8			temp_buf[256];

	asn_encode(buf,&asn_buf);
	if (pho_ptr->param_flag & 0x01)		// handover number
		buf_len = add_tlv("4",pho_ptr->ho_num[0],pho_ptr->ho_num+1,0x00,&asn_buf);
	if (pho_ptr->param_flag & 0x02)		// bss apdu
	{
		temp_len = assign_extsiginfo(&pho_ptr->bss_apdu,temp_buf);
		buf_len = add_tlv("16",temp_len,temp_buf,0x20,&asn_buf);
	}
	return buf_len;
}

int extract_prehores(struct MapPHO_Res *pho_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	pho_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("4",temp_buf,&asn_buf);
	if (len > 0 && len <= ISDN_LEN)	// handover number
	{
		pho_ptr->param_flag |= 0x01;
		pho_ptr->ho_num[0] = len;
		memcpy(pho_ptr->ho_num+1,temp_buf,len);
	}
	len = get_tlv("16",temp_buf,&asn_buf);	// bss apdu
	if (len != -1)
	{
		if (!extract_extsiginfo(&pho_ptr->bss_apdu,len,temp_buf))
			return RER;
		pho_ptr->param_flag |= 0x02;
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send end signal argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++	*/
int assign_sndendsigarg(struct MapSES_Arg *ses_ptr,u8 *buf)
{

	if (ses_ptr->param_flag |= 0x01)	// bss apdu
		return assign_extsiginfo(&ses_ptr->bss_apdu,buf);
	else
		return RER;
}

int extract_sndendsigarg(struct MapSES_Arg *ses_ptr,u32 buf_len,u8 *buf)
{
	if (extract_extsiginfo(&ses_ptr->bss_apdu,buf_len,buf))
	{
		ses_ptr->param_flag = 0x01;
		return ROK;
	}
	else
		return RER;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding process access signalling argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_prcaccsigarg(struct MapPAS_Arg *pas_ptr,u8 *buf)
{

	if (pas_ptr->param_flag |= 0x01)	// bss apdu
		return assign_extsiginfo(&pas_ptr->bss_apdu,buf);
	else
		return RER;
}

int extract_prcaccsigarg(struct MapPAS_Arg *pas_ptr,u32 buf_len,u8 *buf)
{
	if (extract_extsiginfo(&pas_ptr->bss_apdu,buf_len,buf))
	{
		pas_ptr->param_flag = 0x01;
		return ROK;
	}
	else
		return RER;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding forward access signalling argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_fwdaccsigarg(struct MapFAS_Arg *fas_ptr,u8 *buf)
{

	if (fas_ptr->param_flag |= 0x01)	// bss apdu
		return assign_extsiginfo(&fas_ptr->bss_apdu,buf);
	else
		return RER;
}

int extract_fwdaccsigarg(struct MapFAS_Arg *fas_ptr,u32 buf_len,u8 *buf)
{
	if (extract_extsiginfo(&fas_ptr->bss_apdu,buf_len,buf))
	{
		fas_ptr->param_flag = 0x01;
		return ROK;
	}
	else
		return RER;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding prepare subsequent handover argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_presubshoarg(struct MapPSHO_Arg *psho_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			temp_len;
	u8			temp_buf[256];

	asn_encode(buf,&asn_buf);
	if (psho_ptr->param_flag & 0x01)	// target cell id
		buf_len = add_tlv("4-1",GCID_LEN,psho_ptr->target_id,0x00,&asn_buf);
	else
		return RER;
	if (psho_ptr->param_flag & 0x02)	// target msc number
		buf_len = add_tlv("4-2",psho_ptr->msc_num[0],psho_ptr->msc_num+1,0x00,&asn_buf);
	else
		return RER;
	if (psho_ptr->param_flag & 0x04)		// bss apdu
	{
		temp_len = assign_extsiginfo(&psho_ptr->bss_apdu,temp_buf);
		buf_len = add_tlv("16",temp_len,temp_buf,0x20,&asn_buf);
	}
	else
		return RER;
	return buf_len;
}

int extract_presubshoarg(struct MapPSHO_Arg *psho_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];

	psho_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if (get_tlv("4-1",temp_buf,&asn_buf) == GCID_LEN)	// target cell id
	{
		psho_ptr->param_flag |= 0x01;
		memcpy(psho_ptr->target_id,temp_buf,GCID_LEN);
	}
	else
		return RER;
	len = get_tlv("4-2",temp_buf,&asn_buf);		// target msc number
	if (len > 0 && len <= ISDN_LEN)
	{
		psho_ptr->param_flag |= 0x02;
		psho_ptr->msc_num[0] = len;
		memcpy(psho_ptr->msc_num+1,temp_buf,len);
	}
	len = get_tlv("16",temp_buf,&asn_buf);	// bss apdu
	if (len != -1)
	{
		if (!extract_extsiginfo(&psho_ptr->bss_apdu,len,temp_buf))
			return RER;
		psho_ptr->param_flag |= 0x04;
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding prepare subsequent handover response	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_presubshores(struct MapPSHO_Res *psho_ptr,u8 *buf)
{

	if (psho_ptr->param_flag |= 0x01)	// bss apdu
		return assign_extsiginfo(&psho_ptr->bss_apdu,buf);
	else
		return RER;
}

int extract_presubshores(struct MapPSHO_Res *psho_ptr,u32 buf_len,u8 *buf)
{
	if (extract_extsiginfo(&psho_ptr->bss_apdu,buf_len,buf))
	{
		psho_ptr->param_flag = 0x01;
		return ROK;
	}
	else
		return RER;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send Authentiction Info argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_sndauthinfoarg(struct MapSAI_Arg *sai_ptr,u8 *buf, u8 version)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	int			temp_len;
	u8			temp_buf[256];
	u8			tag1 = 1;
	char			tlv2[8];
	
	asn_encode(buf, &asn_buf);

	if(version == AC_Version3)		//add by gxchen
	{
		sprintf(tlv2, "0-%d", tag1++);
		if(sai_ptr->param_flag & 0x01)
			buf_len = add_tlv(tlv2, IMSI_LEN, sai_ptr->imsi, 0x80, &asn_buf);
		else
		{
			mapp_log_debug("version_4 assign sndauthinfo lack IMSI");
			return RER;
		}
		sprintf(tlv2, "2-%d", tag1++);
		if(sai_ptr->param_flag & 0x02)
			buf_len = add_tlv(tlv2, 1, &sai_ptr->num_req_vec, 0x00, &asn_buf);
		else
		{
			mapp_log_debug("version_4 assign sndauthinfo lack numberOfRequestedVectors");
			return RER;
		}
		sprintf(tlv2, "5-%d", tag1++);
		if(sai_ptr->param_flag & 0x04)
			buf_len = add_tlv(tlv2, 1, &sai_ptr->seg_prohibit, 0x00, &asn_buf);
		sprintf(tlv2, "1-%d", tag1++);
		if(sai_ptr->param_flag & 0x08)
			buf_len = add_tlv(tlv2, 1, &sai_ptr->imm_res_prefer, 0x80, &asn_buf);
		sprintf(tlv2, "16");
		if(sai_ptr->param_flag & 0x10)
		{
			temp_len = assign_authReSynInfo(&sai_ptr->resyn_info, temp_buf);
			if(temp_len != RER)
				buf_len = add_tlv(tlv2, temp_len, temp_buf, 0x20, &asn_buf);
		}
		sprintf(tlv2, "3-%d", tag1++);
		if(sai_ptr->param_flag & 0x20)
		{
			temp_buf[0] = sai_ptr->node_type;
			buf_len = add_tlv(tlv2, 1, temp_buf, 0x80, &asn_buf);
		}
		sprintf(tlv2, "4-%d", tag1++);
		if(sai_ptr->param_flag & 0x40)
			buf_len = add_tlv(tlv2, 3, sai_ptr->req_plmn_id, 0x80, &asn_buf);
		sprintf(tlv2, "5-%d", tag1++);
		if(sai_ptr->param_flag & 0x80)
			buf_len = add_tlv(tlv2, 1, &sai_ptr->num_req_add_vec, 0x80, &asn_buf);
		sprintf(tlv2, "6-%d", tag1++);
		if(sai_ptr->param_flag & 0x100)
			buf_len = add_tlv(tlv2, 1, &sai_ptr->add_vec_eps, 0x80, &asn_buf);
	}
	else
	{
		if (sai_ptr->param_flag & 0x01)		// has IMSI
			buf_len = add_tlv("4",IMSI_LEN,sai_ptr->imsi,0x00,&asn_buf);
		else
		{
			mapp_log_debug("assign sndauthinfo lack IMSI");
			return RER;
		}
	}
	
	return buf_len;
}

int extract_sndauthinfoarg(struct MapSAI_Arg *sai_ptr,u32 buf_len,u8 *buf, u8 version)
{
	ASN_BUF		asn_buf;
	int			len=0;
	u8			temp_buf[256];
	u8			tag1 = 1;
	char			tlv2[8];

	sai_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	if(version == AC_Version3)		//add by gxchen
	{
		sprintf(tlv2, "0-%d", tag1++);
		len = get_tlv(tlv2, temp_buf, &asn_buf);
		if(len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
		{
			sai_ptr->param_flag |= 0x01;
			memcpy(sai_ptr->imsi, temp_buf, len);
		}
		else
		{
			mapp_log_debug("extract_sndauthinfoarg version_4 lack IMSI");
			return RER;
		}
		sprintf(tlv2, "2-%d", tag1++);
		if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
		{
			sai_ptr->param_flag |= 0x02;
			sai_ptr->num_req_vec = temp_buf[0];
		}
		else
		{
			mapp_log_debug("extract_sndauthinfoarg version_4 lack numberOfRequestedVectors");
//			return RER;
		}
		sprintf(tlv2, "5-%d", tag1++);
		if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
		{
			sai_ptr->param_flag |= 0x04;
			sai_ptr->seg_prohibit = temp_buf[0];
		}
		sprintf(tlv2, "1-%d", tag1++);
		if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
		{
			sai_ptr->param_flag |= 0x08;
			sai_ptr->imm_res_prefer = temp_buf[0];
		}
		sprintf(tlv2, "16");
		if((len = get_tlv(tlv2, temp_buf, &asn_buf)) > 0)
		{
			sai_ptr->param_flag |= 0x10;
			extract_authReSynInfo(&sai_ptr->resyn_info, len, temp_buf);
		}
		sprintf(tlv2, "3-%d", tag1++);
		if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
		{
			sai_ptr->param_flag |= 0x20;
			sai_ptr->node_type = temp_buf[0];
		}
		sprintf(tlv2, "4-%d", tag1++);
		if(get_tlv(tlv2, temp_buf, &asn_buf) > 0)
		{
			sai_ptr->param_flag |= 0x40;
			memcpy(sai_ptr->req_plmn_id, temp_buf, 3);
		}
		sprintf(tlv2, "5-%d", tag1++);
		if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
		{
			sai_ptr->param_flag |= 0x80;
			sai_ptr->num_req_add_vec = temp_buf[0];
		}
		sprintf(tlv2, "6-%d", tag1++);
		if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
		{
			sai_ptr->param_flag |= 0x100;
			sai_ptr->add_vec_eps = temp_buf[0];
		}
	}
	else
	{
		len = get_tlv("4",temp_buf,&asn_buf);
		if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
		{
			sai_ptr->param_flag = 0x01;
			memcpy(sai_ptr->imsi,temp_buf,len);
		}
		else
		{
			mapp_log_debug("extract_sndauthinfoarg lack IMSI");
			return RER;
		}
	}
	
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send Authentiction Info response	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_sndauthinfores(struct MapSAI_Res *sai_ptr,u8 *buf, u8 version)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u8			ii=0;
	int			temp_len;
	u8			temp_buf[256];
	char			tlv2[32];
	
	asn_encode(buf,&asn_buf);
	if(version == AC_Version3)		//add by gxchen	if(sai_ptr->choice_flag == AUTH_UMTS)
	{
		if(sai_ptr->param_flag & 0x01)
		{
			if(sai_ptr->choice.umts.authlist.choice_flag == AUTH_LIST_QUINTUPLET)
			{
				sprintf(tlv2, "1");
//				buf_len = add_tlv(tlv2, temp_len, temp_buf, 0xa0, &asn_buf);
				buf_len = add_null(tlv2, 0xa0, &asn_buf);
				for(ii = 0; ii < sai_ptr->choice.umts.authlist.choice.quin_list.quin_len; ii ++)
				{
					temp_len = assign_quintuplet(&sai_ptr->choice.umts.authlist.choice.quin_list.quintuplet[ii], temp_buf);
					if(temp_len == RER)
						break;
					sprintf(tlv2, "1.16-%d", ii+1);
					buf_len = add_tlv(tlv2, temp_len, temp_buf, 0x20, &asn_buf);
				}
			}
			else
			{
				sprintf(tlv2, "0");
//				buf_len = add_tlv(tlv2, temp_len, temp_buf, 0xa0, &asn_buf);
				buf_len = add_null(tlv2, 0xa0, &asn_buf);
				for(ii = 0; ii < sai_ptr->choice.umts.authlist.choice.tri_list.tri_len; ii++)
				{
					temp_len = assign_triplet(&sai_ptr->choice.umts.authlist.choice.tri_list.triplet[ii], temp_buf);
					if(temp_len == RER)
						break;
					sprintf(tlv2, "0.16-%d", ii+1);
					buf_len = add_tlv(tlv2, temp_len, temp_buf, 0x20, &asn_buf);
				}
			}
		}
	}
	else
	{
		if (sai_ptr->param_flag & 0x01)	// has authenticate data
		{
			for (ii = 0;ii < sai_ptr->choice.gsm.authlist.auth_len;ii++)
			{
				temp_len = assign_authset(&sai_ptr->choice.gsm.authlist.auth_set[ii],temp_buf);
				if (temp_len == RER)
					break;
				sprintf(tlv2,"16-%d",ii+1);
				buf_len = add_tlv(tlv2,temp_len,temp_buf,0x20,&asn_buf);
			}
		}
	}
	
	return buf_len;
}

int extract_sndauthinfores(struct MapSAI_Res *sai_ptr,u32 buf_len,u8 *buf, u8 version)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	u8			ii;
	char			tlv2[32];

//	sai_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_sndauthinfores buf_len=0");
		return RER;
	}	
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	
	if(version == AC_Version3)		//add by gxchen
	{
		sai_ptr->choice_flag = AUTH_UMTS;
		sai_ptr->param_flag = 0;
		if((len = get_tlv("1", temp_buf, &asn_buf)) > 0)	//quintuplet
		{
			sai_ptr->param_flag |= 0x01;
			sai_ptr->choice.umts.authlist.choice_flag = AUTH_LIST_QUINTUPLET;
			sai_ptr->choice.umts.authlist.choice.quin_list.quin_len = 0;
			for(ii = 0; ii < AUTHLIST_LEN; ii++)
			{
				sai_ptr->choice.umts.authlist.choice.quin_list.quintuplet[ii].param_flag = 0;
				sprintf(tlv2, "1.16-%d", ii+1);
				len = get_tlv(tlv2, temp_buf, &asn_buf);
				if(len <= 0)	//has not data
					break;
				if(!extract_quintuplet(&sai_ptr->choice.umts.authlist.choice.quin_list.quintuplet[ii], len, temp_buf))
					break;
				sai_ptr->choice.umts.authlist.choice.quin_list.quin_len++;
			}
		}
		else if((len = get_tlv("0", temp_buf, &asn_buf)) > 0)	//triplet
		{
			sai_ptr->param_flag |= 0x01;
			sai_ptr->choice.umts.authlist.choice_flag = AUTH_LIST_TRIPLET;
			sai_ptr->choice.umts.authlist.choice.tri_list.tri_len = 0;
			for(ii = 0; ii < AUTHLIST_LEN; ii++)
			{
				sai_ptr->choice.umts.authlist.choice.tri_list.triplet[ii].param_flag = 0;
				sprintf(tlv2, "0.16-%d", ii+1);
				len = get_tlv(tlv2, temp_buf, &asn_buf);
				if(len <= 0)	//has not data
					break;
				if(!extract_triplet(&sai_ptr->choice.umts.authlist.choice.tri_list.triplet[ii], len, temp_buf))
					break;
				sai_ptr->choice.umts.authlist.choice.tri_list.tri_len++;
			}
		}
	}
	else
	{
		sai_ptr->choice_flag = AUTH_GSM;
		sai_ptr->param_flag = 0;
		sai_ptr->choice.gsm.authlist.auth_len = 0;
		for (ii = 0;ii < AUTHLIST_LEN;ii++)
		{
			sai_ptr->choice.gsm.authlist.auth_set[ii].param_flag = 0;
			sprintf(tlv2,"16-%d",ii+1);
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len <= 0)	// has not data
				break;
			if (!extract_authset(&sai_ptr->choice.gsm.authlist.auth_set[ii],len,temp_buf))
				break;
			sai_ptr->param_flag = 0x01;
			sai_ptr->choice.gsm.authlist.auth_len++;
		}
	}
	
	return ROK;
}

//add by gxchen	start
/*	+++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding authentication failure report argument	*/
/*	+++++++++++++++++++++++++++++++++++++	*/
int assign_authfailreportarg(MapAuthFailReport_Arg *fail_ptr, u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u8			tag1 = 1;
	char			tlv2[8];
	
	asn_encode(buf, &asn_buf);
	sprintf(tlv2, "4-%d", tag1++);
	if(fail_ptr->param_flag & 0x01)
		buf_len = add_tlv(tlv2, IMSI_LEN, fail_ptr->imsi, 0x00, &asn_buf);
	else
	{
		mapp_log_debug("assign authfailreportarg lack IMSI");
		return RER;
	}
	sprintf(tlv2, "10-%d", tag1++);
	if(fail_ptr->param_flag & 0x02)
		buf_len = add_tlv(tlv2, 1, (u8*)&fail_ptr->cause, 0x00, &asn_buf);
	else
	{
		mapp_log_debug("version_4 assign authfailreportarg lack failureCause");
		return RER;
	}
	sprintf(tlv2, "1-%d", tag1++);
	if(fail_ptr->param_flag & 0x04)
		buf_len = add_tlv(tlv2, 1, &fail_ptr->reattemp, 0x00, &asn_buf);
	sprintf(tlv2, "10-%d", tag1++);
	if(fail_ptr->param_flag & 0x08)
		buf_len = add_tlv(tlv2, 1, (u8*)&fail_ptr->access_type, 0x00, &asn_buf);
	sprintf(tlv2, "4-%d", tag1++);
	if(fail_ptr->param_flag & 0x10)
		buf_len = add_tlv(tlv2, RAND_LEN, fail_ptr->rand, 0x00, &asn_buf);
	sprintf(tlv2, "0-%d", tag1++);
	if(fail_ptr->param_flag & 0x20)
		buf_len = add_tlv(tlv2, fail_ptr->vlr_num[0], fail_ptr->vlr_num+1, 0x80, &asn_buf);
	sprintf(tlv2, "1-%d", tag1++);
	if(fail_ptr->param_flag & 0x40)
		buf_len = add_tlv(tlv2, fail_ptr->sgsn_num[0], fail_ptr->sgsn_num+1, 0x80, &asn_buf);

	return buf_len;
}

int extract_authfailreportarg(MapAuthFailReport_Arg *fail_ptr, u32 buf_len, u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len=0;
	u8			temp_buf[256];
	u8			tag1 = 1;
	char			tlv2[8];

	fail_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	sprintf(tlv2, "4-%d", tag1++);
	len = get_tlv(tlv2, temp_buf, &asn_buf);
	if(len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		fail_ptr->param_flag |= 0x01;
		memcpy(fail_ptr->imsi, temp_buf, len);
	}
	else
	{
		mapp_log_debug("extract authfailreportarg lack IMSI");
		return RER;
	}
	sprintf(tlv2, "10-%d", tag1++);
	if(1 == get_tlv(tlv2, temp_buf, &asn_buf))
	{
		fail_ptr->param_flag |= 0x02;
		fail_ptr->cause = temp_buf[0];
	}
	sprintf(tlv2, "1-%d", tag1++);
	if(1 == get_tlv(tlv2, temp_buf, &asn_buf))
	{
		fail_ptr->param_flag |= 0x04;
		fail_ptr->reattemp = temp_buf[0];
	}
	sprintf(tlv2, "10-%d", tag1++);
	if(1 == get_tlv(tlv2, temp_buf, &asn_buf))
	{
		fail_ptr->param_flag |= 0x08;
		fail_ptr->access_type = temp_buf[0];
	}
	sprintf(tlv2, "4-%d", tag1++);
	if(RAND_LEN == (len = get_tlv(tlv2, temp_buf, &asn_buf)))
	{
		fail_ptr->param_flag |= 0x10;
		memcpy(fail_ptr->rand, temp_buf, len);
	}
	sprintf(tlv2, "0-%d", tag1++);
	if(2 < (len = get_tlv(tlv2, temp_buf, &asn_buf)))
	{
		fail_ptr->param_flag |= 0x20;
		fail_ptr->vlr_num[0] = len;
		memcpy(fail_ptr->vlr_num+1, temp_buf, len);
	}
	sprintf(tlv2, "1-%d", tag1++);
	if(2 < (len = get_tlv(tlv2, temp_buf, &asn_buf)))
	{
		fail_ptr->param_flag |= 0x40;
		fail_ptr->sgsn_num[0] = len;
		memcpy(fail_ptr->sgsn_num+1, temp_buf, len);
	}

	return ROK;
}

/*	+++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding authentication failure report response	*/
/*	+++++++++++++++++++++++++++++++++++++	*/
/*int assign_authfailreportres(MapAuthFailReport_Res *fail_ptr, u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	
	asn_encode(buf, &asn_buf);
	if(fail_ptr->param_flag & 0x01)
		buf_len = add_tlv("10-1", 1, (u8*)&fail_ptr->error, 0x00, &asn_buf);

	return buf_len;
}

int extract_authfailreportres(MapAuthFailReport_Res *fail_ptr, u32 buf_len, u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];

	fail_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;	//maybe	RER
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;

	if(1 == get_tlv("10-1", temp_buf, &asn_buf))
	{
		fail_ptr->param_flag |= 0x01;
		fail_ptr->error = temp_buf[0];
	}

	return ROK;
}*/
//add by gxchen	end

/*	+++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding check IMEI argument	*/
/*	+++++++++++++++++++++++++++++++++++++	*/
int assign_chkimeiarg(struct MapCIMEI_Arg *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u32			flag;
	
	flag = ptr->param_flag;
	asn_encode(buf,&asn_buf);
	if(flag & 0x01)		//imei
		buf_len = add_tlv("4",IMEI_LEN,ptr->imei,0x00,&asn_buf);
	return buf_len;
}

int extract_chkimeiarg(struct MapCIMEI_Arg *ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF	asn_buf;
	u8		temp_buf[256];

	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_chkimeiarg buf_len=0");
		return RER;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	ptr->param_flag = 0;
	if((get_tlv("4",temp_buf,&asn_buf)) != IMEI_LEN)		//imei
		return RER;
	ptr->param_flag |= 0x01;
	memcpy(ptr->imei,temp_buf,IMEI_LEN);
	return ROK;
}

/*	+++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding check IMEI response	*/
/*	+++++++++++++++++++++++++++++++++++++	*/
int assign_chkimeires(struct MapCIMEI_Res *ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u8			data;
	
	asn_encode(buf,&asn_buf);
	if(ptr->param_flag & 0x01)
	{
		data = ptr->equip_status;
		buf_len = add_tlv("10",1,&data,0x00,&asn_buf);
	}
	return buf_len;
}

int extract_chkimeires(struct MapCIMEI_Res *ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF	asn_buf;
	u8		temp_buf[256];

	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_chkimeires buf_len=0");
		return RER;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;	
	ptr->param_flag = 0;
	if(get_tlv("10",temp_buf,&asn_buf) != 1)
		return RER;
	ptr->param_flag |= 0x01;
	ptr->equip_status = temp_buf[0];
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding insert subscribe Data argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_inssubdataarg(struct MapISD_Arg *isd_ptr,u8 *buf,u8 version)
{
	ASN_BUF		asn_buf;
	int			jj,kk;
	u32			flag1;
	u32			flag;
	u32			len;
	int			buf_len=0;
	int			temp_len;
	u8			temp_data[256],temp_buf[256];
	u8			tag1=1,tag2=1,tag3=1,tag4=1,tag5=1;
	char		tlv1[32],tlv2[32],tlv3[32],tlv4[32],tlv5[32];
	struct 		ExtFwdInfo_struct		*fwd_ptr;
	struct		ExtSsData_struct		*ss_ptr;
	struct		ExtCallBarInfo_struct	*callbar_ptr;
	struct		EmlppInfo_struct	*emlpp_ptr;
	struct		PdpContext_struct		*pdp_ptr;
	
	asn_encode(buf,&asn_buf);
	flag = isd_ptr->param_flag;
	if (flag & 0x01)	// IMSI
	{
		sprintf(tlv1,"0-%d",tag1++);
		buf_len = add_tlv(tlv1,IMSI_LEN,isd_ptr->imsi,0x80,&asn_buf);
	}
	if (flag & 0x02)	// MSISDN
	{
		sprintf(tlv1,"1-%d",tag1++);
		buf_len = add_tlv(tlv1,isd_ptr->msisdn[0],isd_ptr->msisdn+1,0x80,&asn_buf);
	}
	if (flag & 0x04)	// category
	{
		sprintf(tlv1,"2-%d",tag1++);
		buf_len = add_tlv(tlv1,1,&isd_ptr->category,0x80,&asn_buf);
	}
	if (flag & 0x08)	// sub status
	{
		sprintf(tlv1,"3-%d",tag1++);
		temp_data[0] = isd_ptr->sub_status;
		buf_len = add_tlv(tlv1,1,temp_data,0x80,&asn_buf);
	}
	if (flag & 0x20)	// bearer service list
	{
		temp_len = bearer_bittostr(isd_ptr->bearer_data,temp_data,0);

		if(temp_len > 0)
		{
			sprintf(tlv1,"4-%d",tag1++);

			for (jj = 0;jj < temp_len;jj ++)
			{
				sprintf(tlv2,"%s.4-%d",tlv1,jj+1);
				buf_len = add_tlv(tlv2,1,temp_data+jj,0x00,&asn_buf);
			}
		}
	}
	if (flag & 0x40)	// tele service list
	{
		temp_len = tele_bittostr(isd_ptr->tele_data,temp_data,0);
		if(temp_len > 0)
		{
			sprintf(tlv1,"6-%d",tag1++);
			for (jj = 0;jj < temp_len;jj++)
			{
				sprintf(tlv2,"%s.4-%d",tlv1,jj+1);
				buf_len = add_tlv(tlv2,1,temp_data+jj,0x00,&asn_buf);
			}
		}
	}
	if (flag & 0x80)	// ss info list	
	{
		sprintf(tlv1,"7-%d",tag1++);
		tag2 = 1;
		if (isd_ptr->ss_info.param_flag & 0x01)	// fwd info
		{
			fwd_ptr = (ExtFwdInfo_struct *) &isd_ptr->ss_info.fwd_info;
			for (jj = 0;jj < 4;jj ++)	//tag2
			{
				tag3 = 1;
				kk = 0x01 << jj;
				if (fwd_ptr->param_flag & kk)
				{
					sprintf(tlv2,"%s.0-%d",tlv1,tag2++);
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);	// for ss_code
					buf_len = add_tlv(tlv3,1,&fwd_ptr->ss_code[jj],0x00,&asn_buf);
					sprintf(tlv3,"%s.16-%d",tlv2,tag3++);
					add_null(tlv3,0x20,&asn_buf);
					tag4 = 1;
					sprintf(tlv4,"%s.16-%d",tlv3,tag4);
					add_null(tlv4,0x20,&asn_buf);
					tag5 = 1;
					flag1 = fwd_ptr->fwd_feat[jj].param_flag;
					if (flag1 & 0x01) // bs group
					{
						if (fwd_ptr->fwd_feat[jj].bs_code.param_flag == 1)
						{
							sprintf(tlv5,"%s.2-%d",tlv4,tag5++);
							if (tele_bittostr(fwd_ptr->fwd_feat[jj].bs_code.tele_code,temp_data,1))
								buf_len = add_tlv(tlv5,1,temp_data,0x80,&asn_buf);
						}
						else if(fwd_ptr->fwd_feat[jj].bs_code.param_flag  == 2)
						{
							sprintf(tlv5,"%s.3-%d",tlv4,tag5++);
							if (bearer_bittostr(fwd_ptr->fwd_feat[jj].bs_code.bearer_code,temp_data,1))
								buf_len = add_tlv(tlv5,1,temp_data,0x80,&asn_buf);
						}
					}
					if (flag1 & 0x02)	//ss status
					{
						sprintf(tlv5,"%s.4-%d",tlv4,tag5++);
						buf_len = add_tlv(tlv5,1,&fwd_ptr->fwd_feat[jj].ss_status,0x80,&asn_buf);
					}
					if (flag1 & 0x04) //fwdto_num
					{
						sprintf(tlv5,"%s.5-%d",tlv4,tag5++);
						len = fwd_ptr->fwd_feat[jj].fwdto_num[0];
						buf_len = add_tlv(tlv5,len,fwd_ptr->fwd_feat[jj].fwdto_num+1,0x80,&asn_buf);
					}
					if (flag1 &0x08) //fwd opt
					{
						sprintf(tlv5,"%s.6-%d",tlv4,tag5++);
						buf_len = add_tlv(tlv5,1,&fwd_ptr->fwd_feat[jj].fwd_option,0x80,&asn_buf);
					}
					if (flag1 &0x10) //norc time
					{
						sprintf(tlv5,"%s.7-%d",tlv4,tag5++);
						buf_len = add_tlv(tlv5,1,&fwd_ptr->fwd_feat[jj].norc_time,0x80,&asn_buf);
					}		  	
				}							
			}
		}
		if (isd_ptr->ss_info.param_flag & 0x02) // call bar info
		{
			int mm=0, nn;
			callbar_ptr = (ExtCallBarInfo_struct *) &isd_ptr->ss_info.call_info;
			for (jj = 0;jj < 5;jj ++)
			{
				kk = 0x01 << jj;
				if ((callbar_ptr->param_flag & kk) != 0)
				{
					sprintf(tlv2,"%s.1-%d",tlv1,tag2++);
					tag3 = 1;
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);
					buf_len = add_tlv(tlv3,1,&callbar_ptr->ss_code[jj],0x00,&asn_buf);
					sprintf(tlv3,"%s.16-%d",tlv2,tag3++);
					add_null(tlv3,0x20,&asn_buf);
					tag4 = 1;
					for(mm=0;mm<5;mm++)
					{						
						nn = 0x01<< mm;
						if (!(callbar_ptr->bar_list[jj].param_flag & nn))
							continue;
						
						sprintf(tlv4,"%s.16-%d",tlv3,tag4);
						add_null(tlv4,0x20,&asn_buf);
						tag5 = 1;

						if (callbar_ptr->bar_list[jj].bs_code[mm].param_flag == 1)
						{
							sprintf(tlv5,"%s.3-%d",tlv4,tag5++);
							buf_len = add_int(tlv5,callbar_ptr->bar_list[jj].bs_code[mm].tele_code,0x80,&asn_buf);
						}
						else// if(callbar_ptr->bar_list[jj].bs_code[mm].param_flag == 2)
						{
							sprintf(tlv5,"%s.2-%d",tlv4,tag5++);							
							buf_len = add_int(tlv5,callbar_ptr->bar_list[jj].bs_code[mm].bearer_code,0x80,&asn_buf);
						}
						
						sprintf(tlv5,"%s.4-%d",tlv4,tag5++);
						buf_len = add_tlv(tlv5,1,&callbar_ptr->bar_list[jj].ss_status[mm],0x80,&asn_buf);							
					}
				}
			}
		}
		if (isd_ptr->ss_info.param_flag & 0x08) // ss data
		{
			ss_ptr = (ExtSsData_struct *)&isd_ptr->ss_info.ss_data;
			for(jj = 0;jj < 16;jj ++)
			{
				kk = 0x01 << jj;
				if (ss_ptr->param_flag & kk)
				{
					sprintf(tlv2,"%s.3-%d",tlv1,tag2++);
					tag3 = 1;
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);
					buf_len = add_tlv(tlv3,1,&ss_ptr->ss_code[jj],0x00,&asn_buf);
					sprintf(tlv3,"%s.4-%d",tlv2,tag3++);
					buf_len = add_tlv(tlv3,1,&ss_ptr->ss_status[jj],0x80,&asn_buf);
					if (ss_ptr->subs_opt[jj].choice_flag == 1)
					{
						sprintf(tlv3,"%s.2-%d",tlv2,tag3++);
						temp_buf[0] = ss_ptr->subs_opt[jj].choice.clires_opt;
						buf_len = add_tlv(tlv3,1,temp_buf,0x80,&asn_buf);
					}
					else if (ss_ptr->subs_opt[jj].choice_flag == 2)
					{
						sprintf(tlv3,"%s.1-%d",tlv2,tag3++);
						temp_buf[0] = ss_ptr->subs_opt[jj].choice.over_cate;
						buf_len = add_tlv(tlv3,1,temp_buf,0x80,&asn_buf);
					}
				}
			}
		}
		if(isd_ptr->ss_info.param_flag & 0x10)	//emlpp-Info
		{
			emlpp_ptr = (EmlppInfo_struct *)&isd_ptr->ss_info.emlpp_info;
			sprintf(tlv2,"%s.4-%d",tlv1,tag2++);
			tag3 = 1;
			sprintf(tlv3, "%s.2-%d", tlv2, tag3++);
			if(emlpp_ptr->param_flag & 0x01)
				buf_len = add_tlv(tlv3, 1, &emlpp_ptr->maxent_prio, 0x00, &asn_buf);
			sprintf(tlv3, "%s.2-%d", tlv2, tag3++);
			if(emlpp_ptr->param_flag & 0x02)
				buf_len = add_tlv(tlv3, 1, &emlpp_ptr->default_prio, 0x00, &asn_buf);
		}
	}

	if (flag & 0x10)	// odb-data
	{
		if(isd_ptr->odb_data.param_flag & 0x03)
		{
			sprintf(tlv1,"8-%d",tag1++);
			tag2 = 1;
			if (isd_ptr->odb_data.param_flag & 0x01)	// ODB general data
			{
				sprintf(tlv2,"%s.3-%d",tlv1,tag2++);
				temp_buf[0] = isd_ptr->odb_data.odb_general >> 8;
				temp_buf[1] = isd_ptr->odb_data.odb_general;
				if(version<3)
					len = bytestrtobitstr(temp_data,temp_buf,6);
				else
					len = bytestrtobitstr(temp_data,temp_buf,15);
				buf_len = add_tlv(tlv2,len,temp_data,0x00,&asn_buf);
			}
			if (isd_ptr->odb_data.param_flag & 0x02)	// ODB HPLMN data
			{
				sprintf(tlv2,"%s.3-%d",tlv1,tag2++);
				temp_buf[0] = isd_ptr->odb_data.odb_hplmn;
				len = bytestrtobitstr(temp_data,temp_buf,4);
				buf_len = add_tlv(tlv2,len,temp_data,0x00,&asn_buf);
			}
		}
	}

	
	if (flag & 0x100)	// roaming restriction due to unsuppoerted feature
	{
		sprintf(tlv1,"9-%d",tag1++);
		buf_len = add_null(tlv1,0x80,&asn_buf);
	}
	if (flag & 0x200)	// regional Subscription Data
	{
		if (isd_ptr->zc_list.list_len > ZONECODE_LEN)
			return RER;
		for (jj = 0;jj < isd_ptr->zc_list.list_len;jj ++)
		{
			sprintf(tlv1,"10-%d.4-%d",tag1,jj+1);
			buf_len = add_tlv(tlv1,2,isd_ptr->zc_list.zone_code[jj],0x00,&asn_buf);
		}
		tag1 ++;
	}
	if (flag & 0x400)	// vbs Subscription Data
	{
		if (isd_ptr->vbsdata_list.list_len > VBS_LEN)
			return RER;
		for (jj = 0;jj < isd_ptr->vbsdata_list.list_len;jj ++)
		{
			sprintf(tlv1,"11-%d.16-%d.4",tag1,jj+1);
			buf_len = add_tlv(tlv1,3,isd_ptr->vbsdata_list.vbs_data[jj].group_id,0x00,&asn_buf);
			if (isd_ptr->vbsdata_list.vbs_data[jj].param_flag & 0x02)
			{
				sprintf(tlv1,"11-%d.16-%d.5",tag1,jj+1);
				buf_len = add_null(tlv1,0x00,&asn_buf);
			}
		}
		tag1 ++;
	}
	if (flag & 0x800)	// vgcs Subscription Data
	{
		if (isd_ptr->vgcdata_list.list_len > VGCS_LEN)
			return -1;
		for (jj = 0;jj < isd_ptr->vgcdata_list.list_len;jj ++)
		{
			sprintf(tlv1,"12-%d.16-%d.4",tag1,jj+1);
			buf_len = add_tlv(tlv1,3,isd_ptr->vgcdata_list.vgc_data[jj].group_id,0x00,&asn_buf);
		}
		tag1 ++;
	}
	if (flag & 0x1000)	// vlr Camel Subscription Info
	{
		if (isd_ptr->subs_info.param_flag & 0x01)	//o-CSI
		{
			temp_len = assign_ocsi(&isd_ptr->subs_info.o_csi,temp_buf);
			sprintf(tlv1,"13-%d.0",tag1);
			buf_len = add_tlv(tlv1,temp_len,temp_buf,0x0a0,&asn_buf);
		}
		if (isd_ptr->subs_info.param_flag & 0x02)	//ss-CSI
		{
			sprintf(tlv1,"13-%d.2",tag1);
			buf_len = assign_sscsi(tlv1,&isd_ptr->subs_info.ss_csi,&asn_buf);
		}
		if (isd_ptr->subs_info.param_flag & 0x04)	//O-BcsmCamelTDPCriteriaList	
		{
			temp_len = assign_tdpcritlist(&isd_ptr->subs_info.tdp_list,temp_buf);
			sprintf(tlv1,"13-%d.4",tag1);
			buf_len = add_tlv(tlv1,temp_len,temp_buf,0x0a0,&asn_buf);
		}
		if (isd_ptr->subs_info.param_flag & 0x08)	//sms-CSI
		{
			sprintf(tlv1,"13-%d.6",tag1);
			buf_len = assign_smscsi(tlv1,&isd_ptr->subs_info.sms_csi,&asn_buf);
		}
		tag1 ++;
	}
	if (flag & 0x2000)	// naea Preferred CI
	{
		sprintf(tlv1,"15-%d",tag1++);
		buf_len = add_tlv(tlv1,NAEA_LEN,isd_ptr->naea_ci.cic,0x80,&asn_buf);
	}
	if (flag & 0x4000)	// GPRS Subscription Data
	{
		if (isd_ptr->gprs_data.param_flag & 0x01)	//data list include
		{
			sprintf(tlv1,"16-%d.5",tag1);
			buf_len = add_null(tlv1,0x00,&asn_buf);

			sprintf(tlv1,"16-%d.1-2",tag1);
		}
		else
			sprintf(tlv1,"16-%d.1",tag1);
			
		if (isd_ptr->gprs_data.gprs_list.list_len > PDPCONTEXT_LEN)
			return RER;
		
		for (jj = 0;jj < isd_ptr->gprs_data.gprs_list.list_len;jj ++)
		{
			kk = 1;
			sprintf(tlv2,"%s.16-%d",tlv1,jj+1);
			buf_len = add_null(tlv2, 0x20, &asn_buf);
			pdp_ptr = (PdpContext_struct *) &isd_ptr->gprs_data.gprs_list.pdp_context[jj];
			if (pdp_ptr->param_flag & 0x01)	// pdp context id
			{
				sprintf(tlv2,"%s.16-%d.2-%d",tlv1,jj+1, kk++);
				buf_len = add_int(tlv2,pdp_ptr->pdpcontext_id,0x00,&asn_buf);
			}
			if (pdp_ptr->param_flag & 0x02)	// pdp type
			{
				sprintf(tlv2,"%s.16-%d.16-%d",tlv1,jj+1, kk++);
				buf_len = add_tlv(tlv2,2,pdp_ptr->pdp_type,0x80,&asn_buf);
			}
			if (pdp_ptr->param_flag & 0x04)	// pdp add
			{
				sprintf(tlv2,"%s.16-%d.17-%d",tlv1,jj+1, kk++);
				buf_len = add_tlv(tlv2,pdp_ptr->pdp_add[0],pdp_ptr->pdp_add+1,0x80,&asn_buf);
			}
			if (pdp_ptr->param_flag & 0x08)	// QoS subscribed
			{
				sprintf(tlv2,"%s.16-%d.18-%d",tlv1,jj+1, kk++);
				buf_len = add_tlv(tlv2,3,pdp_ptr->qos_sub,0x80,&asn_buf);
			}
			if (pdp_ptr->param_flag & 0x10)	// VPLMN address allowed
			{
				sprintf(tlv2,"%s.16-%d.19-%d",tlv1,jj+1, kk++);
				buf_len = add_null(tlv2,0x80,&asn_buf);
			}
			if (pdp_ptr->param_flag & 0x20)	// apn
			{
				if (pdp_ptr->apn.apn_len > APN_LEN)
					return RER;
				sprintf(tlv2,"%s.16-%d.20-%d",tlv1,jj+1, kk++);
				buf_len = add_tlv(tlv2,pdp_ptr->apn.apn_len,pdp_ptr->apn.apn_data,0x80,&asn_buf);
			}
			if (pdp_ptr->param_flag & 0x40)	// ext QoS subscribed
			{
				sprintf(tlv2,"%s.16-%d.0-%d",tlv1,jj+1, kk++);
				buf_len = add_tlv(tlv2,pdp_ptr->ext_qos_sub[0],pdp_ptr->ext_qos_sub+1,0x80,&asn_buf);
			}
			if(pdp_ptr->param_flag & 0x100)	// ext 2 QoS subscribed
			{
				sprintf(tlv2,"%s.16-%d.2-%d",tlv1,jj+1, kk++);
				buf_len = add_tlv(tlv2,pdp_ptr->ext2_qos_sub[0],pdp_ptr->ext2_qos_sub+1,0x80,&asn_buf);
			}
			if(pdp_ptr->param_flag & 0x200)	// ext 3 QoS subscribed
			{
				sprintf(tlv2,"%s.16-%d.3-%d",tlv1,jj+1, kk++);
				buf_len = add_tlv(tlv2,pdp_ptr->ext3_qos_sub[0],pdp_ptr->ext3_qos_sub+1,0x80,&asn_buf);
			}
		}
		tag1 ++;
	}
	if (flag & 0x8000)	// roaming Restricted In Sgsn Due To Unsupported Feature
	{
		sprintf(tlv1,"23-%d",tag1++);
		buf_len = add_null(tlv1,0x80,&asn_buf);
	}
	if (flag & 0x10000)	// network Aceess Mode
	{
		sprintf(tlv1,"24-%d",tag1++);
		buf_len = add_int(tlv1,isd_ptr->net_mode,0x80,&asn_buf);
	}
	return buf_len;
}

int extract_inssubdataarg(struct MapISD_Arg *isd_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF	asn_buf;
	int		len,jj,kk,index;
	int		temp_len,ss_mask=0;
	u32		flag=0, code_flag=0;
	u8		tag1,tag2=0;
	char	tlv2[32],tlv3[32];
	u8		temp_buf[256],temp_data[256];
	struct	ExtFwdInfo_struct		*fwd_ptr;
	struct	ExtCallBarInfo_struct	*callbar_ptr;
	struct	ExtSsData_struct		*ss_ptr;
	struct	EmlppInfo_struct		*emlpp_ptr;
	struct	PdpContext_struct		*pdp_ptr;
	
	isd_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);	// get imsi
	if (len==IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)
	{
		flag |= 0x01;
		memcpy(isd_ptr->imsi,temp_buf,len);
	}	
	if ((len=get_tlv("1",temp_buf,&asn_buf)) > 2)
	{
		flag |= 0x02;
		isd_ptr->msisdn[0] = len;
		memcpy(isd_ptr->msisdn+1,temp_buf,len);	
	}
	if (get_tlv("2",temp_buf,&asn_buf) > 0)
	{
		flag |= 0x04;
		isd_ptr->category = temp_buf[0];
	}
	if(get_tlv("3",temp_buf,&asn_buf) > 0)
	{
		flag |= 0x08;
		isd_ptr->sub_status = temp_buf[0];
	}
	isd_ptr->odb_data.param_flag = 0;
	len = get_tlv("8.3-1",temp_buf,&asn_buf);	//odb-data->odb->GreneralData
	if (len != -1)
	{
		flag |= 0x10; // odb - data
		isd_ptr->odb_data.param_flag |= 0x01; //odb general
		jj = bitstrtobytestr(temp_data,temp_buf,len);
		isd_ptr->odb_data.odb_general = bcdtou32(temp_data,jj);
	}
	len = get_tlv("8.3-2",temp_buf,&asn_buf);
	if (len != -1)
	{
		flag |= 0x10; // odb - data
		isd_ptr->odb_data.param_flag |= 0x02; // odb hplmn
		jj = bitstrtobytestr(temp_data,temp_buf,len);
		isd_ptr->odb_data.odb_hplmn = bcdtou32(temp_data,jj);
	}
	temp_len = 0;
	for (jj = 0;jj < BSLIST_LEN;jj ++)	// bearer Service List
	{
		sprintf(tlv2,"4.4-%d",jj+1);
		if (get_tlv(tlv2,temp_buf,&asn_buf) < 1)
			break;
		temp_data[jj] = temp_buf[0];
		temp_len ++;
		flag |= 0x20;
	}
	isd_ptr->bearer_data = bearer_strtobit(temp_data,temp_len);	
	temp_len = 0;
	for (jj = 0;jj < TSLIST_LEN;jj ++)	// tele Service List
	{
		sprintf(tlv2,"6.4-%d",jj+1);
		if (get_tlv(tlv2,temp_buf,&asn_buf) < 1)
			break;
		temp_data[jj] = temp_buf[0];
		temp_len++;
		flag |= 0x40;
	}
	isd_ptr->tele_data = tele_strtobit(temp_data,temp_len);
	isd_ptr->ss_info.param_flag = 0;
	tag1 = 1; ss_mask = 0;
	for(index=0;index<4;index++) /* sometime, the sequence of 7.0/7.1/7.3 is not in order */
	{
		if (!(ss_mask & 0x01) && get_tlv("7.0",temp_buf,&asn_buf) != -1)	// forwarding info
		{
			flag |= 0x80; // ss info
			isd_ptr->ss_info.param_flag |= 0x01; // fwd info
			fwd_ptr = (ExtFwdInfo_struct *)&isd_ptr->ss_info.fwd_info;
			fwd_ptr->param_flag = 0;
			for (jj = 0;jj < 4;jj ++)
			{
				fwd_ptr->fwd_feat[jj].param_flag = 0;
				fwd_ptr->fwd_feat[jj].bs_code.param_flag = 0;
				sprintf(tlv2,"7.0-%d.4",tag1); // ss code
				len = get_tlv(tlv2,temp_buf,&asn_buf);
				if (len > 0)
				{
					fwd_ptr->param_flag |= (0x01 << jj);
					fwd_ptr->ss_code[jj] = temp_buf[0];
					ss_mask |= 0x01;
				}
				else
					break;
				sprintf(tlv2,"7.0-%d.16.16",tag1);	// forward feature
				sprintf(tlv3,"%s.2",tlv2);	// bearer code of bs code
				len = get_tlv(tlv3,temp_buf,&asn_buf);
				if (len > 0)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x01;
					fwd_ptr->fwd_feat[jj].bs_code.param_flag = 2; // bearer
					fwd_ptr->fwd_feat[jj].bs_code.bearer_code = bearer_strtobit(temp_buf,1);
				}
				sprintf(tlv3,"%s.3",tlv2);	// tele code of bs code
				len = get_tlv(tlv3,temp_buf, &asn_buf);
				if (len >= 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x01; // bs code
					fwd_ptr->fwd_feat[jj].bs_code.param_flag = 1;// tele
					fwd_ptr->fwd_feat[jj].bs_code.tele_code = tele_strtobit(temp_buf,1);
				}
				sprintf(tlv3,"%s.4",tlv2);
				if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x02; // ss status
					fwd_ptr->fwd_feat[jj].ss_status = temp_buf[0];
				}
				sprintf(tlv3,"%s.5",tlv2);
				len = get_tlv(tlv3,temp_buf,&asn_buf);
				if (len >= 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x04; // fwd to num
					fwd_ptr->fwd_feat[jj].fwdto_num[0] = len;
					memcpy(fwd_ptr->fwd_feat[jj].fwdto_num+1,temp_buf,len);
				}
				sprintf(tlv3,"%s.6",tlv2);
				if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x08; // fwd opt
					fwd_ptr->fwd_feat[jj].fwd_option = temp_buf[0];
				}
				sprintf(tlv3,"%s.7",tlv2);
				if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
				{
					fwd_ptr->fwd_feat[jj].param_flag |= 0x10; // norc time
					fwd_ptr->fwd_feat[jj].norc_time = temp_buf[0];
				}
				tag1 ++;
			}
		}
		if (!(ss_mask & 0x02) && get_tlv("7.1",temp_buf,&asn_buf) != -1)		// call Barring Info
		{
			flag |= 0x80; // ss info
			isd_ptr->ss_info.param_flag |= 0x02; // call bar info
			callbar_ptr = (ExtCallBarInfo_struct *)&isd_ptr->ss_info.call_info;
			memset(callbar_ptr, 0x00, sizeof(ExtCallBarInfo_struct));
			callbar_ptr->param_flag = 0;
			tag2=1;
			for (jj = 0;jj < 5;jj ++)
			{
				callbar_ptr->bs_code[jj].param_flag = 0;
				sprintf(tlv2,"7.1-%d.4",tag1);	//callbarringInfo
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					callbar_ptr->param_flag |= (0x01 << jj); // ss code
					callbar_ptr->ss_code[jj] = temp_buf[0];
					ss_mask |= 0x02;
				}
				else
					break;
				tag1++;
				code_flag = 0;
				for(kk=0;kk<5;kk++)
				{
					sprintf(tlv2,"7.1-%d.16.16-%d",tag1-1,kk+1);
                                   sprintf(tlv3,"%s.4",tlv2);
					if (get_tlv(tlv3,temp_buf,&asn_buf) == 1)
						callbar_ptr->bar_list[jj].ss_status[kk] = temp_buf[0];
					else
						continue;
					callbar_ptr->bar_list[jj].param_flag |= 0x01<<kk;
					sprintf(tlv3,"%s.2",tlv2);
					len = get_tlv(tlv3,temp_buf,&asn_buf);
					if (len >= 1)
					{
						callbar_ptr->bar_list[jj].bs_code[kk].param_flag = 2; // bearer
						callbar_ptr->bar_list[jj].bs_code[kk].bearer_code = bearer_strtobit(temp_buf,1);
						code_flag = 1;
					}
					sprintf(tlv3,"%s.3",tlv2);
					len	= get_tlv(tlv3,temp_buf,&asn_buf);
					if (len >= 1)
					{
						callbar_ptr->bar_list[jj].bs_code[kk].param_flag = 1; // bearer
						callbar_ptr->bar_list[jj].bs_code[kk].tele_code = tele_strtobit(temp_buf,1);
						code_flag = 1;
					}
				}
				if(code_flag == 0)
				{
					callbar_ptr->bar_list[jj].bs_code[0].param_flag = 1; // bearer
					temp_buf[0] = TS_AllSTS;
					callbar_ptr->bar_list[jj].bs_code[0].tele_code = tele_strtobit(temp_buf,1);

					callbar_ptr->bar_list[jj].bs_code[1].param_flag = 1; // bearer
					temp_buf[0] = TS_AllSMS;
					callbar_ptr->bar_list[jj].bs_code[1].tele_code = tele_strtobit(temp_buf,1);
					callbar_ptr->bar_list[jj].ss_status[1] = callbar_ptr->bar_list[jj].ss_status[0];
					callbar_ptr->bar_list[jj].param_flag |= 0x03;
				}
				tag2++;
			}
		}
		if (!(ss_mask & 0x04) && get_tlv("7.3",temp_buf,&asn_buf) != -1)		// ss_Data
		{
			flag |= 0x80; // ss info
			isd_ptr->ss_info.param_flag |= 0x08; // ss data
			ss_ptr = (ExtSsData_struct *)&isd_ptr->ss_info.ss_data;
			ss_ptr->param_flag = 0;
			for(jj = 0;jj < 16;jj ++)
			{
				sprintf(tlv2,"7.3-%d.4-1",tag1);
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					ss_ptr->param_flag |= (0x01 << jj);  
					ss_ptr->ss_code[jj] = temp_buf[0];
					ss_mask |= 0x04;
				}
				else
					break;
				sprintf(tlv2,"7.3-%d.4-2",tag1);	//ss-status
	//			len = get_tlv(tlv2,temp_buf,&asn_buf);
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
					ss_ptr->ss_status[jj] = temp_buf[0];
				ss_ptr->subs_opt[jj].choice_flag = 0;
				sprintf(tlv2,"7.3-%d.2-3",tag1);	//cliRestrictionOption
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					ss_ptr->subs_opt[jj].choice_flag = 1; // clires opt
					ss_ptr->subs_opt[jj].choice.clires_opt = temp_buf[0];
				}
				sprintf(tlv2,"7.3-%d.1-3",tag1);	//overrideCategory
				if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
				{
					ss_ptr->subs_opt[jj].choice_flag = 2; // clires opt
					ss_ptr->subs_opt[jj].choice.over_cate = temp_buf[0];
				}
				sprintf(tlv2,"7.3-%d.2-2",tag1);	// bearer code
				len = get_tlv(tlv2,temp_buf,&asn_buf);
				if (len > 0)
					ss_ptr->bs_code[jj].bearer_code = bearer_strtobit(temp_buf,1);
				sprintf(tlv2,"7.3-%d.3",tag1);	// tele code
				len = get_tlv(tlv2,temp_buf, &asn_buf);
				if (len >= 1)
					ss_ptr->bs_code[jj].tele_code = tele_strtobit(temp_buf,1);
				tag1 ++;
			}
		}
		if(!(ss_mask & 0x08) && get_tlv("7.4", temp_buf, &asn_buf) != -1)	//emlpp-Info
		{
			flag |= 0x80; // ss info
			isd_ptr->ss_info.param_flag |= 0x10;	//emlpp info
			emlpp_ptr = (EmlppInfo_struct *)&isd_ptr->ss_info.emlpp_info;
			emlpp_ptr->param_flag = 0;
			ss_mask |= 0x08;
			sprintf(tlv2, "7.4-%d.2-1", tag1);
			if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
			{
				emlpp_ptr->param_flag |= 0x01;
				emlpp_ptr->maxent_prio = temp_buf[0];
			}
			sprintf(tlv2, "7.4-%d.2-2", tag1);
			if(get_tlv(tlv2, temp_buf, &asn_buf) == 1)
			{
				emlpp_ptr->param_flag |= 0x02;
				emlpp_ptr->default_prio = temp_buf[0];
			}
		}
	}
	if (get_null("9",&asn_buf) != -1)	//get roaming restriction data
	{
		flag |= 0x100;
		isd_ptr->roam_feature = 1;
	}
	len = get_tlv("10",temp_buf,&asn_buf);	//regional Subscription Data
	if (len > 0)
	{
		flag |= 0x200;
		for (jj = 0;jj < ZONECODE_LEN;jj ++)
		{
			sprintf(tlv2,"10.4-%d",jj+1);
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len == 2)
				memcpy(isd_ptr->zc_list.zone_code[jj],temp_buf,2);
			else
				break;
		}
		isd_ptr->zc_list.list_len = jj;
	}
	len = get_tlv("11",temp_buf,&asn_buf);	//vbs Subscription Data
	if (len > 0)
	{
		flag |= 0x400;
		for (jj = 0;jj < VBS_LEN;jj ++)
		{
			sprintf(tlv2,"11.16-%d.4",jj+1);
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len == 3)
			{
				memcpy(isd_ptr->vbsdata_list.vbs_data[jj].group_id,temp_buf,3);
				isd_ptr->vbsdata_list.vbs_data[jj].param_flag |= 0x01;
			}
			else
				break;
			sprintf(tlv2,"11.16-%d.5",jj+1);
			if (get_null(tlv2,&asn_buf) >= 0)
				isd_ptr->vbsdata_list.vbs_data[jj].param_flag |= 0x02;
		}
		isd_ptr->vbsdata_list.list_len = jj;
	}
	len = get_tlv("12",temp_buf,&asn_buf);	//vgcs Subscription Data
	if (len > 0)
	{
		flag |= 0x800;
		for (jj = 0;jj < VGCS_LEN;jj ++)
		{
			sprintf(tlv2,"12.16-%d.4",jj+1);
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len == 3)
			{
				memcpy(isd_ptr->vgcdata_list.vgc_data[jj].group_id,temp_buf,3);
				isd_ptr->vgcdata_list.vgc_data[jj].param_flag = 0x01;
			}
			else
				break;
		}
		isd_ptr->vgcdata_list.list_len = jj;
	}
	len = get_tlv("13",temp_buf,&asn_buf);	//vlr Camel Subscription Info
	if (len > 0)
	{
		flag |= 0x1000;
		isd_ptr->subs_info.param_flag = 0;
		len = get_tlv("13.0",temp_buf,&asn_buf);	//o-CSI
		if (len != -1)
		{
			if (!extract_ocsi(&isd_ptr->subs_info.o_csi,len,temp_buf))
				return RER;
			isd_ptr->subs_info.param_flag |= 0x01;
		}
		if (extract_sscsi("13.2",&isd_ptr->subs_info.ss_csi,&asn_buf) > 0)	//ss-CSI
			isd_ptr->subs_info.param_flag |= 0x02;
		len = get_tlv("13.4",temp_buf,&asn_buf);	//O-BcsmCamelTDPCriteriaList
		if (len != -1)
		{
			if (!extract_tdpcritlist(&isd_ptr->subs_info.tdp_list,len,temp_buf))
				return RER;
			isd_ptr->subs_info.param_flag |= 0x04;
		}
		if (extract_smscsi("13.6",&isd_ptr->subs_info.sms_csi,&asn_buf) > 0)	//sms-CSI
			isd_ptr->subs_info.param_flag |= 0x08;
	}
	if (get_tlv("15.0",temp_buf,&asn_buf) == NAEA_LEN)	//naea Preferred CI
	{
		memcpy(isd_ptr->naea_ci.cic,temp_buf,NAEA_LEN);
		flag |= 0x2000;
	}
	len = get_tlv("16",temp_buf,&asn_buf);	//GPRS Subscription Data
	if (len > 0)
	{
		flag |= 0x4000;
		if (get_null("16.5",&asn_buf) != -1)
		{
			isd_ptr->gprs_data.param_flag |= 0x01;
			isd_ptr->gprs_data.data_include = 1;
		}
		for (jj = 0;jj < PDPCONTEXT_LEN;jj ++)
		{
			pdp_ptr = (PdpContext_struct *) &isd_ptr->gprs_data.gprs_list.pdp_context[jj];
			pdp_ptr->param_flag = 0;
			sprintf(tlv2,"16.16-%d.2",jj+1);	// pdp context id
			if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
			{
				pdp_ptr->param_flag |= 0x01;
				pdp_ptr->pdpcontext_id = temp_buf[0];
			}
			else
				break;
			sprintf(tlv2,"16.16-%d.16",jj+1);	// pdp type
			if (get_tlv(tlv2,temp_buf,&asn_buf) == 2)
			{
				pdp_ptr->param_flag |= 0x02;
				memcpy(pdp_ptr->pdp_type,temp_buf,2);
			}
			sprintf(tlv2,"16.16-%d.17",jj+1);	// pdp address
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len != -1 && len < PDP_LEN)
			{
				pdp_ptr->param_flag |= 0x04;
				pdp_ptr->pdp_add[0] = len;
				memcpy(pdp_ptr->pdp_add+1,temp_buf,len);
			}
			sprintf(tlv2,"16.16-%d.18",jj+1);	// QoS subscribed
			if (get_tlv(tlv2,temp_buf,&asn_buf) == 3)
			{
				pdp_ptr->param_flag |= 0x08;
				memcpy(pdp_ptr->qos_sub,temp_buf,3);
			}
			sprintf(tlv2,"16.16-%d.19",jj+1);	// vplmn allow
			if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
			{
				pdp_ptr->param_flag |= 0x10;
				pdp_ptr->vplmn_allow = temp_buf[0];
			}
			sprintf(tlv2,"16.16-%d.20",jj+1);	// apn
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len != -1 && len < APN_LEN)
			{
				pdp_ptr->param_flag |= 0x20;
				pdp_ptr->apn.apn_len = len;
				memcpy(pdp_ptr->apn.apn_data,temp_buf,len);
			}
			sprintf(tlv2,"16.16-%d.0",jj+1);	// ext QoS subscribed
			len = get_tlv(tlv2,temp_buf,&asn_buf);
			if (len != -1 && len < EXT_QOS_SUB_LEN)
			{
				pdp_ptr->param_flag |= 0x40;
				pdp_ptr->ext_qos_sub[0] = len;
				memcpy(pdp_ptr->ext_qos_sub+1,temp_buf,len);
			}
		}
		if (jj != 0)
			isd_ptr->gprs_data.param_flag |= 0x02;
		isd_ptr->gprs_data.gprs_list.list_len = jj;
	}
	if (get_null("23",&asn_buf) != -1)//roaming Restricted In Sgsn Due To Unsupported Feature
	{
		flag |= 0x8000;
		isd_ptr->roamsgsn_feature = 1;
	}
	if (get_tlv("24",temp_buf,&asn_buf) == 1)
	{
		flag |= 0x10000;
		isd_ptr->net_mode = temp_buf[0];
	}
	isd_ptr->param_flag = flag;
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding insert subscribe Data response	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_inssubdatares(struct MapISD_Res *isd_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			temp_len;
	u8			temp_buf[256],temp_data[256];
	int			flag,jj,buf_len=0;
	int			tag1=1;
	char		tlv1[32],tlv2[32];
	
	asn_encode(buf,&asn_buf);
	flag = isd_ptr->param_flag;
	if (flag & 0x01) // tele list
	{
		temp_len = tele_bittostr(isd_ptr->tele_data,temp_data,0);		
		sprintf(tlv1,"1-%d",tag1++);
		for (jj = 0;jj < temp_len;jj ++)
		{
			sprintf(tlv2,"%s.4-%d",tlv1,jj+1);
			buf_len = add_tlv(tlv2,1,&temp_data[jj],0x00,&asn_buf);
		}
	}
	if (flag & 0x02) // bearer list
	{
		temp_len = bearer_bittostr(isd_ptr->bearer_data,temp_data,0);		
		sprintf(tlv1,"2-%d",tag1++);
		for (jj = 0;jj < temp_len;jj ++)
		{
			sprintf(tlv2,"%s.4-%d",tlv1,jj+1);
			buf_len = add_tlv(tlv2,1,&temp_data[jj],0x00,&asn_buf);
		}
	}
	if (flag & 0x04) // ss list
	{
		sprintf(tlv1,"3-%d",tag1++);
		for (jj = 0;jj < isd_ptr->ss_list.sslist_len;jj ++)
		{
			sprintf(tlv2,"%s.4-%d",tlv1,jj+1);
			buf_len = add_tlv(tlv2,1,&isd_ptr->ss_list.ss_code[jj],0x00,&asn_buf);
		}
	}
	if (flag & 0x08)	// odb data
	{
		sprintf(tlv1,"4-%d",tag1++);
		temp_buf[0] = isd_ptr->odb_data;
		temp_len = bytestrtobitstr(temp_data,temp_buf,6);
		buf_len = add_tlv(tlv1,temp_len,temp_data,0x80,&asn_buf);
	}
	if (flag & 0x10)	//subs res
	{
		sprintf(tlv1,"5-%d",tag1++);
		temp_buf[0] = isd_ptr->subs_res;
		buf_len = add_tlv(tlv1,1,temp_buf,0x80,&asn_buf);
	}
	if (flag & 0x20)	 // camel phase
	{
		sprintf(tlv1,"6-%d",tag1++);
		buf_len = add_tlv(tlv1,3,isd_ptr->camel_phase,0x80,&asn_buf);
	}
	return buf_len;
}

int extract_inssubdatares(struct MapISD_Res *isd_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len,jj;
	int			temp_len;
	u8			temp_buf[256],temp_data[256];
	u32			flag=0;
	char		tlv2[32];
	
	isd_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	temp_len = 0;
	for (jj = 0;jj < TSLIST_LEN;jj ++)	// tele Service List
	{
		sprintf(tlv2,"1.4-%d",jj+1);
		if(get_tlv(tlv2,temp_buf,&asn_buf) < 1)
			break;
		temp_data[jj] = temp_buf[0];
		temp_len++;
		flag |= 0x01;
	}
	isd_ptr->tele_data = tele_strtobit(temp_data,temp_len);
	temp_len = 0;
	for (jj = 0;jj < BSLIST_LEN;jj ++)	// bearer Service List
	{
		sprintf(tlv2,"2.4-%d",jj+1);
		if(get_tlv(tlv2,temp_buf,&asn_buf) < 1)
			break;
		temp_data[jj] = temp_buf[0];
		temp_len ++;
		flag |= 0x02;
	}
	isd_ptr->bearer_data = bearer_strtobit(temp_data,temp_len);	
	isd_ptr->ss_list.sslist_len = 0;
	for (jj = 0;jj < SS_LEN;jj ++)		// ss list
	{
		sprintf(tlv2,"3.4-%d",jj+1);
		if (get_tlv(tlv2,temp_buf,&asn_buf) == 1)
		{
			flag |= 0x04;
			isd_ptr->ss_list.ss_code[jj] = temp_buf[0];
		}
		else 
			break;
	}
	isd_ptr->ss_list.sslist_len = jj;
	len = get_tlv("4",temp_buf,&asn_buf);	//odb-data
	if (len != -1)
	{
		flag |= 0x08;
		jj = bitstrtobytestr(temp_data,temp_buf,len);
		isd_ptr->odb_data = bcdtou32(temp_data,jj);
	}
	if (get_tlv("5",temp_buf,&asn_buf) == 1)// subs response
	{
		isd_ptr->subs_res = temp_buf[0];
		flag |= 0x10;
	}
	if (get_tlv("6",temp_buf,&asn_buf) == 3)
	{
		memcpy(isd_ptr->camel_phase,temp_buf,3);
		flag |= 0x20;
	}
	isd_ptr->param_flag = flag;
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding delete Subscriber Data argument	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_delsubdataarg(struct MapDSD_Arg *dsd_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0,jj;
	char		tlv2[32];
	u32			flag;
	int			temp_len;
	u8			temp_data[256];
	
	flag = dsd_ptr->param_flag;
	asn_encode(buf,&asn_buf);
	if (flag & 0x01)		//imsi
		buf_len = add_tlv("0",IMSI_LEN,dsd_ptr->imsi,0x80,&asn_buf);
	else
		return RER;
	if (flag & 0x02)		//bs code
	{
		temp_len = assign_bscode(&dsd_ptr->bs_code,temp_data,0);
		buf_len = add_tlv("1",temp_len,temp_data,0x80,&asn_buf);
	}
	if (flag & 0x04)		//ss list
	{
		for (jj = 0;jj < dsd_ptr->ss_list.sslist_len;jj ++)
		{
			sprintf(tlv2,"2.4-%d",jj+1);
			buf_len = add_tlv(tlv2,1,&dsd_ptr->ss_list.ss_code[jj],0x00,&asn_buf);
		}	
	}
	if (flag & 0x08)		//roaming restriction due to unsupported feature
		buf_len = add_null("4",0x80,&asn_buf);
	if (flag & 0x10)		//regional subscription identifier (zone code)
		buf_len = add_tlv("5",2,dsd_ptr->regional_ident,0x80,&asn_buf);
	if (flag & 0x20)		//vbsGroupIndication
		buf_len = add_null("7",0x80,&asn_buf);
	if (flag & 0x40)		//vgcGroupIndication
		buf_len = add_null("8",0x80,&asn_buf);
	if (flag & 0x80)		//camelSubscriptionInfoWithdraw
		buf_len = add_null("9",0x80,&asn_buf);
	if (flag & 0x100)	//gprsSubscriptionDataWithdraw
	{
		if (dsd_ptr->gprs_withdraw.choice_flag & 0x01)
			buf_len = add_null("10.5",0x00,&asn_buf);
		else if (dsd_ptr->gprs_withdraw.choice_flag & 0x02)
		{
			if (dsd_ptr->gprs_withdraw.choice.context_list.list_len > PDPCONTEXT_LEN)
				return RER;
			temp_len = dsd_ptr->gprs_withdraw.choice.context_list.list_len;
			for (jj = 0;jj < temp_len;jj ++)
			{
				sprintf(tlv2,"10.4-%d",jj+1);
				buf_len = add_int(tlv2,dsd_ptr->gprs_withdraw.choice.context_list.context_id[jj],0x00,&asn_buf);
			}
		}
	}
	if (flag & 0x200)	//roaming restricted insgsn due to unsupported feature
		buf_len = add_null("11",0x80,&asn_buf);
	return buf_len;
}

int extract_delsubdataarg(struct MapDSD_Arg *dsd_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len,jj;
	u8			temp_buf[256];
	char 		tlv2[32];

	dsd_ptr->param_flag = 0;
	if (buf_len == 0)
		return RER;
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);
	if (len == IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0) //imsi
	{
		dsd_ptr->param_flag|=0x01;
		memcpy(dsd_ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	if ((len=get_tlv("1",temp_buf,&asn_buf)) > 0)	//bs code
	{
		if (!extract_bscode(&dsd_ptr->bs_code,len,temp_buf))
			return RER;
		dsd_ptr->param_flag |= 0x02;
	}
	dsd_ptr->ss_list.sslist_len = 0;
	for (jj = 0;jj < SS_LEN;jj ++)	//get ss list
	{
		sprintf(tlv2,"2.4-%d",jj+1);
		if (get_tlv(tlv2,temp_buf,&asn_buf) != 1)
			break;
		dsd_ptr->ss_list.sslist_len++;
		dsd_ptr->ss_list.ss_code[jj] = temp_buf[0];		
		dsd_ptr->param_flag|=0x04;
	}
	if (get_tlv("4",temp_buf,&asn_buf) != -1)	//roaming restriction due to unsupported feature
	{
		dsd_ptr->param_flag |= 0x08;
		dsd_ptr->roam_feature = 1;
	}	
	if (get_tlv("5",temp_buf,&asn_buf) == 2)	// regional subscription identifier (zone code)
	{
		dsd_ptr->param_flag |= 0x10;
		memcpy(dsd_ptr->regional_ident,temp_buf,2);
	}
	if (get_tlv("7",temp_buf,&asn_buf) != -1)	//vbsGroupIndication
	{
		dsd_ptr->param_flag |= 0x20;
		dsd_ptr->vbsg_ind = 1;
	}
	if (get_tlv("8",temp_buf,&asn_buf) != -1)	//vgcGroupIndication
	{
		dsd_ptr->param_flag |= 0x40;
		dsd_ptr->vgcsg_ind = 1;
	}
	if (get_tlv("9",temp_buf,&asn_buf) != -1)	//camelSubscriptionInfoWithdraw
	{
		dsd_ptr->param_flag |= 0x80;
		dsd_ptr->camel_withdraw = 1;
	}
	if (get_tlv("10",temp_buf,&asn_buf) != -1)	//gprsSubscriptionDataWithdraw
	{
		dsd_ptr->param_flag |= 0x100;
		if (get_tlv("10.5",temp_buf,&asn_buf) != -1)	// all GPRS data
		{
			dsd_ptr->gprs_withdraw.choice_flag = 0x01;
			dsd_ptr->gprs_withdraw.choice.allgprs_data = 1;
		}
		else
		{
			dsd_ptr->gprs_withdraw.choice.context_list.list_len = 0;
			for (jj = 0;jj < PDPCONTEXT_LEN;jj ++)
			{
				sprintf(tlv2,"10.4-%d",jj+1);
				if (get_tlv(tlv2,temp_buf,&asn_buf) != 1)
					break;
				dsd_ptr->gprs_withdraw.choice.context_list.context_id[jj] = temp_buf[0];
				dsd_ptr->gprs_withdraw.choice.context_list.list_len ++;
				dsd_ptr->gprs_withdraw.choice_flag = 0x02;
			}
		}
	}
	if (get_tlv("11",temp_buf,&asn_buf) != -1)	//roaming restricted insgsn due to unsupported feature
	{
		dsd_ptr->param_flag |= 0x200;
		dsd_ptr->roamsgsn_feature = 1;
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding delete Subscriber Data response	*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_delsubdatares(struct MapDSD_Res *dsdr_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;
	u8			temp_buf[16];

	asn_encode(buf,&asn_buf);	
	if (dsdr_ptr->param_flag & 0x01)
	{
		temp_buf[0] = dsdr_ptr->subs_res;
		buf_len = add_tlv("0",1,temp_buf,0x80,&asn_buf);
	}
	return buf_len;		
}

int extract_delsubdatares(struct MapDSD_Res *dsdr_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	u8			temp_buf[256];

	dsdr_ptr->param_flag=0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	if (get_tlv("0",temp_buf,&asn_buf) > 0)
	{
		dsdr_ptr->subs_res = temp_buf[0];
		dsdr_ptr->param_flag |= 0x01;
	}
	return ROK;
}

/*	+++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding RESET argument	*/
/*  +++++++++++++++++++++++++++++++++	*/
int assign_resetarg(struct MapReset_Arg *rs_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	u32			flag;
	int			buf_len=0,ii;
	u8			temp_isdn[32];
	char		tlv2[32];

	asn_encode(buf,&asn_buf);
	flag = rs_ptr->param_flag;
	if (flag & 0x01)	// hlr num
		buf_len = add_tlv("4",rs_ptr->hlr_num[0],rs_ptr->hlr_num+1,0x00,&asn_buf);
	else
	{
		mapp_log_debug("reset lack hlr_num");
		return RER;
	}
	if (flag & 0x02)	// hlr_list
	{
		for(ii = 0;ii < rs_ptr->hlr_list.list_len;ii ++)
		{
			buf_len = add_null("16",0x20,&asn_buf);
			sprintf(tlv2,"16.4-%d",ii+1);
			buf_len = add_tlv(tlv2,IMSI_LEN,rs_ptr->hlr_list.hlr_id[ii],0x00,&asn_buf);
		}
	}
	if (flag & 0x04)	//networkResource
	{
		temp_isdn[0] = rs_ptr->networkResource;
		buf_len = add_tlv("10",1,temp_isdn,0x00,&asn_buf);
	}
	return buf_len;
}

int extract_resetarg(struct MapReset_Arg *rs_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			len;
	u8			temp_buf[256];
	int			ii;
	char		tlv2[32];

	rs_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_reset,buf_len=0");
		return RER;
	}
	if(asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("4",temp_buf,&asn_buf);	//hlr num
	if(len > 2)
	{
		rs_ptr->param_flag |= 0x01;
		rs_ptr->hlr_num[0] = len;
		memcpy(rs_ptr->hlr_num+1,temp_buf,len);
	}
	else
	{
		mapp_log_debug("extract resetArg lack hlr number");
		return RER;
	}
	rs_ptr->hlr_list.list_len=0;
	for (ii = 0;ii < HLRID_NUM;ii ++)
	{
		sprintf(tlv2,"16.4-%d",ii+1);
		len = get_tlv(tlv2,temp_buf,&asn_buf);
		if (len != IMSI_LEN)
			break;
		rs_ptr->param_flag |= 0x02;	
		memcpy(rs_ptr->hlr_list.hlr_id[ii],temp_buf,IMSI_LEN);
	}
	rs_ptr->hlr_list.list_len = ii;
	if(get_tlv("10",temp_buf,&asn_buf) == 1)
	{
		rs_ptr->networkResource=temp_buf[0];
		rs_ptr->param_flag |= 0x04;
	}
	return ROK;
}

/*	++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding restore Data argument		*/
/*  ++++++++++++++++++++++++++++++++++++++++	*/
int assign_restdataarg(struct MapRD_Arg *rsd_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);	
	if (rsd_ptr->param_flag & 0x01)	//imsi
		buf_len = add_tlv("4-1",IMSI_LEN,rsd_ptr->imsi,0x00,&asn_buf);
	else
		return RER;
	if (rsd_ptr->param_flag & 0x02)	//lmsi
		buf_len = add_tlv("4-2",LMSI_LEN,rsd_ptr->lmsi,0x00,&asn_buf);
	if (rsd_ptr->param_flag & 0x04)	// VLR capability
	{
		if (rsd_ptr->vlr_cap.param_flag & 0x01)	// camel phase
			buf_len = add_tlv("6.0",3,rsd_ptr->vlr_cap.camel_phase,0x80,&asn_buf);
	}
	return buf_len;
}

int extract_restdataarg(struct MapRD_Arg *rsd_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int 		len;
	u8			temp_buf[256];

	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_restdataarg buf_len=0");
		return RER;
	}
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	rsd_ptr->param_flag = 0;
	len = get_tlv("4-1",temp_buf,&asn_buf);
	if (len==IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)	//get imsi
	{
		rsd_ptr->param_flag |= 0x01;
		memcpy(rsd_ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	if (get_tlv("4-2",temp_buf,&asn_buf) == LMSI_LEN)	//get lmsi
	{
		memcpy(rsd_ptr->lmsi,temp_buf,LMSI_LEN);
		rsd_ptr->param_flag |= 0x02;
	}
	len = get_tlv("6.0",temp_buf,&asn_buf);		//get camel info
	if (len != -1)
	{
		memcpy(rsd_ptr->vlr_cap.camel_phase,temp_buf,3);
		rsd_ptr->vlr_cap.param_flag = 0x01;
		rsd_ptr->param_flag |= 0x04;
	}
	return ROK;	
}

/*	++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding restore Data response		*/
/*  ++++++++++++++++++++++++++++++++++++++++	*/
int assign_restdatares(struct MapRD_Res *rsd_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);	
	if (rsd_ptr->param_flag & 0x01)	//hlr num
		buf_len = add_tlv("4",rsd_ptr->hlr_num[0],rsd_ptr->hlr_num+1,0x00,&asn_buf);
	else
		return RER;
	if (rsd_ptr->param_flag & 0x02)	//MS not reachable
		buf_len = add_null("5",0x00,&asn_buf);
	return buf_len;	
}

int extract_restdatares(struct MapRD_Res *rsd_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF	asn_buf;
	u8		temp_buf[256];
	int 	len;

	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_restdatares buf_len=0");
		return RER;
	}
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	rsd_ptr->param_flag = 0;
	if((len=get_tlv("4",temp_buf,&asn_buf)) > 2 )//get hlr number
	{
		rsd_ptr->hlr_num[0] = len;
		memcpy(rsd_ptr->hlr_num+1,temp_buf,len);
		rsd_ptr->param_flag|=0x01;
	}
	else
		return RER;
	if(get_tlv("5",temp_buf,&asn_buf) != -1)	//get MS not reachable
	{
		rsd_ptr->param_flag |= 0x02;
		rsd_ptr->msnot_reach = 1;
	}
	return ROK;	
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send routing info for GPRS argument	*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_sndroutinfogprsarg(struct MapSRIFG_Arg *sfg_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);	
	if (sfg_ptr->param_flag & 0x01)		// imsi
		buf_len = add_tlv("0",IMSI_LEN,sfg_ptr->imsi,0x80,&asn_buf);
	else
		return RER;
	if (sfg_ptr->param_flag & 0x02)		// ggsn address
		buf_len = add_tlv("1",sfg_ptr->ggsn_add[0],sfg_ptr->ggsn_add+1,0x80,&asn_buf);
	if (sfg_ptr->param_flag & 0x04)		// ggsn number
		buf_len = add_tlv("2",sfg_ptr->ggsn_num[0],sfg_ptr->ggsn_num+1,0x80,&asn_buf);
	else
		return RER;
	return buf_len;
}

int extract_sndroutinfogprsarg(struct MapSRIFG_Arg *sfg_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int 		len;
	u8			temp_buf[256];

	sfg_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_sendroutinfoforgprs buf_len=0");
		return RER;
	}
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);
	if (len==IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)	//get imsi
	{
		sfg_ptr->param_flag |= 0x01;
		memcpy(sfg_ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	len = get_tlv("1",temp_buf,&asn_buf);
	if (len > 0 && len <= GSN_LEN)	//get ggsn address
	{
		sfg_ptr->param_flag |= 0x02;
		sfg_ptr->ggsn_add[0] = len;
		memcpy(sfg_ptr->ggsn_add+1,temp_buf,len);
	}
	len = get_tlv("2",temp_buf,&asn_buf);	// get ggsn number
	if (len >0 && len <= ISDN_LEN)
	{
		sfg_ptr->param_flag |= 0x04;
		sfg_ptr->ggsn_num[0] = len;
		memcpy(sfg_ptr->ggsn_num+1,temp_buf,len);
	}
	else
		return RER;
	return ROK;	
}

/*	+++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding send routing info for GPRS response	*/
/*  +++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_sndroutinfogprsres(struct MapSRIFG_Res *sfg_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);	
	if (sfg_ptr->param_flag & 0x01)		// sgsn address
		buf_len = add_tlv("0",sfg_ptr->sgsn_add[0],sfg_ptr->sgsn_add+1,0x80,&asn_buf);
	else
		return RER;
	if (sfg_ptr->param_flag & 0x02)		// ggsn address
		buf_len = add_tlv("1",sfg_ptr->ggsn_add[0],sfg_ptr->ggsn_add+1,0x80,&asn_buf);
	if (sfg_ptr->param_flag & 0x04)		// mobile not reachable reason
		buf_len = add_tlv("2",1,&sfg_ptr->mobile_reason,0x80,&asn_buf);
	return buf_len;
}

int extract_sndroutinfogprsres(struct MapSRIFG_Res *sfg_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int 		len;
	u8			temp_buf[256];

	sfg_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_sendroutinfoforgprs res buf_len=0");
		return RER;
	}
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);
	if (len > 0 && len <= GSN_LEN)
	{
		sfg_ptr->param_flag |= 0x01;
		sfg_ptr->sgsn_add[0] = len;
		memcpy(sfg_ptr->sgsn_add+1,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	len = get_tlv("1",temp_buf,&asn_buf);
	if (len > 0 && len <= GSN_LEN)	//get ggsn address
	{
		sfg_ptr->param_flag |= 0x02;
		sfg_ptr->ggsn_add[0] = len;
		memcpy(sfg_ptr->ggsn_add+1,temp_buf,len);
	}
	if (get_tlv("2",temp_buf,&asn_buf) == 1)	// get mobile not reachable reason
	{
		sfg_ptr->param_flag |= 0x04;
		sfg_ptr->mobile_reason = temp_buf[0];
	}
	return ROK;	
}

/*	+++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding failure report argument	*/
/*  +++++++++++++++++++++++++++++++++++++++++	*/
int assign_failreportarg(struct MapFR_Arg *fr_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);	
	if (fr_ptr->param_flag & 0x01)		// imsi
		buf_len = add_tlv("0",IMSI_LEN,fr_ptr->imsi,0x80,&asn_buf);
	else
		return RER;
	if (fr_ptr->param_flag & 0x02)		// ggsn number
		buf_len = add_tlv("1",fr_ptr->ggsn_num[0],fr_ptr->ggsn_num+1,0x80,&asn_buf);
	else
		return RER;
	if (fr_ptr->param_flag & 0x04)		// ggsn address
		buf_len = add_tlv("2",fr_ptr->ggsn_add[0],fr_ptr->ggsn_add+1,0x80,&asn_buf);
	return buf_len;
}

int extract_failreportarg(struct MapFR_Arg *fr_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int 		len;
	u8			temp_buf[256];

	fr_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--extract_failure report buf_len=0");
		return RER;
	}
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);
	if (len==IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)	//get imsi
	{
		fr_ptr->param_flag |= 0x01;
		memcpy(fr_ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	len = get_tlv("1",temp_buf,&asn_buf);	// get ggsn number
	if (len >0 && len <= ISDN_LEN)
	{
		fr_ptr->param_flag |= 0x02;
		fr_ptr->ggsn_num[0] = len;
		memcpy(fr_ptr->ggsn_num+1,temp_buf,len);
	}
	else
		return RER;
	len = get_tlv("2",temp_buf,&asn_buf);
	if (len > 0 && len <= GSN_LEN)	//get ggsn address
	{
		fr_ptr->param_flag |= 0x04;
		fr_ptr->ggsn_add[0] = len;
		memcpy(fr_ptr->ggsn_add+1,temp_buf,len);
	}
	return ROK;	
}

/*	+++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding failure report response	*/
/*  +++++++++++++++++++++++++++++++++++++++++	*/
int assign_failreportres(struct MapFR_Res *fr_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);	
	if (fr_ptr->param_flag & 0x01)		// ggsn address
		buf_len = add_tlv("0",fr_ptr->ggsn_add[0],fr_ptr->ggsn_add+1,0x80,&asn_buf);
	return buf_len;
}

int extract_failreportres(struct MapFR_Res *fr_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int 		len;
	u8			temp_buf[256];

	fr_ptr->param_flag = 0;
	if (buf_len == 0)
		return ROK;
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);
	if (len > 0 && len <= GSN_LEN)	//get ggsn address
	{
		fr_ptr->param_flag |= 0x01;
		fr_ptr->ggsn_add[0] = len;
		memcpy(fr_ptr->ggsn_add+1,temp_buf,len);
	}
	return ROK;	
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding note MS present for GPRS argument		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_notemspregprsarg(struct MapNMPFG_Arg *npg_ptr,u8 *buf)
{
	ASN_BUF		asn_buf;
	int			buf_len=0;

	asn_encode(buf,&asn_buf);
	if (npg_ptr->param_flag & 0x01)		// imsi
		buf_len = add_tlv("0",IMSI_LEN,npg_ptr->imsi,0x80,&asn_buf);
	else
		return RER;
	if (npg_ptr->param_flag & 0x02)		// sgsn address
		buf_len = add_tlv("1",npg_ptr->sgsn_add[0],npg_ptr->sgsn_add+1,0x80,&asn_buf);
	else
		return RER;
	if (npg_ptr->param_flag & 0x04)		// ggsn address
		buf_len = add_tlv("2",npg_ptr->ggsn_add[0],npg_ptr->ggsn_add+1,0x80,&asn_buf);
	return buf_len;
}

int extract_notemspregprsarg(struct MapNMPFG_Arg *npg_ptr,u32 buf_len,u8 *buf)
{
	ASN_BUF		asn_buf;
	int 		len;
	u8			temp_buf[256];

	npg_ptr->param_flag = 0;
	if (buf_len == 0)
	{
		mapp_log_debug("MAPP--note ms present for gprs buf_len=0");
		return RER;
	}
	if (asn_decode_v3(buf,buf_len,&decErr,&asn_buf) == -1)
		return RER;
	len = get_tlv("0",temp_buf,&asn_buf);
	if (len==IMSI_LEN && (temp_buf[IMSI_LEN-1]&0xf0) == 0xf0)	//get imsi
	{
		npg_ptr->param_flag |= 0x01;
		memcpy(npg_ptr->imsi,temp_buf,IMSI_LEN);
	}
	else
		return RER;
	len = get_tlv("1",temp_buf,&asn_buf);	// get sgsn address
	if (len >0 && len <= GSN_LEN)
	{
		npg_ptr->param_flag |= 0x02;
		npg_ptr->sgsn_add[0] = len;
		memcpy(npg_ptr->sgsn_add+1,temp_buf,len);
	}
	else
		return RER;
	len = get_tlv("2",temp_buf,&asn_buf);	//get ggsn address
	if (len > 0 && len <= GSN_LEN)
	{
		npg_ptr->param_flag |= 0x04;
		npg_ptr->ggsn_add[0] = len;
		memcpy(npg_ptr->ggsn_add+1,temp_buf,len);
	}
	return ROK;	
}

/*	++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
/*	encoding/decoding note MS present for GPRS response		*/
/*  ++++++++++++++++++++++++++++++++++++++++++++++++++++	*/
int assign_notemspregprsres(struct MapNMPFG_Res *npg_ptr,u8 *buf)
{
	return 0;
}

int extract_notemspregprsres(struct MapNMPFG_Res *npg_ptr,u32 buf_len,u8 *buf)
{
	return ROK;
}
