FreeCalypso > hg > fc-tourmaline
diff src/g23m-gprs/sndcp/sndcp_cias.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gprs/sndcp/sndcp_cias.c Fri Oct 16 06:25:50 2020 +0000 @@ -0,0 +1,2710 @@ +/* ++----------------------------------------------------------------------------- +| Project : GPRS (8441) +| Modul : sndcp_cias.c ++----------------------------------------------------------------------------- +| Copyright 2002 Texas Instruments Berlin, AG +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments Berlin, AG +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments Berlin, AG. +| +| These files implement Van Jacobson Compression algorithm which is taken from +| University of California Berkley's Implementation. +| +| +| "Copyright (c)1989 Regents of the University of California. +| All rights reserved.Redistribution and use in source and binary forms are +| permitted, provided that the above copyright notice and this paragraph are +| duplicated in all such forms and that any documentation advertising materials, +| and other materials related to such distributionand use acknowledge that the +| software was developed by the University of California, Berkeley. +| The name of the University may not be used to endorse or promote products +| derived from this software without specific prior written permission. +| THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +| INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +| FITNESS FOR A PARTICULAR PURPOSE" ++----------------------------------------------------------------------------- +| Purpose : This modul is part of the entity SNDCP and implements all +| functions to handles the incoming process internal signals as +| described in the SDL-documentation (CIA-statemachine) ++----------------------------------------------------------------------------- +*/ + + +#define ENTITY_SNDCP + +/*==== INCLUDES =============================================================*/ + +#include "typedefs.h" /* to get Condat data types */ +#include "vsi.h" /* to get a lot of macros */ +#include "macdef.h" +#include "gsm.h" /* to get a lot of macros */ +#include "prim.h" /* to get the definitions of used SAP and directions */ + +#include "dti.h" + +#include "sndcp.h" /* to get the global entity definitions */ +#include "sndcp_f.h" /* to get the functions to access the global arrays*/ + +#include <string.h> /* to get memcpy() */ +#include "sndcp_cias.h" /* to get the signals to service cia */ +#include "sndcp_ciap.h" /* to get primitives to service cia */ +#include "sndcp_ciaf.h" /* to get primitives to service cia */ +#include "sndcp_sdf.h" /* to get sd functions */ +#include "sndcp_sdaf.h" /* to get sda functions */ +#include "sndcp_sds.h" /* to get sd signals */ + +#ifdef TI_PS_FF_V42BIS +#include "v42b_type.h" +#include "v42b_dico.h" +#include "v42b_enc.h" +#include "v42b_dec.h" +#include "v42b_debug.h" +#endif /* TI_PS_FF_V42BIS */ + +/*==== CONST ================================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + +/*==== PRIVATE FUNCTIONS ====================================================*/ + +/* + * Update connection state cs & send uncompressed packet ('uncompressed' + * means a regular ip/tcp packet but with the 'conversation id' we hope + * to use on future compressed packets in the protocol field). + */ +#define UNCOMPRESSED {\ + memcpy(cs->cs_hdr, (UBYTE*)cbuf->c_hdr, tip_hlen);\ + ip->ip_p = cs->cs_id;\ + sndcp_data->cia.comp.last_xmit = cs->cs_id;\ +} + + +/* ++------------------------------------------------------------------------------ +| Function : cia_vj_comp ++------------------------------------------------------------------------------ +| Description : compresses the TCP/IP header of the given packet +| (Van Jacobson algorithm). A part of this routine has been taken +| from implementation of University of California, Berkeley. +| +| Parameters : com_buf - received packet, packet length, packet type +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +LOCAL UBYTE cia_vj_comp(struct comp_buf *cbuf) +{ + struct cstate *cs = sndcp_data->cia.comp.last_cs->cs_next; + T_SNDCP_TCP_HEADER *oth, *oth_tmp; /* last TCP header */ + T_SNDCP_TCP_HEADER *th; /* current TCP header */ + T_SNDCP_IP_HEADER *ip; /* current IP header */ + USHORT ip_hlen, tip_hlen; /* IP hdr len., TCP/IP hdr len*/ + USHORT tmp1, tmp2; /* general purpose tempories */ + ULONG changes = 0; /* change mask */ + UBYTE new_seq[16]; /* changes from last to current*/ + UBYTE *cp = new_seq; + UBYTE th_off, oth_off; + BOOL found = FALSE; + USHORT th_sum; + ULONG seq, o_seq; + + ip = (T_SNDCP_IP_HEADER *)cbuf->c_hdr; + ip_hlen = ip->ip_vhl & HL_MASK; /* IP header length in integers */ + th = (T_SNDCP_TCP_HEADER *)&((ULONG *)cbuf->c_hdr)[ip_hlen]; + th_off = th->th_off >> 4; + + TRACE_FUNCTION( "cia_vj_comp" ); + + /* + * Bail if this is an IP fragment or if the TCP packet isn't + * `compressible' (i.e., ACK isn't set or some other control bit is + * set). (We assume that the caller has already made sure the + * packet is IP proto TCP). + */ + if (ip->ip_off & 0xff3f) + { + TRACE_EVENT("INFO COMP: return TYPE_IP, packet is an IP fragment"); + return (TYPE_IP); + } + + if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK) + { + TRACE_EVENT("INFO COMP: return TYPE_IP, TH_ACK is not set"); + return (TYPE_IP); + } + /* + * Packet is compressible -- we're going to send either a + * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need + * to locate (or create) the connection state. Special case the + * most recently used connection since it's most likely to be used + * again & we don't have to do any reordering if it's used. + */ + oth_tmp = (T_SNDCP_TCP_HEADER *) + &((ULONG *)cs->cs_hdr)[cs->cs_ip->ip_vhl & HL_MASK]; + if ((ip->ip_src != cs->cs_ip->ip_src) || + (ip->ip_dst != cs->cs_ip->ip_dst) || + (*(ULONG *)th != *(ULONG *)oth_tmp)){ + /* + * Wasn't the first -- search for it. + * + * States are kept in a circularly linked list with + * last_cs pointing to the end of the list. The + * list is kept in lru order by moving a state to the + * head of the list whenever it is referenced. Since + * the list is short and, empirically, the connection + * we want is almost always near the front, we locate + * states via linear search. If we don't find a state + * for the datagram, the oldest state is (re-)used. + */ + struct cstate *lcs; + struct cstate *lastcs = sndcp_data->cia.comp.last_cs; + + do { + lcs = cs; + cs = cs->cs_next; + oth_tmp = (T_SNDCP_TCP_HEADER *) + &((ULONG *)cs->cs_hdr)[cs->cs_ip->ip_vhl & HL_MASK]; + if ((ip->ip_src == cs->cs_ip->ip_src) && + (ip->ip_dst == cs->cs_ip->ip_dst) && + (*(ULONG *)th == *(ULONG *)oth_tmp)){ + found = TRUE; + break; + } + + } while (cs != lastcs); + + if(found) + { + /* + * Found it -- move to the front on the connection list. + */ + if (cs == lastcs) + sndcp_data->cia.comp.last_cs = lcs; + else { + lcs->cs_next = cs->cs_next; + cs->cs_next = lastcs->cs_next; + lastcs->cs_next = cs; + } + } else { + /* + * Didn't find it -- re-use oldest cstate. Send an + * uncompressed packet that tells the other side what + * connection number we're using for this conversation. + * Note that since the state list is circular, the oldest + * state points to the newest and we only need to set + * last_cs to update the lru linkage. + */ + sndcp_data->cia.comp.last_cs = lcs; + tip_hlen = (ip_hlen+th_off)<<2; + UNCOMPRESSED; + return (TYPE_UNCOMPRESSED_TCP); + }/*if din't find*/ + } + + /* + * Make sure that only what we expect to change changed. The first + * line of the `if' checks the IP protocol version, header length & + * type of service. The 2nd line checks the "Don't fragment" bit. + * The 3rd line checks the time-to-live and protocol (the protocol + * check is unnecessary but costless). The 4th line checks the TCP + * header length. The 5th line checks IP options, if any. The 6th + * line checks TCP options, if any. If any of these things are + * different between the previous & current datagram, we send the + * current datagram `uncompressed'. + */ + oth = (T_SNDCP_TCP_HEADER *)&((ULONG *)cs->cs_ip)[ip_hlen]; + oth_off = oth->th_off >> 4; + tip_hlen = (ip_hlen+th_off)<<2; + + if (((USHORT *)ip)[0] != ((USHORT *)cs->cs_ip)[0] || + ((USHORT *)ip)[3] != ((USHORT *)cs->cs_ip)[3] || + ((USHORT *)ip)[4] != ((USHORT *)cs->cs_ip)[4] || + (th_off != oth_off) || + ((ip_hlen > 5) && (memcmp(ip + 1, cs->cs_ip + 1, (ip_hlen - 5) << 2))) || + ((th_off > 5) && (memcmp(th + 1, oth + 1, (th_off - 5) << 2)))) { + + UNCOMPRESSED; + return (TYPE_UNCOMPRESSED_TCP); + } + + /* + * Figure out which of the changing fields changed. The + * receiver expects changes in the order: urgent, window, + * ack, seq (the order minimizes the number of temporaries + * needed in this section of code). + */ + if (th->th_flags & TH_URG) { + tmp1 = sndcp_swap2(th->th_urp); + if (tmp1 >= 256 || tmp1 == 0) { + *cp++ = 0; + cp[1] = (UBYTE)tmp1; + cp[0] = (tmp1 & 0xff00) >> 8; + cp += 2; + } else { + *cp++ = (UBYTE)tmp1; + } + changes |= NEW_U; + } else if (th->th_urp != oth->th_urp){ + /* argh! URG not set but urp changed -- a sensible + * implementation should never do this but RFC793 + * doesn't prohibit the change so we have to deal + * with it. */ + UNCOMPRESSED; + return (TYPE_UNCOMPRESSED_TCP); + } + if ((tmp1 = sndcp_swap2(th->th_win) - sndcp_swap2(oth->th_win)) != 0) { + if (tmp1 >= 256) { + *cp++ = 0; + cp[1] = (UBYTE)tmp1; + cp[0] = (tmp1 & 0xff00) >> 8; + cp += 2; + } else { + *cp++ = (UBYTE)tmp1; + } + changes |= NEW_W; + } + + if ((tmp2 = (USHORT)(sndcp_swap4(th->th_ack)-sndcp_swap4(oth->th_ack)))!=0){ + if (tmp2 > MAX_CHANGE){ + UNCOMPRESSED; + return (TYPE_UNCOMPRESSED_TCP); + } + if (tmp2 >= 256) { + *cp++ = 0; + cp[1] = (UBYTE)tmp2; + cp[0] = (tmp2 & 0xff00) >> 8; + cp += 2; + } else { + *cp++ = (UBYTE)tmp2; + } + changes |= NEW_A; + } + + seq = sndcp_swap4(th->th_seq); + o_seq = sndcp_swap4(oth->th_seq); + if(seq < o_seq) { + TRACE_EVENT("WARNING COMP: seq < o_seq, return UNCOMPRESSED_TCP "); + UNCOMPRESSED; + return (TYPE_UNCOMPRESSED_TCP); + } else if((tmp1 = (USHORT)(seq - o_seq)) != 0) { + if (tmp1 > MAX_CHANGE){ + UNCOMPRESSED; + return (TYPE_UNCOMPRESSED_TCP); + } + if (tmp1 >= 256) { + *cp++ = 0; + cp[1] = (UBYTE)tmp1; + cp[0] = (tmp1 & 0xff00) >> 8; + cp += 2; + } else { + *cp++ = (UBYTE)tmp1; + } + changes |= NEW_S; + } + + /* look for special case encodings. */ + switch (changes) { + + case 0: + /* + * Nothing changed. If this packet contains data and the + * last one didn't, this is probably a data packet following + * an ack (normal on an interactive connection) and we send + * it compressed. Otherwise it's probably a retransmit, + * retransmitted ack or window probe. Send it uncompressed + * in case the other side missed the compressed version. + */ + if ((ip->ip_len != cs->cs_ip->ip_len) && + (sndcp_swap2(cs->cs_ip->ip_len) == tip_hlen)) + break; + + /* (fall through) */ + + case SPECIAL_I: + case SPECIAL_D: + /* + * actual changes match one of our special case encodings -- + * send packet uncompressed. + */ + UNCOMPRESSED; + return (TYPE_UNCOMPRESSED_TCP); + + case NEW_S|NEW_A: + if ((tmp1 == tmp2) && + (tmp1 == sndcp_swap2(cs->cs_ip->ip_len) - tip_hlen)) { + /* special case for echoed terminal traffic */ + changes = SPECIAL_I; + cp = new_seq; + } + break; + + case NEW_S: + if (tmp1 == sndcp_swap2(cs->cs_ip->ip_len) - tip_hlen) { + /* special case for data xfer */ + changes = SPECIAL_D; + cp = new_seq; + } + break; + } + + tmp1 = sndcp_swap2(ip->ip_id) - sndcp_swap2(cs->cs_ip->ip_id); + if (tmp1 != 1) { + if ((tmp1 >= 256) || (tmp1 == 0)) { + *cp++ = 0; + cp[1] = (UBYTE)tmp1; + cp[0] = (tmp1 & 0xff00) >> 8; + cp += 2; + } else { + *cp++ = (UBYTE)tmp1; + } + changes |= NEW_I; + } + + if (th->th_flags & TH_PUSH) + changes |= TCP_PUSH_BIT; + /* + * Grab the cksum before we overwrite it below. Then update our + * state with this packet's header. + */ + th_sum = sndcp_swap2(th->th_sum); + memcpy(cs->cs_ip, ip, tip_hlen); + + /* + * We want to use the original packet as our compressed packet. + * (cp - new_seq) is the number of bytes we need for compressed + * sequence numbers. In addition we need one byte for the change + * mask, one for the connection id and two for the tcp checksum. + * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how + * many bytes of the original packet to toss so subtract the two to + * get the new packet size. + */ + tmp1 = cp - new_seq; + cp = (UBYTE *)ip; + + /* + * we always send a "new" connection id so the receiver state + * stays synchronized. + */ + sndcp_data->cia.comp.last_xmit = cs->cs_id; + tip_hlen -= tmp1 + 4; + cp += tip_hlen; + *cp++ = (UBYTE)(changes | NEW_C); + *cp++ = cs->cs_id; + + cbuf->pack_len -= tip_hlen; + cbuf->hdr_len -= tip_hlen; + cbuf->c_hdr += tip_hlen; + *cp++ = th_sum >> 8; + *cp++ = (UBYTE)(th_sum & 0x00ff); + memcpy(cp, new_seq, tmp1); + return (TYPE_COMPRESSED_TCP); +} + +#endif /* CF_FAST_EXEC */ + + +/* ++------------------------------------------------------------------------------ +| Function : cia_header_comp ++------------------------------------------------------------------------------ +| Description : compresses the TCP/IP header of the given packet +| (Van Jacobson algorithm) +| +| Parameters : packet as desc_list, packet_type. +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +#ifdef _SNDCP_DTI_2_ +GLOBAL void cia_header_comp (T_desc_list2* dest_desc_list, + T_desc_list2* src_desc_list, + UBYTE* packet_type) +#else /*_SNDCP_DTI_2_*/ +GLOBAL void cia_header_comp (T_desc_list* dest_desc_list, + T_desc_list* src_desc_list, + UBYTE* packet_type) +#endif /*_SNDCP_DTI_2_*/ +{ + +#ifdef _SNDCP_DTI_2_ + T_desc2* src_desc = (T_desc2*)src_desc_list->first; + T_desc2* new_desc; + U8 *src_desc_buff = &src_desc->buffer[src_desc->offset]; +#else /*_SNDCP_DTI_2_*/ + T_desc* src_desc = (T_desc*)src_desc_list->first; + T_desc* new_desc; + U8 *src_desc_buff = &src_desc->buffer[0]; +#endif /*_SNDCP_DTI_2_*/ + + +/* + * A struct mbuf is used in the call cia_vj_comp because that routine + * needs to modify both the start address and length if the incoming + * packet is compressed + */ + + struct comp_buf cbuf; + T_SNDCP_IP_HEADER *ip; + T_SNDCP_TCP_HEADER *tcp; + USHORT hdr_len; + USHORT offset; + + TRACE_FUNCTION( "cia_header_comp" ); + + if ((src_desc == NULL)) + { + TRACE_EVENT("ERROR: Descriptor Pointer is a NULLPTR"); + *packet_type = TYPE_ERROR; + return; + } + + /* + * Verify protocol type and header length + */ + ip = (T_SNDCP_IP_HEADER *)&src_desc_buff[0]; + if((ip->ip_p == PROT_TCPIP)) + { + hdr_len = (ip->ip_vhl & HL_MASK) << 2; + tcp = (T_SNDCP_TCP_HEADER *)&src_desc_buff[hdr_len]; + hdr_len += (tcp->th_off >> 4) << 2; + if( (src_desc->len >= hdr_len) && (hdr_len >=40) ){ + /* + * initialize comp_buf + */ + cbuf.hdr_len = hdr_len; /* header len. passed to compr. routine*/ + cbuf.pack_len = src_desc->len; /* descriptor length */ + cbuf.p_type = TYPE_IP; /* set default packet type */ + /* use temporary buffer to store TCP/IP header */ + cbuf.c_hdr = (ULONG)&sndcp_data->cia.comp.tcpip_hdr[0]; + memcpy((UBYTE*)cbuf.c_hdr, &src_desc_buff[0], cbuf.hdr_len); + /* + * Call VJ header compression routine + */ + *packet_type = cia_vj_comp(&cbuf); + } + else + *packet_type = TYPE_IP; + + }/* if TCP_IP_PROTOKOL */ + else{ + *packet_type = TYPE_IP; + if(src_desc->len <40) + TRACE_EVENT("INFO COMP: Descriptor length < 40"); + } + + switch(*packet_type) + { + /* + * IP packet + */ + case TYPE_IP: + /* + * if acknowledged mode + */ + if(src_desc_list != dest_desc_list) + { + dest_desc_list->first = src_desc_list->first; + dest_desc_list->list_len = src_desc_list->list_len; + } + TRACE_EVENT("INFO COMP: Header Type TYPE_IP"); + break; + + /* + * Uncompressed TCP/IP packet + */ + case TYPE_UNCOMPRESSED_TCP: + /* + * if acknowledged mode + */ + if(src_desc_list != dest_desc_list) + { +#ifdef _SNDCP_DTI_2_ + MALLOC(new_desc, (USHORT)(sizeof(T_desc2)-1+src_desc->len)); +#else + MALLOC(new_desc, (USHORT)(sizeof(T_desc)-1+src_desc->len)); +#endif + /* + * Copy data packet to destination descriptor + */ + memcpy(new_desc->buffer, src_desc_buff, src_desc->len); + /* + * store connection id + */ + new_desc->buffer[PR_TYPE_POS] = ((UBYTE*)cbuf.c_hdr)[PR_TYPE_POS] + ;/*lint !e644 !e415 !e416 creation and access of out-of-bounds pointer*/ + /* + * Build destination descriptor list + */ + new_desc->next = src_desc->next; + new_desc->len = src_desc->len; +#ifdef _SNDCP_DTI_2_ + new_desc->offset = src_desc->offset; + new_desc->size = src_desc->size; +#endif + dest_desc_list->first = (ULONG)new_desc; + dest_desc_list->list_len = src_desc_list->list_len; + } + else{ + /* + * store connection id + */ + src_desc_buff[PR_TYPE_POS] = ((UBYTE*)cbuf.c_hdr)[PR_TYPE_POS] + ;/*lint !e415 !e416 creation and access of out-of-bounds pointer */ + } + TRACE_EVENT("INFO COMP: Header Type TYPE_UNCOMPRESSED_TCP"); + break; + + + /* + * Compressed TCP/IP packet + */ + case TYPE_COMPRESSED_TCP: + /* compute compressed header length */ + offset = (USHORT)(src_desc->len - cbuf.pack_len); +#ifdef _SNDCP_DTI_2_ + MALLOC(new_desc, (USHORT)(sizeof(T_desc2) - 1 + cbuf.pack_len)); +#else + MALLOC(new_desc, (USHORT)(sizeof(T_desc) - 1 + cbuf.pack_len)); +#endif + /* + * Copy compressed header to new descriptor + */ + memcpy(&new_desc->buffer[0], (UBYTE*)cbuf.c_hdr, cbuf.hdr_len); + /* + * Copy payload to new descriptor + */ + memcpy(&new_desc->buffer[cbuf.hdr_len], + &src_desc_buff[hdr_len], cbuf.pack_len-cbuf.hdr_len) + ;/*lint !e644 !e662 Possible creation of out-of-bounds pointer */ + /* + * Build destination descriptor list + */ + new_desc->next = src_desc->next; + new_desc->len = (USHORT)cbuf.pack_len; +#ifdef _SNDCP_DTI_2_ + new_desc->offset = 0; + new_desc->size = (USHORT)cbuf.pack_len; +#endif + dest_desc_list->first = (ULONG)new_desc; + dest_desc_list->list_len = src_desc_list->list_len - offset; + /* + * if unacknowledgement mode + */ + if(src_desc_list == dest_desc_list) + { + /* + * Free source decsriptor + */ + MFREE(src_desc); + } + TRACE_EVENT("INFO COMP: Header TYPE_COMPRESSED_TCP"); + break; + + default: + TRACE_EVENT("Header Type: TYPE_ERROR"); + break; + } + +#ifdef SNDCP_TRACE_BUFFER + sndcp_trace_desc_list(dest_desc_list); +#endif /* SNDCP_TRACE_BUFFER */ + +} /* cia_header_comp*/ + +#endif /* CF_FAST_EXEC */ + + +#ifndef _SNDCP_DTI_2_ +/* ++------------------------------------------------------------------------------ +| Function : cia_su_cia_comp_req ++------------------------------------------------------------------------------ +| Description : Simulation for cia reaction to SIG_SU_CIA_DATA_REQ. +| Instead of sending the pdu to cia and then receiving +| 1 or more CIA_COMP_IND. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ + !defined(REL99) || defined(SNDCP_2to1) */ + +LOCAL void cia_su_cia_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req, + USHORT npdu_number, + UBYTE nsapi, + UBYTE sapi, + UBYTE packet_type + ) +{ + BOOL ready = FALSE; + USHORT header_size = SN_UNITDATA_PDP_HDR_LEN_BIG; + /* + * Bit offset in destination sdu. + */ + USHORT bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3); + /* + * Offset in current desc. + */ + USHORT desc_offset = 0; + USHORT sdu_len = 0; + UBYTE first = SEG_POS_FIRST; + UBYTE segment_number = 0; + T_desc_list* desc_list = &sn_unitdata_req->desc_list; + + TRACE_FUNCTION( "cia_su_cia_comp_req" ); + + while (!ready && desc_list->first != NULL) { + /* + * How long will sdu be? + */ + if (desc_list->list_len + header_size >= sndcp_data->su->n201_u) { + sdu_len = (USHORT)(sndcp_data->su->n201_u << 3); + } else { + sdu_len = (USHORT)((desc_list->list_len + header_size) << 3); + } + { + PALLOC_SDU(cia_comp_ind, CCI_COMP_IND, sdu_len); + /* + * Set parameters. + */ + + cia_comp_ind->sapi = sapi; + /* + * cia_qos is not yet used, set to 0. + */ + cia_comp_ind->cia_qos.delay = 0; + cia_comp_ind->cia_qos.relclass = 0; + cia_comp_ind->cia_qos.peak = 0; + cia_comp_ind->cia_qos.preced = 0; + cia_comp_ind->cia_qos.mean = 0; + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cia_comp_ind->algo_type = CIA_ALGO_V42; + cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0; + + cia_comp_ind->pdu_ref.ref_nsapi = nsapi; + cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number; + cia_comp_ind->pdu_ref.ref_seg_num = segment_number; + segment_number ++; + if (desc_list->list_len + header_size <= sndcp_data->su->n201_u) { + cia_comp_ind->seg_pos = first + SEG_POS_LAST; + } else { + cia_comp_ind->seg_pos = first; + } + cia_comp_ind->packet_type = packet_type; + /* + * Copy descriptors to cia_comp_ind->sdu. + */ + while (desc_list->first != NULL) { + T_desc* help = (T_desc*)desc_list->first; + USHORT cur_len = (((T_desc*)desc_list->first)->len - desc_offset); + if ((cur_len << 3) <= + cia_comp_ind->sdu.l_buf + + cia_comp_ind->sdu.o_buf - + bit_offset) { + + /* + * Copy current desc to sdu. + */ + if (cur_len>0) + { + memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3], + &((T_desc*)desc_list->first)->buffer[desc_offset], + cur_len); + } + bit_offset += (USHORT)(cur_len << 3); + desc_list->list_len -= cur_len; + + /* + * Free read desc and go to next in list. + */ + desc_list->first = help->next; + desc_offset = 0; + MFREE(help); + help = NULL; + } else { + /* + * Current desc does not fit completely in sdu. + */ + USHORT part_len = (USHORT)(cia_comp_ind->sdu.l_buf + + cia_comp_ind->sdu.o_buf - + bit_offset) + >> 3; + if (part_len > 0) + { + memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3], + &((T_desc*)desc_list->first)->buffer[desc_offset], + part_len); + desc_offset += part_len; + } + desc_list->list_len -= part_len; + + header_size = SN_UNITDATA_PDP_HDR_LEN_SMALL; + bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3); + + break; + } + } /* while (desc_list->first != NULL) { */ + /* + * Instead of PSEND(SNDCP_handle, cia_comp_ind); + */ + cia_cia_comp_ind(cia_comp_ind); + /* + * One segment sent, set 'first' to 'none'. + */ + first = SEG_POS_NONE; + } + /* + * If the desc_list is empty now, leave. + */ + + if (sn_unitdata_req->desc_list.list_len == 0) { + PFREE(sn_unitdata_req); + sn_unitdata_req = NULL; + ready = TRUE; + } + } + +} /* cia_su_cia_comp_req() */ +/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */ + +#else /* _SNDCP_DTI_2_ */ +/* ++------------------------------------------------------------------------------ +| Function : cia_su_cia_comp_req ++------------------------------------------------------------------------------ +| Description : This function is used, if no data compression is used in +| uplink. It does only the segmentation of the incoming data. +| +| Simulation for cia reaction to SIG_SU_CIA_DATA_REQ. +| Instead of sending the pdu to cia and then receiving +| 1 or more CIA_COMP_IND. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ + !defined(REL99) || defined(SNDCP_2to1) */ + +LOCAL void cia_su_cia_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req, + USHORT npdu_number, + UBYTE nsapi, + UBYTE sapi, + UBYTE packet_type + ) +{ + BOOL ready = FALSE; + U16 header_size = SN_UNITDATA_PDP_HDR_LEN_BIG; + U16 desc2_data_struct_offset = 0; + U8 first = SEG_POS_FIRST; + U8 segment_number = 0; + U32* segment_header; + T_desc_list2* desc_list2 = &sn_unitdata_req->desc_list2; + T_desc_list3 desc_list3; + T_desc3* desc3; + T_desc3* current_desc3; + /* + * Offset in current desc. Set the desc_offset to the offset of + * the first desc in the list that is to be read. + */ + U16 desc_offset = ((T_desc2*)desc_list2->first)->offset; + + TRACE_FUNCTION( "cia_su_cia_comp_req" ); + + while (!ready && desc_list2->first != NULL) + { + /* + * How long will the segment be? + */ + desc_list3.first = NULL; + desc_list3.list_len = 0; + if ((desc_list2->list_len + header_size) >= sndcp_data->su->n201_u) + { + desc_list3.list_len = (USHORT)sndcp_data->su->n201_u; + } + else + { + desc_list3.list_len = (USHORT)(desc_list2->list_len + header_size); + } + + { + T_CIA_COMP_IND *cia_comp_ind; + MALLOC(cia_comp_ind, sizeof(T_CIA_COMP_IND)); + /* + * Set parameters. + */ + + cia_comp_ind->sapi = sapi; + /* + * cia_qos is not yet used, set to 0. + */ + cia_comp_ind->cia_qos.delay = 0; + cia_comp_ind->cia_qos.relclass = 0; + cia_comp_ind->cia_qos.peak = 0; + cia_comp_ind->cia_qos.preced = 0; + cia_comp_ind->cia_qos.mean = 0; + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cia_comp_ind->algo_type = CIA_ALGO_V42; + cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0; + + cia_comp_ind->pdu_ref.ref_nsapi = nsapi; + cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number; + cia_comp_ind->pdu_ref.ref_seg_num = segment_number; + segment_number ++; + + /* Allocate memory for SNDCP header and LLC encode offset */ + MALLOC (segment_header, (USHORT)(ENCODE_OFFSET_BYTE + header_size)); + + MALLOC (desc3, (U16)(sizeof(T_desc3))); + /* + * Fill desc3 descriptor control information. + */ + desc3->next = (U32)NULL; + desc3->len = header_size; + desc3->offset = ENCODE_OFFSET_BYTE; + desc3->buffer = (U32)segment_header; + desc_list3.first = (U32)desc3; + current_desc3 = desc3; + + if (desc_list2->list_len + header_size <= sndcp_data->su->n201_u) + { + cia_comp_ind->seg_pos = first + SEG_POS_LAST; + } else { + cia_comp_ind->seg_pos = first; + } + cia_comp_ind->packet_type = packet_type; + cia_comp_ind->desc_list3.first = desc_list3.first; + cia_comp_ind->desc_list3.list_len = desc_list3.list_len; + + desc_list3.list_len = 0; + desc_list3.list_len += desc3->len; + /* + * Copy descriptors to cia_comp_ind->desc_list3, list may have to be built. + */ + while (desc_list2->first != NULL) + {/* This while moves data from desc2 to segment defined by desc3 descriptors*/ + T_desc2* help = (T_desc2*)desc_list2->first; + U16 cur_len = (((T_desc2*)desc_list2->first)->len - desc_offset); + desc2_data_struct_offset = offsetof(T_desc2, buffer); + if (cur_len <= (sndcp_data->su->n201_u - desc_list3.list_len)) + {/* Is there room for all the desc2 data in the current segment */ + + /* + * describe current desc2 by desc3 descriptors. + */ + + MALLOC (desc3, (USHORT)(sizeof(T_desc3))); + /* + * Fill desc3 descriptor control information. + */ + desc3->next = (U32)NULL; + desc3->len = cur_len; + desc3->offset = desc_offset + desc2_data_struct_offset; + desc3->buffer = (U32)desc_list2->first; + current_desc3->next = (U32)desc3; + current_desc3 = desc3; + desc_list3.list_len += desc3->len; + + /* Attach desc3 to desc2 allocation, this is always the last + attach on a desc2 descriptor */ + sndcp_cl_desc2_attach(help); + + desc_list2->list_len -= cur_len; + + /* + * Free read desc and go to next in list. + */ + desc_list2->first = help->next; + /* + * If another desc is present in the list to be read, then + * set the desc_offset to the offset of the next desc in the + * list that is to be read. Else set desc_offset to zero + */ + if (desc_list2->first != NULL) + { + desc_offset = ((T_desc2*)desc_list2->first)->offset; + } + else + { + desc_offset = 0; + } + MFREE(help); + help = NULL; + } else { + /* + * Current desc does not fit completely in sdu. + */ + + USHORT part_len = (USHORT)(sndcp_data->su->n201_u - desc_list3.list_len); + + if (part_len > 0) + { + MALLOC (desc3, (USHORT)(sizeof(T_desc3))); + /* + * Fill desc3 descriptor control information. + */ + desc3->next = (ULONG)NULL; + desc3->len = part_len; + desc3->offset = desc_offset + desc2_data_struct_offset; + desc3->buffer = (ULONG)desc_list2->first; + current_desc3->next = (ULONG)desc3; + current_desc3 = desc3; + desc_list3.list_len += desc3->len; + + /* Attach desc3 to desc2 allocation, this is an intermediate + attach on a desc2 descriptor */ + sndcp_cl_desc2_attach(help); + + desc_offset += part_len; + } + desc_list2->list_len -= part_len; + + header_size = SN_UNITDATA_PDP_HDR_LEN_SMALL; + break; + } + } /* while (desc_list->first != NULL) { */ + + /* + * Instead of PSEND(SNDCP_handle, cia_comp_ind); + */ + cia_cia_comp_ind(cia_comp_ind); + /* + * One segment sent, set 'first' to 'none'. + */ + first = SEG_POS_NONE; + } + /* + * If the desc_list is empty now, leave. + */ + if (sn_unitdata_req->desc_list2.list_len == 0) { + + MFREE(sn_unitdata_req); + sn_unitdata_req = NULL; + ready = TRUE; + } + } +} /* cia_su_cia_comp_req() */ +/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */ + +#ifdef TI_PS_FF_V42BIS +/* ++------------------------------------------------------------------------------ +| Function : cia_su_cci_comp_req ++------------------------------------------------------------------------------ +| Description : This function is used, if data compression is used in uplink +| direction. At first it calls the data compression function with +| parameters, that allow a segmentation without memcopy. Than it +| does the segmentation. +| +| Simulation for CCI reaction to SIG_SU_CIA_DATA_REQ. +| Instead of sending the pdu to CCI and then receiving +| 1 or more CCI_COMP_IND. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ + !defined(REL99) || defined(SNDCP_2to1) */ + +LOCAL void cia_su_cci_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req, + USHORT npdu_number, + UBYTE nsapi, + UBYTE sapi, + UBYTE packet_type + ) +{ + BOOL ready = FALSE; + U16 header_size = SN_UNITDATA_PDP_HDR_LEN_BIG; + U16 desc2_data_struct_offset = offsetof(T_desc2, buffer); + U8 segment_position = SEG_POS_FIRST; + U8 segment_number = 0; + U32* segment_header; + T_desc_list2* desc_list2 = &sn_unitdata_req->desc_list2; + T_desc2* desc2; + T_desc_list3 desc_list3; + T_desc3* desc3; + T_desc3* current_desc3; + + U8 descs_per_seg = 5; + U8 i; + U16 desc_size = (sndcp_data->su->n201_u - header_size - + (desc2_data_struct_offset + 1) * descs_per_seg) / + descs_per_seg + + desc2_data_struct_offset + 1; + + + + + + + TRACE_FUNCTION( "cia_su_cci_comp_req" ); + TRACE_EVENT_P1("sn_unitdata_req in: %08x", sn_unitdata_req); + //TRACE_EVENT_P1("PacketType: %d",packet_type); + + /* + * Reset V.42 context and call the encoder routine + */ + //TRACE_EVENT_P1("V42 ENC: Input Uncompressed Packet, length %d", desc_list2->list_len); +#ifdef SNDCP_TRACE_BUFFER + //sndcp_trace_desc_list(desc_list2); +#endif + v42b_init(sndcp_data->cia.enc, 0, 0, 0, 0); + TRACE_FUNCTION ("as reinit in uplink"); + /* + * the function can be called with 0s as parameters, because it was initialized + * befor what the function sees on the valid magic number + * + * the call replaces an independent reinit function + */ + v42b_encoder(sndcp_data->cia.enc, desc_list2, NULL, desc_size); + //TRACE_EVENT_P1("V42 ENC: Output Compresset Packet, length %d", desc_list2->list_len); +#ifdef SNDCP_TRACE_BUFFER + //sndcp_trace_desc_list(desc_list2); +#endif + + + desc2 = (T_desc2*)desc_list2->first; + + while (desc2) + { + + + + desc_list3.first = (U32) NULL; + desc_list3.list_len = 0; + + + MALLOC(segment_header, (ENCODE_OFFSET_BYTE + header_size)); + MALLOC(desc3,sizeof(T_desc3)); + + desc3->next = (U32) NULL; + desc3->len = header_size; + desc3->offset = ENCODE_OFFSET_BYTE; + desc3->buffer = (U32)segment_header; + + desc_list3.first = (U32)desc3; + desc_list3.list_len = desc3->len; + + current_desc3 = desc3; + + for (i = 0; (i < descs_per_seg) && desc2; i++) + { + MALLOC(desc3,sizeof(T_desc3)); + + desc3->next = (U32) NULL; + desc3->len = desc2->len; + desc3->offset = desc2->offset + desc2_data_struct_offset; + desc3->buffer = (U32)desc2; + + current_desc3->next = (U32) desc3; + current_desc3 = desc3; + desc_list3.list_len += desc3->len; + + desc2 = (T_desc2*) desc2->next; + } + header_size = SN_UNITDATA_PDP_HDR_LEN_SMALL; + + { + T_CIA_COMP_IND *cia_comp_ind; + MALLOC(cia_comp_ind, sizeof(T_CIA_COMP_IND)); + /* + * Set parameters. + */ + + cia_comp_ind->sapi = sapi; + /* + * cci_qos is not yet used, set to 0. + */ + cia_comp_ind->cia_qos.delay = 0; + cia_comp_ind->cia_qos.relclass = 0; + cia_comp_ind->cia_qos.peak = 0; + cia_comp_ind->cia_qos.preced = 0; + cia_comp_ind->cia_qos.mean = 0; + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cia_comp_ind->algo_type = CCI_ALGO_V42; + cia_comp_ind->comp_inst = CCI_COMP_INST_V42_0; + + cia_comp_ind->pdu_ref.ref_nsapi = nsapi; + cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number; + cia_comp_ind->pdu_ref.ref_seg_num = segment_number; + segment_number ++; + + if (desc2 != NULL) + { + cia_comp_ind->seg_pos = segment_position; + } + else + { + cia_comp_ind->seg_pos = segment_position | SEG_POS_LAST; + } + + cia_comp_ind->packet_type = packet_type; + cia_comp_ind->desc_list3.first = desc_list3.first; + cia_comp_ind->desc_list3.list_len = desc_list3.list_len; + + /* + * Instead of PSEND(SNDCP_handle, cci_comp_ind); + */ + cia_cia_comp_ind(cia_comp_ind); + /* + * One segment sent, set 'first' to 'none'. + */ + segment_position = SEG_POS_NONE; + } + } + /* + * If the desc_list2 is empty now, leave. + */ + TRACE_EVENT_P1("sn_unitdata_req out: %08x", sn_unitdata_req); + MFREE(sn_unitdata_req); + sn_unitdata_req = NULL; +} +/*#endif */ /* FAST_EXEC */ +#endif /* TI_PS_FF_V42BIS */ +#endif /* _SNDCP_DTI_2_ */ + +#ifdef _SNDCP_DTI_2_ +/* ++------------------------------------------------------------------------------ +| Function : cia_sua_cia_comp_req ++------------------------------------------------------------------------------ +| Description : Simulation for cia reaction to SIG_SUA_CIA_DATA_REQ. +| Instead of sending the pdu to cia and then receiving +| 1 or more CIA_COMP_IND. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +LOCAL void cia_sua_cia_comp_req (T_desc_list2 dest_desc_list, + U8 npdu_number, + U8 nsapi, + U8 sapi, + U8 packet_type + ) +{ + BOOL ready = FALSE; + U16 header_size = SN_DATA_PDP_HDR_LEN_BIG; + U16 desc2_data_struct_offset = 0; + U8 first = SEG_POS_FIRST; + U8 segment_number = 0; + U32* segment_header; + T_desc_list2* desc_list2 = &dest_desc_list; + T_desc_list3 desc_list3; + T_desc3* desc3; + T_desc3* current_desc3; + USHORT list_len = desc_list2->list_len; + T_desc2* help = (T_desc2*)desc_list2->first; + T_desc2* delhelp = NULL; + + /* + * Offset in current descriptor Set the desc_offset to the offset of + * the first desc in the list that is to be read. + */ + U16 desc_offset = help->offset; + + TRACE_FUNCTION( "cia_sua_cia_comp_req" ); + + while (!ready && help != NULL) { + /* + * How long will the segment be? + */ + desc_list3.first = NULL; + desc_list3.list_len = 0; + if ((list_len + header_size) >= sndcp_data->sua->n201_i) + { + desc_list3.list_len = (U16)sndcp_data->sua->n201_i; + } + else + { + desc_list3.list_len = (U16)(list_len + header_size); + } + + { + /* + * First desc in list must be header!!! + */ + BOOL first_part = TRUE; + + T_CIA_COMP_IND *cia_comp_ind; + MALLOC(cia_comp_ind, sizeof(T_CIA_COMP_IND)); + /* + * Set parameters. + */ + cia_comp_ind->sapi = sapi; + /* + * cia_qos is not yet used, set to 0. + */ + cia_comp_ind->cia_qos.delay = 0; + cia_comp_ind->cia_qos.relclass = 0; + cia_comp_ind->cia_qos.peak = 0; + cia_comp_ind->cia_qos.preced = 0; + cia_comp_ind->cia_qos.mean = 0; + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cia_comp_ind->algo_type = CIA_ALGO_V42; + cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0; + + cia_comp_ind->pdu_ref.ref_nsapi = nsapi; + cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number; + cia_comp_ind->pdu_ref.ref_seg_num = segment_number; + segment_number ++; + + /* Allocate memory for SNDCP header and LLC encode offset */ + MALLOC (segment_header, (U16)(ENCODE_OFFSET_BYTE + header_size)); + + MALLOC (desc3, (U16)(sizeof(T_desc3))); + /* + * Fill desc3 descriptor control information. + */ + desc3->next = (U32)NULL; + desc3->len = header_size; + desc3->offset = ENCODE_OFFSET_BYTE; + desc3->buffer = (U32)segment_header; + desc_list3.first = (U32)desc3; + current_desc3 = desc3; + + if (list_len + header_size <= sndcp_data->sua->n201_i) + { + cia_comp_ind->seg_pos = first + SEG_POS_LAST; + } else { + cia_comp_ind->seg_pos = first; + } + cia_comp_ind->packet_type = packet_type; + cia_comp_ind->desc_list3.first = desc_list3.first; + cia_comp_ind->desc_list3.list_len = desc_list3.list_len; + + desc_list3.list_len = 0; + desc_list3.list_len += desc3->len; + /* + * Copy descriptors to cia_comp_ind->desc_list3, list may have to be built. + */ + while (help != NULL) + {/* + * This while moves data from desc2 to segment defined + * by desc3 descriptors + */ + U16 cur_len = (help->len - desc_offset); + desc2_data_struct_offset = offsetof(T_desc2, buffer); + if (cur_len <= (sndcp_data->sua->n201_i - desc_list3.list_len)) + {/* Is there room for all the desc2 data in the current segment */ + /* + * describe current desc2 by desc3 descriptors. + */ + if (cur_len>0) + { + MALLOC (desc3, (U16)(sizeof(T_desc3))); + /* + * Fill desc3 descriptor control information. + */ + desc3->next = (U32)NULL; + desc3->len = cur_len; + desc3->offset = desc_offset + desc2_data_struct_offset; + desc3->buffer = (U32)help; + current_desc3->next = (ULONG)desc3; + current_desc3 = desc3; + desc_list3.list_len += desc3->len; + + /* Attach desc3 to desc2 allocation, this is always the last + attach on a desc2 descriptor */ + sndcp_cl_desc2_attach(help); + + } + list_len -= cur_len; + + /* + * Free read desc and go to next in list. + */ + if (help != NULL) + { + delhelp = help; + help = (T_desc2*)help->next; + } + /* + * If another desc is present in the list to be read, then + * set the desc_offset to the offset of the next desc in the + * list that is to be read. Else set desc_offset to zero + */ + if (help != NULL) + { + desc_offset = help->offset; + } + else + { + desc_offset = 0; + } + if (delhelp != NULL && + first_part && + (packet_type == TYPE_COMPRESSED_TCP || + packet_type == TYPE_UNCOMPRESSED_TCP)) { + + MFREE(delhelp); + delhelp = NULL; + first_part = FALSE; + } + } + else + { + /* + * Current desc does not fit completely in sdu. + */ + + U16 part_len = (USHORT)(sndcp_data->sua->n201_i-desc_list3.list_len); + + if (part_len>0) + { + MALLOC (desc3, (USHORT)(sizeof(T_desc3))); + /* + * Fill desc3 descriptor control information. + */ + desc3->next = (ULONG)NULL; + desc3->len = part_len; + desc3->offset = desc_offset + desc2_data_struct_offset; + desc3->buffer = (ULONG)help; + current_desc3->next = (ULONG)desc3; + current_desc3 = desc3; + desc_list3.list_len += desc3->len; + + /* Attach desc3 to desc2 allocation, this is an intermediate + attach on a desc2 descriptor */ + sndcp_cl_desc2_attach(help); + + desc_offset += part_len; + } + list_len -= part_len; + + header_size = SN_DATA_PDP_HDR_LEN_SMALL; + break; + } + } + /* + * Instead of PSEND(SNDCP_handle, cia_comp_ind); + */ + cia_cia_comp_ind(cia_comp_ind); + /* + * One segment sent, set 'first' to 'none'. + */ + first = SEG_POS_NONE; + } + /* + * If the desc_list is empty now, leave. + */ + if (list_len == 0) { + ready = TRUE; + } + } +} /* cia_sua_cia_comp_req() */ + +#endif /* CF_FAST_EXEC */ + +#else /* _SNDCP_DTI_2_ */ +/* ++------------------------------------------------------------------------------ +| Function : cia_sua_cia_comp_req ++------------------------------------------------------------------------------ +| Description : Simulation for cia reaction to SIG_SUA_CIA_DATA_REQ. +| Instead of sending the pdu to cia and then receiving +| 1 or more CIA_COMP_IND. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +LOCAL void cia_sua_cia_comp_req (T_desc_list dest_desc_list, + UBYTE npdu_number, + UBYTE nsapi, + UBYTE sapi, + UBYTE packet_type + ) +{ + BOOL ready = FALSE; + USHORT header_size = SN_DATA_PDP_HDR_LEN_BIG; + USHORT bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3); + USHORT desc_offset = 0; + USHORT sdu_len = 0; + UBYTE first = SEG_POS_FIRST; + UBYTE segment_number = 0; + T_desc_list* desc_list = &dest_desc_list; + USHORT list_len = desc_list->list_len; + T_desc* help = (T_desc*)desc_list->first; + T_desc* delhelp = NULL; + + USHORT help_buffer_offset = 0; + + TRACE_FUNCTION( "cia_sua_cia_comp_req" ); + + while (!ready && help != NULL) { + /* + * How long will sdu be? + */ + if (list_len + header_size >= sndcp_data->sua->n201_i) { + sdu_len = (USHORT)(sndcp_data->sua->n201_i << 3); + } else { + sdu_len = (USHORT)((list_len + header_size) << 3); + } + { + /* + * First desc in list must be header!!! + */ + BOOL first_part = TRUE; + + PALLOC_SDU(cia_comp_ind, CCI_COMP_IND, sdu_len); + /* + * Set parameters. + */ + cia_comp_ind->sapi = sapi; + /* + * cia_qos is not yet used, set to 0. + */ + cia_comp_ind->cia_qos.delay = 0; + cia_comp_ind->cia_qos.relclass = 0; + cia_comp_ind->cia_qos.peak = 0; + cia_comp_ind->cia_qos.preced = 0; + cia_comp_ind->cia_qos.mean = 0; + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cia_comp_ind->algo_type = CIA_ALGO_V42; + cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0; + + cia_comp_ind->pdu_ref.ref_nsapi = nsapi; + cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number; + cia_comp_ind->pdu_ref.ref_seg_num = segment_number; + segment_number ++; + if (list_len + header_size <= sndcp_data->sua->n201_i) { + cia_comp_ind->seg_pos = first + SEG_POS_LAST; + } else { + cia_comp_ind->seg_pos = first; + } + cia_comp_ind->packet_type = packet_type; + /* + * Copy descriptors to cia_comp_ind->sdu. + */ + while (help != NULL) { + USHORT cur_len = (help->len - desc_offset); + + if ((cur_len << 3) <= + cia_comp_ind->sdu.l_buf + + cia_comp_ind->sdu.o_buf - + bit_offset) { + + /* + * Copy current desc to sdu. + */ + if (cur_len>0) + { + memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3], + &help->buffer[desc_offset], + cur_len); + } + bit_offset += (USHORT)(cur_len << 3); + list_len -= cur_len; + + /* + * Free read desc and go to next in list. + */ + if (help != NULL) { + delhelp = help; + help = (T_desc*)help->next; + } + help_buffer_offset = 0; + desc_offset = 0; + if (delhelp != NULL && + first_part && + (packet_type == TYPE_COMPRESSED_TCP || + packet_type == TYPE_UNCOMPRESSED_TCP)) { + + MFREE(delhelp); + delhelp = NULL; + first_part = FALSE; + } + } else { + /* + * Current desc does not fit completely in sdu. + */ + desc_offset = (USHORT)(cia_comp_ind->sdu.l_buf + + cia_comp_ind->sdu.o_buf - + bit_offset) + >> 3; + if (desc_offset>0) + { + memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3], + &help->buffer[help_buffer_offset], + desc_offset); + help_buffer_offset += (desc_offset); + } + list_len -= desc_offset; + + header_size = SN_DATA_PDP_HDR_LEN_SMALL; + bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3); + break; + } + } + /* + * Instead of PSEND(SNDCP_handle, cia_comp_ind); + */ + cia_cia_comp_ind(cia_comp_ind); + /* + * One segment sent, set 'first' to 'none'. + */ + first = SEG_POS_NONE; + } + /* + * If the desc_list is empty now, leave. + */ + if (list_len == 0) { + ready = TRUE; + } + } + +} /* cia_sua_cia_comp_req() */ + +#endif /* CF_FAST_EXEC */ + +#endif /*_SNDCP_DTI_2_*/ + + +/* ++------------------------------------------------------------------------------ +| Function : cia_sd_cia_decomp_req ++------------------------------------------------------------------------------ +| Description : This Function does the defragmentation for noncompressed data. +| +| Simulation for cia reaction to SIG_SD_CIA_TRANSFER_REQ. +| If (cur_seg_pos & SEG_POS_FIRST > 0) then a new CIA_DECOMP_IND is allocated. +| T_desc is allocated with the length of the sdu included in the +| ll_unitdata_ind. The sdu data is copied to the desc and the desc is added to +| the currently assembled desc_list in the current CIA_DECOMP_IND. +| If (cur_seg_pos & SEG_POS_LAST > 0) then a the CIA_DECOMP_IND is now complete +| and is "sent to this service" by calling the cia function cia_cia_decomp_ind. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ + !defined(REL99) || defined(SNDCP_2to1) */ + +GLOBAL void cia_sd_cia_decomp_req(T_LL_UNITDATA_IND* ll_unitdata_ind) +{ + USHORT length = 0; + USHORT header_len = SN_UNITDATA_PDP_HDR_LEN_SMALL; + USHORT sdu_index = 0; + T_CIA_DECOMP_IND *cur_cia_decomp_ind; + UBYTE nsapi; +#ifdef _SNDCP_DTI_2_ + T_desc2* help = NULL; + T_desc2* descriptor = NULL; +#else /*_SNDCP_DTI_2_*/ + T_desc* help = NULL; + T_desc* descriptor = NULL; +#endif /*_SNDCP_DTI_2_*/ + + TRACE_FUNCTION( "cia_sd_cia_decomp_req" ); + + nsapi = (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf / 8)]) & 0xf; + cur_cia_decomp_ind = sndcp_data->cia.cur_cia_decomp_ind[nsapi]; + + /* + * In case of first segment allocate new N-PDU. + */ + if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_FIRST) > 0) { + { + + T_CIA_DECOMP_IND *cia_decomp_ind; + MALLOC(cia_decomp_ind, sizeof(T_CIA_DECOMP_IND)); + +#ifdef SNDCP_TRACE_ALL + + sndcp_data->cia.cia_decomp_ind_number[nsapi] ++; + TRACE_EVENT_P1("number of cia_decomp_ind: % d", + sndcp_data->cia.cia_decomp_ind_number[nsapi]); +#endif /* SNDCP_TRACE_ALL */ + + + /* + * if there is an unfinished cur_cia_decomp_ind deallocate it together + * with the allocated descriptors + */ + if (cur_cia_decomp_ind NEQ NULL) + { + MFREE_PRIM(cur_cia_decomp_ind); + TRACE_EVENT("Deallocate unfinished cur_cia_decomp_ind"); + } + cur_cia_decomp_ind = cia_decomp_ind; + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cur_cia_decomp_ind->algo_type = CIA_ALGO_V42; + cur_cia_decomp_ind->comp_inst = CIA_COMP_INST_V42_0; + + cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi]; + cur_cia_decomp_ind->desc_list2.first = (ULONG)NULL; + cur_cia_decomp_ind->desc_list2.list_len = 0; + + header_len = SN_UNITDATA_PDP_HDR_LEN_BIG; + cia_decomp_ind->pcomp = + ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf >> 3) + 1] & 0xf; + } + } + /* + * If big header has been received in state != RECEIVE_FIRST_SEGMENT + */ + if (sndcp_data->big_head[nsapi]) { + header_len = SN_UNITDATA_PDP_HDR_LEN_BIG; + } + sdu_index = (ll_unitdata_ind->sdu.o_buf >> 3) + header_len; + length = (ll_unitdata_ind->sdu.l_buf >> 3) - header_len; + /* + * Allocate new descriptor and copy sdu data. + */ +#ifdef _SNDCP_DTI_2_ + MALLOC (descriptor, (USHORT)(sizeof(T_desc2) - 1 + length)); +#else /*_SNDCP_DTI_2_*/ + MALLOC (descriptor, (USHORT)(sizeof(T_desc) - 1 + length)); +#endif /*_SNDCP_DTI_2_*/ + + /* + * Fill descriptor control information. + */ + descriptor->next = (ULONG)NULL; + descriptor->len = length; +#ifdef _SNDCP_DTI_2_ + descriptor->offset = 0; + descriptor->size = descriptor->len; +#endif + + /* + * Add length of descriptor data to list length. + */ + cur_cia_decomp_ind->desc_list2.list_len += length; + + /* + * Copy user data from SDU to descriptor. + */ + if (length>0) + { + memcpy (descriptor->buffer, + &ll_unitdata_ind->sdu.buf[sdu_index], + length); + } + + /* + * Add desc to desc_list. + */ +#ifdef _SNDCP_DTI_2_ + help = (T_desc2*)cur_cia_decomp_ind->desc_list2.first; +#else /*_SNDCP_DTI_2_*/ + help = (T_desc*)cur_cia_decomp_ind->desc_list2.first; +#endif /*_SNDCP_DTI_2_*/ + if (help == NULL) { + cur_cia_decomp_ind->desc_list2.first = (ULONG)descriptor; + } else { + if (help->next == NULL) { + help->next = (ULONG) descriptor; + } else { + while (help->next != NULL) { +#ifdef _SNDCP_DTI_2_ + help = (T_desc2*)help->next; +#else /*_SNDCP_DTI_2_*/ + help = (T_desc*)help->next; +#endif /*_SNDCP_DTI_2_*/ + } + help->next = (ULONG)descriptor; + } + } + + /* + * If this is the last segment, send it to this same service with a simulated + * primitive. + */ + if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_LAST) > 0) { + /* + * By now algo_type, cia_qos and comp_inst are not evaluated. + */ + cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi]; + cia_cia_decomp_ind(cur_cia_decomp_ind); + cur_cia_decomp_ind = NULL; + } else { + /* + * Request next segment. + */ + sd_get_unitdata_if_nec(ll_unitdata_ind->sapi); + } + /* + * Update global current CIA_DECOMP_IND + */ + sndcp_data->cia.cur_cia_decomp_ind[nsapi] = cur_cia_decomp_ind; + /* + * Free incoming prim. + */ + if (ll_unitdata_ind != NULL) { + PFREE (ll_unitdata_ind); + ll_unitdata_ind = NULL; + } +} /* cia_sd_cia_decomp_req() */ + +/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */ + +#ifdef TI_PS_FF_V42BIS +/* ++------------------------------------------------------------------------------ +| Function : cia_sd_cci_decomp_req ++------------------------------------------------------------------------------ +| Description : This function does the desegmentation and decomressoin for +| compressed data. +| +| Simulation for CCI reaction to SIG_SD_CIA_TRANSFER_REQ. +| If (cur_seg_pos & SEG_POS_FIRST > 0) then a new CCI_DECOMP_IND is allocated. +| T_desc is allocated with the length of the sdu included in the +| ll_unitdata_ind. The sdu data is copied to the desc and the desc is added to +| the currently assembled desc_list in the current CCI_DECOMP_IND. +| If (cur_seg_pos & SEG_POS_LAST > 0) then a the CCI_DECOMP_IND is now complete +| and is "sent to this service" by calling the cia function cia_cci_decomp_ind. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ + !defined(REL99) || defined(SNDCP_2to1) */ + +LOCAL void cia_sd_cci_decomp_req (/*T_pdu_ref pdu_ref, + USHORT cur_seg_pos, + */T_LL_UNITDATA_IND* ll_unitdata_ind + ) +{ + + USHORT length = 0; + USHORT header_len = SN_UNITDATA_PDP_HDR_LEN_SMALL; + USHORT sdu_index = 0; + T_CIA_DECOMP_IND *cur_cia_decomp_ind; + UBYTE nsapi; +#ifdef _SNDCP_DTI_2_ + T_desc2* help = NULL; + T_desc2* descriptor = NULL; +#else /*_SNDCP_DTI_2_*/ + T_desc* help = NULL; + T_desc* descriptor = NULL; +#endif /*_SNDCP_DTI_2_*/ + + TRACE_FUNCTION( "cia_sd_cci_decomp_req" ); + + nsapi = (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf / 8)]) & 0xf; + cur_cia_decomp_ind = sndcp_data->cia.cur_cia_decomp_ind[nsapi]; + + /* + * In case of first segment allocate new N-PDU. + */ + if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_FIRST) > 0) + { + { + T_CIA_DECOMP_IND *cia_decomp_ind; + MALLOC(cia_decomp_ind, sizeof(T_CIA_DECOMP_IND)); + +#ifdef SNDCP_TRACE_ALL + + sndcp_data->cia.cia_decomp_ind_number[nsapi] ++; + TRACE_EVENT_P1("number of cia_decomp_ind: % d", + sndcp_data->cia.cia_decomp_ind_number[nsapi]); +#endif /* SNDCP_TRACE_ALL */ + + + /* + * if there is an unfinished cur_cia_decomp_ind deallocate it together + * with the allocated descriptors + */ + if (cur_cia_decomp_ind NEQ NULL) + { + MFREE_PRIM(cur_cia_decomp_ind); + TRACE_EVENT("Deallocate unfinished cur_cia_decomp_ind"); + } + cur_cia_decomp_ind = cia_decomp_ind; + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cur_cia_decomp_ind->algo_type = CIA_ALGO_V42; + cur_cia_decomp_ind->comp_inst = CIA_COMP_INST_V42_0; + + cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi]; + cur_cia_decomp_ind->desc_list2.first = (ULONG)NULL; + cur_cia_decomp_ind->desc_list2.list_len = 0; + + header_len = SN_UNITDATA_PDP_HDR_LEN_BIG; + cia_decomp_ind->pcomp = + ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf >> 3) + 1] & 0xf; + } + } + /* + * If big header has been received in state != RECEIVE_FIRST_SEGMENT + */ + if (sndcp_data->big_head[nsapi]) { + header_len = SN_UNITDATA_PDP_HDR_LEN_BIG; + } + sdu_index = (ll_unitdata_ind->sdu.o_buf >> 3) + header_len; + length = (ll_unitdata_ind->sdu.l_buf >> 3) - header_len; + /* + * Allocate new descriptor and copy sdu data. + */ +#ifdef _SNDCP_DTI_2_ + MALLOC (descriptor, (USHORT)(sizeof(T_desc2) - 1 + length)); +#else /*_SNDCP_DTI_2_*/ + MALLOC (descriptor, (USHORT)(sizeof(T_desc) - 1 + length)); +#endif /*_SNDCP_DTI_2_*/ + + /* + * Fill descriptor control information. + */ + descriptor->next = (ULONG)NULL; + descriptor->len = length; +#ifdef _SNDCP_DTI_2_ + descriptor->offset = 0; + descriptor->size = descriptor->len; +#endif + + /* + * Add length of descriptor data to list length. + */ + cur_cia_decomp_ind->desc_list2.list_len += length; + + /* + * Copy user data from SDU to descriptor. + */ + if (length>0) + { + memcpy (descriptor->buffer, + &ll_unitdata_ind->sdu.buf[sdu_index], + length); + } + + /* + * Add desc to desc_list. + */ +#ifdef _SNDCP_DTI_2_ + help = (T_desc2*)cur_cia_decomp_ind->desc_list2.first; +#else /*_SNDCP_DTI_2_*/ + help = (T_desc*)cur_cia_decomp_ind->desc_list2.first; +#endif /*_SNDCP_DTI_2_*/ + if (help == NULL) { + cur_cia_decomp_ind->desc_list2.first = (ULONG)descriptor; + } else { + if (help->next == NULL) { + help->next = (ULONG) descriptor; + } else { + while (help->next != NULL) { +#ifdef _SNDCP_DTI_2_ + help = (T_desc2*)help->next; +#else /*_SNDCP_DTI_2_*/ + help = (T_desc*)help->next; +#endif /*_SNDCP_DTI_2_*/ + } + help->next = (ULONG)descriptor; + } + } + + /* + * If this is the last segment, send it to this same service with a simulated + * primitive. + */ + if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_LAST) > 0) + { + T_desc_list2 desc_list2; + /* + * By now algo_type, cci_qos and comp_inst are not evaluated. + */ + cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi]; + + desc_list2.first = cur_cia_decomp_ind->desc_list2.first; + desc_list2.list_len = cur_cia_decomp_ind->desc_list2.list_len; + + /* + * Reset V.42 context and call the decoder routine. + */ + TRACE_EVENT_P1("V42 DEC: Input Compresset Packet, length %d", desc_list2.list_len); +#ifdef SNDCP_TRACE_BUFFER + sndcp_trace_desc_list(&desc_list2); + + sndcp_data->cia.trabu[0] = 0;/////////////////////////////////////////////////////////////// + +#endif + v42b_init(sndcp_data->cia.dec, 0, 0, 0, 0); + TRACE_EVENT ("as reinit in downlink"); + /* + * the function can be called with 0s as parameters, because it was initialized + * befor what the function sees on the valid magic number + * + * the call replaces an independent reinit function + */ + v42b_decoder(sndcp_data->cia.dec, &desc_list2, NULL, 100); + if (!IS_ERROR(sndcp_data->cia.dec)) + { + TRACE_EVENT_P1("V42 DEC: Output Decompressed Packet, length %d", desc_list2.list_len); +#ifdef SNDCP_TRACE_BUFFER + sndcp_trace_desc_list(&desc_list2); +#endif + + cur_cia_decomp_ind->desc_list2.first = desc_list2.first; + cur_cia_decomp_ind->desc_list2.list_len = desc_list2.list_len; + + cia_cia_decomp_ind(cur_cia_decomp_ind); + cur_cia_decomp_ind = NULL; + } + else + { + MFREE_PRIM (cur_cia_decomp_ind); + cur_cia_decomp_ind = NULL; + TRACE_EVENT("Deallocate corrupted V.42 bis packet"); + + /* + * Request next segment. + */ + sd_get_unitdata_if_nec(ll_unitdata_ind->sapi); + } + } + else + { + /* + * Request next segment. + */ + sd_get_unitdata_if_nec(ll_unitdata_ind->sapi); + } + /* + * Update global current CIA_DECOMP_IND + */ + sndcp_data->cia.cur_cia_decomp_ind[nsapi] = cur_cia_decomp_ind; + /* + * Free incoming prim. + */ + if (ll_unitdata_ind != NULL) { + PFREE (ll_unitdata_ind); + ll_unitdata_ind = NULL; + } +} /* cia_sd_cci_decomp_req_sim() */ + +/* #endif *//* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */ +#endif /* TI_PS_FF_V42BIS */ + +/* ++------------------------------------------------------------------------------ +| Function : sig_sda_cia_cia_decomp_req ++------------------------------------------------------------------------------ +| Description : Simulation for cia reaction to SIG_SDA_CIA_TRANSFER_REQ. +| If (cur_seg_pos & SEG_POS_FIRST > 0) then a new CIA_DECOMP_IND is allocated. +| T_desc is allocated with the length of the sdu included in the +| ll_data_ind. The sdu data is copied to the desc and the desc is added to +| the currently assembled desc_list in the current CCI_DECOMP_IND. +| If (cur_seg_pos & SEG_POS_LAST > 0) then a the CIA_DECOMP_IND is now complete +| and is "sent to this service" by calling the cia function cia_cia_decomp_ind. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +GLOBAL void sig_sda_cia_cia_decomp_req ( T_LL_DATA_IND* ll_data_ind ) +{ + USHORT length = 0; + USHORT header_len = SN_DATA_PDP_HDR_LEN_SMALL; + USHORT sdu_index = 0; + T_CIA_DECOMP_IND *cur_cia_decomp_ind; + UBYTE nsapi = 0; +#ifdef _SNDCP_DTI_2_ + T_desc2* help = NULL; + T_desc2* local_desc = NULL; +#else /*_SNDCP_DTI_2_*/ + T_desc* help = NULL; + T_desc* local_desc = NULL; +#endif /*_SNDCP_DTI_2_*/ + + TRACE_FUNCTION( "cia_sig_sda_cia_cia_decomp_req_sim" ); + + nsapi = (ll_data_ind->sdu.buf[(ll_data_ind->sdu.o_buf / 8)]) & 0xf; + cur_cia_decomp_ind = sndcp_data->cia.cur_cia_decomp_ind[nsapi]; + + /* + * In case of first segment allocate new N-PDU. + */ + if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_FIRST) > 0) { + + T_CIA_DECOMP_IND *cia_decomp_ind; + MALLOC(cia_decomp_ind, sizeof(T_CIA_DECOMP_IND)); + +#ifdef SNDCP_TRACE_ALL + sndcp_data->cia.cia_decomp_ind_number[nsapi] ++; + TRACE_EVENT_P1("number of cia_decomp_ind: % d", + sndcp_data->cia.cia_decomp_ind_number[nsapi]); +#endif + + if (cur_cia_decomp_ind NEQ NULL) + { + MFREE_PRIM(cur_cia_decomp_ind); + TRACE_EVENT("Deallocate unfinished cur_cia_decomp_ind"); + } + + cur_cia_decomp_ind = cia_decomp_ind; + + /* + * Will be changed as soon as more that 1 instance of V42.bis is used. + */ + cur_cia_decomp_ind->algo_type = CIA_ALGO_V42; + cur_cia_decomp_ind->comp_inst = CIA_COMP_INST_V42_0; + + cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi]; + cur_cia_decomp_ind->desc_list2.first = (ULONG)NULL; + cur_cia_decomp_ind->desc_list2.list_len = 0; + + header_len = SN_DATA_PDP_HDR_LEN_BIG; + cia_decomp_ind->pcomp = + ll_data_ind->sdu.buf[(ll_data_ind->sdu.o_buf >> 3) + 1] & 0xf; + + } + /* + * If big header has been received in state != RECEIVE_FIRST_SEGMENT + */ + if (sndcp_data->big_head[nsapi]) { + header_len = SN_DATA_PDP_HDR_LEN_BIG; + } + sdu_index = (ll_data_ind->sdu.o_buf >> 3) + header_len; + + if ((ll_data_ind->sdu.l_buf >> 3) < header_len){ + /*This condition is added as part of fix for GCF 46.1.2.2.3.2 failure because of wrong length*/ + TRACE_ERROR("SNDCP: Unexpected Length of N-PDU"); + PFREE (ll_data_ind); + ll_data_ind = NULL; + return; + }else{ + + length = (ll_data_ind->sdu.l_buf >> 3) - header_len; + } + + /* + * Allocate new descriptor and copy sdu data. + */ +#ifdef _SNDCP_DTI_2_ + MALLOC (local_desc, (USHORT)(sizeof(T_desc2) - 1 + length)); +#else /*_SNDCP_DTI_2_*/ + MALLOC (local_desc, (USHORT)(sizeof(T_desc) - 1 + length)); +#endif /*_SNDCP_DTI_2_*/ + + /* + * Fill descriptor control information. + */ + local_desc->next = (ULONG)NULL; + local_desc->len = length; +#ifdef _SNDCP_DTI_2_ + local_desc->offset = 0; + local_desc->size = local_desc->len; +#endif + /* + * Add length of descriptor data to list length. + */ + cur_cia_decomp_ind->desc_list2.list_len += length; + + /* + * Copy user data from SDU to descriptor. + */ + if (length>0) + { + memcpy (local_desc->buffer, &ll_data_ind->sdu.buf[sdu_index], length); + } + + /* + * Add desc to desc_list. + */ +#ifdef _SNDCP_DTI_2_ + help = (T_desc2*)cur_cia_decomp_ind->desc_list2.first; +#else /*_SNDCP_DTI_2_*/ + help = (T_desc*)cur_cia_decomp_ind->desc_list2.first; +#endif /*_SNDCP_DTI_2_*/ + if (help == NULL) { + cur_cia_decomp_ind->desc_list2.first = (ULONG)local_desc; + } else { + if (help->next == NULL) { + help->next = (ULONG) local_desc; + } else { + while (help->next != NULL) { +#ifdef _SNDCP_DTI_2_ + help = (T_desc2*)help->next; +#else /*_SNDCP_DTI_2_*/ + help = (T_desc*)help->next; +#endif /*_SNDCP_DTI_2_*/ + } + help->next = (ULONG)local_desc; + } + } + /* + * If this is the last segment, send it to this same service with a simulated + * primitive. + */ + if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_LAST) > 0) { + /* + * By now algo_type and comp_inst are not evaluated. + */ + cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi]; + cia_cia_decomp_ind(cur_cia_decomp_ind); + cur_cia_decomp_ind = NULL; + /* + * Reset the Current Segment Counter to zero, since we have received the + * last segment + */ + sndcp_data->cur_segment_number[nsapi] = 0; + } else { + /* + * Check the Current Segment Number whether we have received more than + * SNDCP_MAX_SEGMENT_NUMBER segments or not. If we have received more than + * SNDCP_MAX_SEGMENT_NUMBER segments in a single NPDU, then we will discard + * the stored segments and also the remaining segments of this NPDU, till + * we receive that last segment of this NPDU. + * This has been done in order to encounter the PARTITION problem which + * we will face if we keep on storing the segments in SNDCP. + */ + sndcp_data->cur_segment_number[nsapi] ++; + if (sndcp_data-> cur_segment_number[nsapi] > SNDCP_MAX_SEGMENT_NUMBER) + { + TRACE_EVENT("Segment Number in Single NPDU exceeds max segment number"); + + /* Deleting the stored segments */ + sig_mg_cia_delete_npdus(nsapi); + + /* Change the state to SDA_ACK_DISCARD */ + sndcp_set_nsapi_rec_state(nsapi, SDA_ACK_DISCARD); + } + + /* + * Request next segment. + */ + sda_get_data_if_nec(ll_data_ind->sapi); + } + /* + * Update global current CIA_DECOMP_IND + */ + sndcp_data->cia.cur_cia_decomp_ind[nsapi] = cur_cia_decomp_ind; + /* + * Free incoming prim. + */ + if (ll_data_ind != NULL) { + PFREE (ll_data_ind); + ll_data_ind = NULL; + } +} /* cia_sig_sda_cia_cia_decomp_req_sim() */ + +#endif /* CF_FAST_EXEC */ + + +/*==== PUBLIC FUNCTIONS =====================================================*/ + +/* ++------------------------------------------------------------------------------ +| Function : sig_mg_cia_reset_ind ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_MG_CIA_RESET_IND +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +GLOBAL void sig_mg_cia_reset_ind (void) +{ + TRACE_ISIG( "sig_mg_cia_reset_ind" ); + + switch( GET_STATE(CIA) ) + { + case CIA_DEFAULT: + sndcp_reset_xid_block(&sndcp_data->cia.cur_xid_block); + break; + default: + TRACE_ERROR( "SIG_MG_CIA_RESET_IND unexpected" ); + break; + } +} /* sig_mg_cia_reset_ind() */ + +#endif /* CF_FAST_EXEC */ + + +/* ++------------------------------------------------------------------------------ +| Function : sig_su_cia_cia_comp_req ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_SU_CIA_CIA_COMP_REQ +| This function makes a decision whether we are using data +| compression in uplink direction and calls the according +| function. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ + defined(SNDCP_2to1) */ + +GLOBAL void sig_su_cia_cia_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req, + USHORT npdu_number, + UBYTE nsapi, + UBYTE sapi + ) +{ + U8 direction = 0; + BOOL compressed = FALSE; + UBYTE packet_type = TYPE_IP; + TRACE_ISIG( "sig_su_cia_cia_comp_req" ); + + switch( GET_STATE(CIA) ) + { + case CIA_DEFAULT: + sndcp_is_nsapi_header_compressed(nsapi, &compressed); + if (compressed) { +#ifdef _SNDCP_DTI_2_ + cia_header_comp(&sn_unitdata_req->desc_list2, + &sn_unitdata_req->desc_list2, + &packet_type); +#else /*_SNDCP_DTI_2_*/ + cia_header_comp(&sn_unitdata_req->desc_list, + &sn_unitdata_req->desc_list, + &packet_type); +#endif /*_SNDCP_DTI_2_*/ + } + + sndcp_is_nsapi_data_compressed(nsapi, &compressed); + if (sndcp_data->cia.cur_xid_block.v42.is_set) + { + if (sndcp_data->cia.cur_xid_block.v42.p0_set) + { + direction = sndcp_data->cia.cur_xid_block.v42.p0; + TRACE_EVENT_P1("dir: %d",direction); + } + } + if (compressed && (direction & 0x01)) { /* datacompr. in uplink ? */ +#ifdef TI_PS_FF_V42BIS + + cia_su_cci_comp_req(sn_unitdata_req, + npdu_number, + nsapi, + sapi, + packet_type); + +#else /* !TI_PS_FF_V42BIS */ + TRACE_EVENT("INFO CIA: Data compression is not implemented yet!"); + MFREE_PRIM(sn_unitdata_req); + sn_unitdata_req = NULL; + +#endif /* TI_PS_FF_V42BIS */ + } else { /* if (compressed) */ + cia_su_cia_comp_req(sn_unitdata_req, + npdu_number, + nsapi, + sapi, + packet_type); + } + break; + default: + TRACE_ERROR( "SIG_SU_CIA_CIA_COMP_REQ unexpected" ); +#ifdef _SNDCP_DTI_2_ + MFREE_PRIM(sn_unitdata_req); +#else /*_SNDCP_DTI_2_*/ + PFREE_DESC(sn_unitdata_req); +#endif /*_SNDCP_DTI_2_*/ + break; + } +} /* sig_su_cia_cia_comp_req() */ + +/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */ + +/* ++------------------------------------------------------------------------------ +| Function : sig_sua_cia_cia_comp_req ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_SUA_CIA_CIA_COMP_REQ +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +GLOBAL void sig_sua_cia_cia_comp_req (T_SN_DATA_REQ* sn_data_req, + UBYTE npdu_number, + UBYTE nsapi, + UBYTE sapi + ) +{ + BOOL compressed = FALSE; + UBYTE packet_type = TYPE_IP; + /* + * define desc_list for comp header. Is initialized later. + */ +#ifdef _SNDCP_DTI_2_ + T_desc_list2 dest_desc_list; +#else /*_SNDCP_DTI_2_*/ + T_desc_list dest_desc_list; +#endif /*_SNDCP_DTI_2_*/ + + TRACE_ISIG( "sig_sua_cia_cia_comp_req" ); + + switch( GET_STATE(CIA) ) + { + case CIA_DEFAULT: + sndcp_is_nsapi_header_compressed(nsapi, &compressed); + if (compressed) { +#ifdef _SNDCP_DTI_2_ + cia_header_comp(&dest_desc_list, + &sn_data_req->desc_list2, + &packet_type); + } else { + dest_desc_list = sn_data_req->desc_list2; +#else /*_SNDCP_DTI_2_*/ + cia_header_comp(&dest_desc_list, + &sn_data_req->desc_list, + &packet_type); + } else { + dest_desc_list = sn_data_req->desc_list; +#endif /*_SNDCP_DTI_2_*/ + } + + sndcp_is_nsapi_data_compressed(nsapi, &compressed); + if (compressed) { + + /* + * The data compression routine shall be invoked here. + */ + TRACE_EVENT("INFO CIA: Data compression is not implemented yet!"); + MFREE_PRIM(sn_data_req); + sn_data_req = NULL; + + } else { /* if (compressed) */ + cia_sua_cia_comp_req(dest_desc_list, + npdu_number, + nsapi, + sapi, + packet_type); + } + /* + * free comp header + */ + if (compressed && dest_desc_list.first != 0) { + MFREE(dest_desc_list.first); + dest_desc_list.first = 0; + } + break; + default: + TRACE_ERROR( "SIG_SUA_CIA_CIA_COMP_REQ unexpected" ); +#ifdef _SNDCP_DTI_2_ + MFREE_PRIM(sn_data_req); +#else /*_SNDCP_DTI_2_*/ + PFREE_DESC(sn_data_req); +#endif /*_SNDCP_DTI_2_*/ + break; + } +} /* sig_sua_cia_cia_comp_req() */ + +#endif /* CF_FAST_EXEC */ + + +/* ++------------------------------------------------------------------------------ +| Function : sig_mg_cia_delete_npdus ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_MG_CIA_DELETE_NPDUS +| +| Parameters : nsapi +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +GLOBAL void sig_mg_cia_delete_npdus (UBYTE nsapi) +{ + TRACE_ISIG( "sig_mg_cia_delete_npdus" ); + + switch( GET_STATE(CIA) ) + { + case CIA_DEFAULT: + if (sndcp_data->cia.cur_cia_decomp_ind[nsapi] != NULL) { +#ifdef SNDCP_TRACE_ALL + sndcp_data->cia.cia_decomp_ind_number[nsapi] --; + TRACE_EVENT_P1("number of cia_decomp_ind: % d", + sndcp_data->cia.cia_decomp_ind_number[nsapi]); +#endif /* SNDCP_TRACE_ALL */ + /* + * Currently assembled pdu is for given nsapi. + */ + MFREE_PRIM(sndcp_data->cia.cur_cia_decomp_ind[nsapi]); + sndcp_data->cia.cur_cia_decomp_ind[nsapi] = NULL; + } + break; + default: + TRACE_ERROR( "SIG_MG_CIA_DELETE_XID unexpected" ); + break; + } +} /* SIG_MG_CIA_DELETE_NPDUS() */ + +#endif /* CF_FAST_EXEC */ + + +/* ++------------------------------------------------------------------------------ +| Function : sig_mg_cia_new_xid ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_MG_CIA_NEW_XID +| +| Parameters : new T_XID_BLOCK +| ++------------------------------------------------------------------------------ +*/ +#ifndef CF_FAST_EXEC + +GLOBAL void sig_mg_cia_new_xid (T_XID_BLOCK* new_xid) +{ +#ifdef TI_PS_FF_V42BIS + T_XID_BLOCK* old_xid; + U8 p0 = SNDCP_V42_DEFAULT_DIRECTION; + U16 p1 = SNDCP_V42_DEFAULT_P1; + U8 p2 = SNDCP_V42_DEFAULT_P2; + + old_xid = &(sndcp_data->cia.cur_xid_block); +#endif + + TRACE_ISIG( "sig_mg_cia_new_xid" ); + + switch( GET_STATE(CIA) ) + { + case CIA_DEFAULT: + if (new_xid->vj.is_set) { + if (new_xid->vj.s0_m_1_set) { + cia_compress_init((UBYTE)(new_xid->vj.s0_m_1)); + } + } +#ifdef TI_PS_FF_V42BIS + if (new_xid->v42.is_set) + { + /* block is valid */ + if (new_xid->v42.p0_set) + { + p0 = new_xid->v42.p0; + /* what have we to do, if p0 is not set? */ + } + if (new_xid->v42.p1_set) + { + p1 = new_xid->v42.p1; + /* what have we to do, if p1 is not set? */ + } + if (new_xid->v42.p2_set) + { + p2 = new_xid->v42.p2; + /* what have we to do, if p2 is not set? */ + } + + if (new_xid->v42.nsapis_set && new_xid->v42.nsapis == 0) + { + /* no applicable NSAPI + * turn off data compression in either direction + */ + if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x1) /* uplink */ + { + TRACE_EVENT_P1("1 enc dico:%08x",sndcp_data->cia.enc); + v42b_deinit(sndcp_data->cia.enc); + MFREE(sndcp_data->cia.enc); + TRACE_EVENT("uplink deinit"); + } + if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x2) /* downlink */ + { + TRACE_EVENT_P1("1 dec dico:%08x",sndcp_data->cia.dec); + v42b_deinit(sndcp_data->cia.dec); + MFREE(sndcp_data->cia.dec); + TRACE_EVENT("downlink deinit"); + } + } + else if (old_xid->v42.is_set) + { + /* currently we have a valid xid-block for data compression + * we have to check the parameters + */ + + /* we have to check the parameters */ + if (old_xid->v42.p0 != p0 || + old_xid->v42.p1 != p1 || + old_xid->v42.p2 != p2) + { + /* parameters have changed */ + if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x1) /* uplink */ + { + TRACE_EVENT_P1("2 enc dico:%08x",sndcp_data->cia.enc); + v42b_deinit(sndcp_data->cia.enc); + MFREE(sndcp_data->cia.enc); + TRACE_EVENT("uplink deinit"); + } + if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x2) /* downlink */ + { + TRACE_EVENT_P1("2 dec dico:%08x",sndcp_data->cia.dec); + v42b_deinit(sndcp_data->cia.dec); + MFREE(sndcp_data->cia.dec); + TRACE_EVENT("uplink deinit"); + } + /* we have to init with new parameters */ + if (p0 & 0x1)/* uplink */ + { + TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO)); + MALLOC(sndcp_data->cia.enc, sizeof(T_V42B_DICO)); + TRACE_EVENT_P1("enc dico:%08x",sndcp_data->cia.enc); + v42b_init(sndcp_data->cia.enc, p1, p2, 50, BANK_SIZE_512); + TRACE_EVENT("uplink init"); + } + if (p0 & 0x2)/* downlink */ + { + TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO)); + MALLOC(sndcp_data->cia.dec, sizeof(T_V42B_DICO)); + v42b_init(sndcp_data->cia.dec, p1, p2, 0, BANK_SIZE_512); + TRACE_EVENT_P1("dec dico:%08x",sndcp_data->cia.dec); + TRACE_EVENT("downlink init"); + } + } + } + else + { + /* currently we have no valid xid-block for data comprssion */ + if (p0 & 0x1)/* uplink */ + { + TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO)); + MALLOC(sndcp_data->cia.enc, sizeof(T_V42B_DICO)); + TRACE_EVENT_P1("enc dico:%08x",sndcp_data->cia.enc); + v42b_init(sndcp_data->cia.enc, p1, p2, 50, BANK_SIZE_512); + TRACE_EVENT("uplink init"); + } + if (p0 & 0x2)/* downlink */ + { + TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO)); + MALLOC(sndcp_data->cia.dec, sizeof(T_V42B_DICO)); + TRACE_EVENT_P1("dec dico:%08x",sndcp_data->cia.dec); + v42b_init(sndcp_data->cia.dec, p1, p2, 0, BANK_SIZE_512); + TRACE_EVENT("downlink init"); + } + } + } + else + { + if (old_xid->v42.is_set && old_xid->v42.nsapis_set && old_xid->v42.nsapis != 0) + { + /* we have no XID with V42 set */ + if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x1) /* uplink */ + { + TRACE_EVENT_P1("3 enc dico:%08x",sndcp_data->cia.enc); + v42b_deinit(sndcp_data->cia.enc); + MFREE(sndcp_data->cia.enc); + TRACE_EVENT("uplink deinit"); + } + if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x2) /* downlink */ + { + TRACE_EVENT_P1("3 dec dico:%08x",sndcp_data->cia.dec); + v42b_deinit(sndcp_data->cia.dec); + MFREE(sndcp_data->cia.dec); + TRACE_EVENT("downlink deinit"); + } + } + } +#endif /* TI_PS_FF_V42BIS */ + sndcp_data->cia.cur_xid_block = *new_xid; + break; + default: + TRACE_ERROR( "SIG_MG_CIA_NEW_XID unexpected" ); + break; + } +} /* SIG_MG_CIA_NEW_XID() */ + +#endif /* CF_FAST_EXEC */ + +/* ++------------------------------------------------------------------------------ +| Function : sig_sd_cia_cia_decomp_req ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_SD_CIA_TRANSFER_REQ +| This function mekes a decision whether we are using data +| compression in downlink direction and calls the according +| function. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ + defined(SNDCP_2to1) */ + +GLOBAL void sig_sd_cia_cia_decomp_req (T_LL_UNITDATA_IND* ll_unitdata_ind)/*UBYTE dcomp, + T_pdu_ref pdu_ref, + USHORT cur_seg_pos, + T_LL_UNITDATA_IND* ll_unitdata_ind + )*/ +{ +#ifdef TI_PS_FF_V42BIS + U8 direction = 0; + U8 nsapi; +#endif /* TI_PS_FF_V42BIS */ + TRACE_ISIG( "sig_sd_cia_cia_decomp_req" ); +#ifdef TI_PS_FF_V42BIS + nsapi = (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf / 8)]) & 0xf; +#endif /* TI_PS_FF_V42BIS */ + switch( GET_STATE(CIA) ) + { + case CIA_DEFAULT: +#ifdef TI_PS_FF_V42BIS + if (sndcp_data->cia.cur_xid_block.v42.is_set) + { + if (sndcp_data->cia.cur_xid_block.v42.p0_set) + { + direction = sndcp_data->cia.cur_xid_block.v42.p0; + TRACE_EVENT_P1("dir: %d",direction); + } + } + /* + * Is dcomp in sdu equal to dcomp in cur_xid_block and downlink? + */ + TRACE_EVENT_P1("our dcomp value: %d", sndcp_data->cia.cur_xid_block.v42.dcomp); + TRACE_EVENT_P1("receipt dcomp value: %d", sndcp_data->cur_dcomp[nsapi]); + if (sndcp_data->cur_dcomp[nsapi] == sndcp_data->cia.cur_xid_block.v42.dcomp && (direction & 0x2)) + { + /* + * Compression used + */ + cia_sd_cci_decomp_req(/*pdu_ref, cur_seg_pos, */ll_unitdata_ind); + + } else { + /* + * No compression used, request will not be sent to CCI, but handled + * in cia service. + */ + cia_sd_cia_decomp_req (/*pdu_ref, cur_seg_pos, */ll_unitdata_ind); + } +#else /* ! TI_PS_FF_V42BIS */ + cia_sd_cia_decomp_req (/*pdu_ref, cur_seg_pos, */ll_unitdata_ind); +#endif /* TI_PS_FF_V42BIS */ + + break; + default: + TRACE_ERROR( "SIG_SD_CIA_TRANSFER_REQ unexpected" ); + break; + } +} /* sig_sd_cia_cia_decomp_req() */ +/*#endif */