FreeCalypso > hg > freecalypso-sw
diff gsm-fw/g23m-aci/aci/conc_sms.c @ 775:eedbf248bac0
gsm-fw/g23m-aci subtree: initial import from LoCosto source
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 12 Oct 2014 01:45:14 +0000 |
parents | |
children | b63b6e9da6cd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/g23m-aci/aci/conc_sms.c Sun Oct 12 01:45:14 2014 +0000 @@ -0,0 +1,2876 @@ +/* ++----------------------------------------------------------------------------- +| Project : $Workfile:: +| Modul : CONC_SMS ++----------------------------------------------------------------------------- +| 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. ++----------------------------------------------------------------------------- +| Purpose : SMS Concatenation Handler ++----------------------------------------------------------------------------- +*/ + +#ifndef CONC_SMS_C +#define CONC_SMS_C +#endif + +/*==== INCLUDES ===================================================*/ + +#include "aci_all.h" + +#include "aci_cmh.h" +#include "ati_cmd.h" +#include "aci_cmd.h" + +#include "aci_fd.h" +#include "aci_mem.h" + +#include "psa.h" +#include "psa_sms.h" + +#include "cmh.h" +#include "cmh_sms.h" + +#include "psa_cc.h" + +#include "typedefs.h" +#include "aci_lst.h" + +#include "psa_util.h" +#include "conc_sms.h" + +#ifdef _CONC_TESTING_ +#include "aci_io.h" +#include "aci_mfw.h" +#endif + +/*==== VARIABLES ==================================================*/ + +GLOBAL T_SM_ASSEMBLY assembly_list[MAX_BUF_ELEMS]; +GLOBAL T_SEG_BUF segBuf_list [MAX_BUF_ELEMS]; +GLOBAL T_CONC_BUF concBuf_list [MAX_CONC_BUF_ELEMS]; +LOCAL USHORT RefNum_Del = 0xFF; +LOCAL BOOL dFLAG = FALSE; +LOCAL CHAR Addres[MAX_SMS_ADDR_DIG]; + + + +/*==== FUNCTIONS ==================================================*/ + +LOCAL void concSMS_printConcatList (); +LOCAL USHORT concSMS_findMaxRefNum(void); // Marcus: Issue 872: 03/10/2002 + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_findSeqNumSB | ++--------------------------------------------------------------------+ + + PURPOSE : find 'seq_num' in segment buffer +*/ +LOCAL BOOL concSMS_findSeqNumSB ( UBYTE critrerium, + void *elem ) +{ + T_SEG_BUF_ELEM *compared = (T_SEG_BUF_ELEM *)elem; + + if ( compared->seq_num == critrerium ) + return TRUE; + else + return FALSE; +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_findSeqNumElemCB | ++--------------------------------------------------------------------+ + + PURPOSE : find 'seq_num' in concatenation buffer +*/ +LOCAL BOOL concSMS_findSeqNumElemCB ( UBYTE critrerium, + void *elem ) +{ + T_CONC_BUF_ELEM *compared = (T_CONC_BUF_ELEM *)elem; + + if ( compared->seq_num == critrerium ) + return TRUE; + else + return FALSE; +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_findRecNumElemCB | ++--------------------------------------------------------------------+ + + PURPOSE : find 'rec_num' in concatenation buffer +*/ +LOCAL BOOL concSMS_findRecNumElemCB ( UBYTE critrerium, + void *elem ) +{ + T_CONC_BUF_ELEM *compared = (T_CONC_BUF_ELEM *)elem; + + if ( compared->rec_num == critrerium ) + return TRUE; + else + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_getAsBuffer | ++--------------------------------------------------------------------+ + + PURPOSE : This functions searchs the assembly buffer for ref_num + and address. +*/ +LOCAL T_SM_ASSEMBLY* concSMS_getAsBuffer( USHORT ref_num, CHAR *address ) +{ + UBYTE i; + + TRACE_FUNCTION ("concSMS_getAsBuffer()"); + + /* search for the element */ + for (i=0; i<MAX_BUF_ELEMS; i++) + { + if ( (assembly_list[i].ref_num EQ ref_num) AND + (assembly_list[i].in_use) ) + { + if ((address NEQ NULL) /* AND (address[0] NEQ '\0') */) + { + if (!strcmp(assembly_list[i].address, address)) + { + return &assembly_list[i]; + } + } + else + { + return &assembly_list[i]; + } + } + } + + return NULL; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_addToAsBuffer | ++--------------------------------------------------------------------+ + + PURPOSE : This function adds data to the assembly buffer. It returns + NULL if buffer is full. + +*/ +LOCAL T_SM_ASSEMBLY* concSMS_addToAsBuffer ( USHORT ref_num, + CHAR *address, + UBYTE max_num, + T_SM_DATA_EXT *data ) +{ + UBYTE i; + T_SM_ASSEMBLY *assembly_elem = NULL; + + TRACE_FUNCTION ("concSMS_addToAsBuffer()"); + + + /* search for the element */ + assembly_elem = concSMS_getAsBuffer( ref_num, address ); + +#ifdef _CONC_TESTING_ + TRACE_EVENT_P1("addToAsBuffer:[0].in_use: %d", assembly_list[0].in_use); + TRACE_EVENT_P1("addToAsBuffer:[1].in_use: %d", assembly_list[1].in_use); +#endif + + /* element not found */ + if (assembly_elem EQ NULL) + { + /* search for an unused list entry */ + for (i=0; i<MAX_BUF_ELEMS; i++) + { + if (assembly_list[i].in_use EQ FALSE) + { + assembly_elem = &assembly_list[i]; + break; + } + } + + /* buffer is full */ + if (assembly_elem EQ NULL) + return NULL; + + + /* create new assembly buffer for this ref_num*/ + assembly_elem->in_use = TRUE; + assembly_elem->ref_num = ref_num; + + if ( (address NEQ NULL) AND (address[0] NEQ '\0') ) + strcpy(assembly_elem->address, address); + else + assembly_elem->address[0] = '\0'; + + assembly_elem->next_exp_num = 1; + assembly_elem->segs_left = max_num; + assembly_elem->seg_count = 0; + } /* if (assembly_elem EQ NULL) */ + + if (assembly_elem->seg_count EQ 0) + { + /* alloc memory for data to assemble */ + + UBYTE segs; + + segs = MINIMUM(assembly_elem->segs_left, CONC_MAX_SEGS); + ACI_MALLOC(assembly_elem->data.data, (USHORT)(MAX_SM_LEN*segs)); + assembly_elem->segs_left -= segs; + assembly_elem->data.len = 0; + } + + memcpy(assembly_elem->data.data+assembly_elem->data.len, + data->data, data->len); + + assembly_elem->data.len += data->len; + assembly_elem->data.data[assembly_elem->data.len] = '\0'; + assembly_elem->next_exp_num++; + assembly_elem->seg_count++; + +#ifdef _CONC_TESTING_ + if (assembly_elem->data.len < TTRACE_LEN) + { + TRACE_EVENT_P1("addToAsBuffer:data.data: %s", assembly_elem->data.data); + } + TRACE_EVENT_P1("addToAsBuffer:data.len: %d", assembly_elem->data.len); + TRACE_EVENT_P1("addToAsBuffer:next_exp_num: %d", assembly_elem->next_exp_num); + TRACE_EVENT_P1("addToAsBuffer:seg_count: %d", assembly_elem->seg_count); +#endif + + return assembly_elem; +} + + +/* ++---------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_removeFromAsBuffer | ++---------------------------------------------------------------------+ + + PURPOSE : This functions gets data from the assembly buffer and + sets it to 'unused'. The assembly is completed. + +*/ +LOCAL UBYTE concSMS_removeFromAsBuffer(T_SM_DATA_EXT *data_conc, + USHORT ref_num, + CHAR *address) +{ + T_SM_ASSEMBLY *assembly_buf; + + TRACE_FUNCTION ("concSMS_removeFromAsBuffer()"); + + + /* search for the element */ + assembly_buf = concSMS_getAsBuffer( ref_num, address ); + + if (assembly_buf EQ NULL) + return FALSE; + + assembly_buf->in_use = FALSE; + + data_conc->data = assembly_buf->data.data; + data_conc->len = assembly_buf->data.len; + + return TRUE; +} + + +/* ++---------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_getFromAsBuffer | ++---------------------------------------------------------------------+ + + PURPOSE : This functions gets data from the assembly buffer and + resets the seg_count. The assembly buffer is still in use + and the assembly is not completed. + +*/ +LOCAL UBYTE concSMS_getFromAsBuffer(T_SM_DATA_EXT *data_conc, + USHORT ref_num, + CHAR *address) +{ + T_SM_ASSEMBLY *assembly_buf; + + TRACE_FUNCTION ("concSMS_getFromAsBuffer()"); + + + /* search for the element */ + assembly_buf = concSMS_getAsBuffer( ref_num, address ); + + /* assemlby buffer not found */ + if (assembly_buf EQ NULL) + return FALSE; + + assembly_buf->seg_count = 0; + + data_conc->data = assembly_buf->data.data; + data_conc->len = assembly_buf->data.len; + + return TRUE; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_getSegBuffer | ++--------------------------------------------------------------------+ + + PURPOSE : This functions searchs the segment buffer for ref_num + and address. +*/ +LOCAL T_SEG_BUF* concSMS_getSegBuffer( USHORT ref_num, CHAR *address ) +{ + UBYTE i; + + TRACE_FUNCTION ("concSMS_getSegBuffer()"); + + + /* search for the element */ + for (i=0; i<MAX_BUF_ELEMS; i++) + { + if ((segBuf_list[i].ref_num EQ ref_num) AND + (segBuf_list[i].in_use)) + { + + if ((address NEQ NULL) /* AND (address[0] NEQ '\0') */) + { + if (!strcmp(segBuf_list[i].address, address)) + return &segBuf_list[i]; + } + else + { + return &segBuf_list[i]; + } + } + } + + return NULL; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_addToSegBuffer | ++--------------------------------------------------------------------+ + + PURPOSE : This functions adds one segment to the buffer and returns + FALSE if no segment buffer is available or the current + seg buffer is full. + +*/ +LOCAL UBYTE concSMS_addToSegBuffer ( USHORT ref_num, + CHAR *address, + UBYTE seq_num, + UBYTE rec_num, + T_ACI_SMS_STAT status, + T_SM_DATA_EXT *data ) +{ + T_SEG_BUF *segBuf = NULL; + T_SEG_BUF_ELEM *segBufElem; + USHORT count; + UBYTE i; + + TRACE_FUNCTION ("concSMS_addToSegBuffer()"); + + + /* search for the segment buffer */ + segBuf = concSMS_getSegBuffer( ref_num, address ); + + /* element not found */ + if (segBuf EQ NULL) + { + /* search for an unused list entry */ + for (i=0; i<MAX_BUF_ELEMS; i++) + { + if (segBuf_list[i].in_use EQ FALSE) + { + segBuf = &segBuf_list[i]; + break; + } + } + + /* no segment buffer available */ + if ( segBuf EQ NULL) + return FALSE; + + /* initialise new buffer */ + segBuf->in_use = TRUE; + segBuf->ref_num = ref_num; + if ( (address) AND (address[0] NEQ '\0') ) + strcpy(segBuf->address, address); + else + segBuf->address[0] = '\0'; + segBuf->list = new_list(); + } + + count = get_list_count(segBuf->list); + if ( count >= CONC_MAX_SEGS ) + { + /* clean segment buffer before it overflows */ + while (1) + { + segBufElem = remove_first_element(segBuf->list); + if (segBufElem EQ NULL) + break; + ACI_MFREE(segBufElem->data.data); + ACI_MFREE(segBufElem); + } + segBuf->in_use = FALSE; + return FALSE; + } + + /* create new segment buffer element */ + ACI_MALLOC(segBufElem, sizeof(T_SEG_BUF_ELEM)); + memset(segBufElem, 0, sizeof(T_SEG_BUF_ELEM)); + + /* fill new buffer element */ + segBufElem->seq_num = seq_num; + segBufElem->rec_num = rec_num; + segBufElem->status = status; + + /* alloc memory and copy user data to segment buffer */ + ACI_MALLOC(segBufElem->data.data, data->len); + segBufElem->data.len = data->len; + memcpy(segBufElem->data.data, data->data, data->len); + + /* insert element (segment) into the segment buffer */ + insert_list(segBuf->list, segBufElem); + + return TRUE; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_removeFromSegBuffer| ++--------------------------------------------------------------------+ + + PURPOSE : This function finds and removes the segment with + 'seq_num' from the segment buffer. + +*/ +LOCAL T_SEG_BUF_ELEM* concSMS_removeFromSegBuffer ( USHORT ref_num, + CHAR* address, + UBYTE seq_num ) +{ + T_SEG_BUF *segBuf = NULL; + T_SEG_BUF_ELEM *segBufElem; + + USHORT count; + + TRACE_FUNCTION ("concSMS_removeFromSegBuffer()"); + + + /* search for the segment buffer */ + segBuf = concSMS_getSegBuffer( ref_num, address ); + + + /* segment buffer not found */ + if (segBuf EQ NULL) + return NULL; + + segBufElem = remove_element(segBuf->list, seq_num, concSMS_findSeqNumSB); + + if (segBufElem EQ NULL) + { + return NULL; /* didn't find the segment buffer element for this seq_num */ + } + + count = get_list_count(segBuf->list); + + if (count EQ 0) + { + ACI_MFREE (segBuf->list); + segBuf->list = NULL; + segBuf->in_use = FALSE; + } + + return segBufElem; + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_getConcBuffer | ++--------------------------------------------------------------------+ + + PURPOSE : This functions searchs the concatenations buffer for + ref_num and address. +*/ +LOCAL T_CONC_BUF* concSMS_getConcBuffer( USHORT ref_num, CHAR *address ) +{ + UBYTE i; + + TRACE_FUNCTION ("concSMS_getConcBuffer()"); + + /* search for the element */ + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + if ((concBuf_list[i].ref_num EQ ref_num) AND + (concBuf_list[i].in_use)) + { + if ((address NEQ NULL) /* AND (address[0] NEQ '\0') */) + { + if (!strcmp(concBuf_list[i].address, address)) + { + return &concBuf_list[i]; + } + } + else + { + return &concBuf_list[i]; + } + } + } + + return NULL; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_addToConcatList | ++--------------------------------------------------------------------+ + + PURPOSE : +*/ +LOCAL BOOL concSMS_addToConcatList ( USHORT ref_num, + CHAR *address, + UBYTE max_num, + UBYTE seq_num, + UBYTE rec_num, + T_ACI_SMS_STAT status, + UBYTE mem) +{ + T_CONC_BUF *concBuf; + T_CONC_BUF_ELEM *concBufElem; + UBYTE i; + + TRACE_FUNCTION ("concSMS_addToConcatList()"); + + + /* search for concatenation buffer */ + concBuf = concSMS_getConcBuffer( ref_num, address ); + + + /* element not found */ + if (concBuf EQ NULL) + { + + /* search for an unused list entry */ + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + if (concBuf_list[i].in_use EQ FALSE) + { + concBuf = &concBuf_list[i]; + break; + } + } + + /* buffer is full */ + if ( concBuf EQ NULL) + return FALSE; + + + concBuf->in_use = TRUE; + concBuf->ref_num = ref_num; + + if ( (address) AND (address[0] NEQ '\0') ) + strcpy(concBuf->address, address); + else + concBuf->address[0] = '\0'; + + concBuf->max_num = max_num; + concBuf->list = new_list(); + } + + + /* don't add elements with same seq_num to the Concatenation Buffer */ + concBufElem = find_element(concBuf->list,seq_num,concSMS_findSeqNumElemCB); + if (concBufElem) + return FALSE; + + + + /* create new conc. buffer element */ + ACI_MALLOC(concBufElem, sizeof(T_CONC_BUF_ELEM)); + + /* increase total count of stored CSMS segments by 1*/ + concShrdPrm.elem_count++; + + concBufElem->seq_num = seq_num; + concBufElem->rec_num = rec_num; + concBufElem->status = status; + concBufElem->mem = mem; + + /* insert element into the conc. buffer */ + insert_list(concBuf->list, concBufElem); + + concSMS_printConcatList(); + + return TRUE; +} + + + +/* ++---------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_removeFromConcatList| ++---------------------------------------------------------------------+ + + PURPOSE : This function removes and FREES the memory for the element. +*/ +LOCAL T_ACI_LIST *concSMS_removeFromConcatList ( USHORT ref_num, + CHAR *address, + UBYTE rec_num ) +{ + T_CONC_BUF *concBuf = NULL; + T_CONC_BUF_ELEM *concBufElem; + USHORT count; + + TRACE_FUNCTION ("concSMS_removeFromConcatList()"); + + + /* search for concatenation buffer */ + concBuf = concSMS_getConcBuffer( ref_num, address ); + + /* concatenation buffer not found */ + if (concBuf EQ NULL) + { + TRACE_EVENT_P1("conc_buf NULL: rec: %d", rec_num); + return NULL; + } + + concBufElem = remove_element(concBuf->list, rec_num, concSMS_findRecNumElemCB); + + if (concBufElem EQ NULL) + { + TRACE_EVENT_P1("concBufElem NULL: rec: %d", rec_num); + return NULL; + } + + /* free memory for this element */ + ACI_MFREE(concBufElem); + + /* decrease total count of stored CSMS segments by 1*/ + concShrdPrm.elem_count--; + + count = get_list_count(concBuf->list); + + if (count EQ 0) + { + ACI_MFREE (concBuf->list); + concBuf->list = NULL; + concBuf->in_use = FALSE; + return NULL; + } + return concBuf->list; +} + + +/* ++---------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_sortConcatList | ++---------------------------------------------------------------------+ + + PURPOSE : This function sorts the concat. buffer acc. to its seq_num. +*/ +LOCAL void concSMS_sortConcatList ( USHORT ref_num, + CHAR *address ) +{ + T_CONC_BUF *concBuf = NULL; + T_CONC_BUF_ELEM *concBufElem; + UBYTE seq_num; + UBYTE rec_num = 0; + T_ACI_LIST *oldlist, *newlist, *current; + USHORT count; + + TRACE_FUNCTION ("concSMS_sortConcatList()"); + + + /* search for concatenation buffer */ + concBuf = concSMS_getConcBuffer( ref_num, address ); + + /* concatenation buffer not found */ + if (concBuf EQ NULL) + return; + + newlist = new_list(); + oldlist = concBuf->list; + + count = get_list_count(oldlist); + + while (count) + { + seq_num = 255; + current = oldlist; + while (current) + { + concBufElem = (T_CONC_BUF_ELEM*)current->msg; + if ( concBufElem->seq_num < seq_num ) + { + seq_num = concBufElem->seq_num; + rec_num = concBufElem->rec_num; + } + current = current->next; + } + + concBufElem = remove_element(oldlist, rec_num, concSMS_findRecNumElemCB); + + insert_list(newlist, concBufElem); + + count = get_list_count(oldlist); + } + if (concBuf->list) + { + ACI_MFREE (concBuf->list); + concBuf->list = NULL; + } + concBuf->list = newlist; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_split | ++--------------------------------------------------------------------+ + + PURPOSE : return TRUE if splitting was done, otherwise FALSE +*/ +LOCAL UBYTE concSMS_split ( T_ACI_SM_DATA* tar_data, + T_SM_DATA_EXT* src_data, + UBYTE alphabet, + T_EXT_CMS_CMD_ID id) +{ +#ifndef _SIMULATION_ + T_TIME time_val; /* Used for input to random generator */ +#endif + + TRACE_FUNCTION ("concSMS_split ()"); + + if (alphabet EQ 0x00) + { + /* 7-bit data coding scheme */ + if (src_data->len <= concShrdPrm.l_uncomp7bit_data) + { + tar_data->len = (UBYTE)src_data->len; + memcpy ( tar_data->data, src_data->data, tar_data->len ); + return FALSE; + } + else + { + tar_data->len = concShrdPrm.l_uncomp7bit_data_conc; + concShrdPrm.max_sms_len = concShrdPrm.l_uncomp7bit_data_conc; + } + } + else + { + /* 8-bit data coding scheme */ + if (src_data->len <= concShrdPrm.l_uncomp8bit_data) + { + tar_data->len = (UBYTE)src_data->len; + memcpy ( tar_data->data, src_data->data, tar_data->len ); + return FALSE; + } + else + { + tar_data->len = concShrdPrm.l_uncomp8bit_data_conc; + concShrdPrm.max_sms_len = concShrdPrm.l_uncomp8bit_data_conc; + } + } + + /* copy first segment to 'tar_data' */ + memcpy ( tar_data->data, src_data->data, tar_data->len ); + + concShrdPrm.udh.ref_num = (UBYTE)concSMS_findMaxRefNum(); /* Marcus: Issue 872: 03/10/2002 */ + concShrdPrm.udh.ref_num++; + + concShrdPrm.udh.max_num = (src_data->len+(concShrdPrm.max_sms_len-1)) / concShrdPrm.max_sms_len; + concShrdPrm.udh.seq_num = 1; + + if (id EQ CMGS_CONC) + { +#ifndef _SIMULATION_ + vsi_t_time (VSI_CALLER &time_val); + srand((USHORT) time_val); /* initialize random generator */ + + /* For every conc sms going out, generate a random reference number and + * send it. Also when power cycled it will generate a new random number. + */ + concShrdPrm.udh.ref_num = (UBYTE)rand(); +#endif + concShrdPrm.specPrm.concCMGS.data.len = src_data->len; + concShrdPrm.specPrm.concCMGS.data.data = src_data->data; + concShrdPrm.specPrm.concCMGS.offset = tar_data->len; + return TRUE; + } + + if (id EQ CMGW_CONC) + { + concShrdPrm.specPrm.concCMGW.data.len = src_data->len; + concShrdPrm.specPrm.concCMGW.data.data = src_data->data; + concShrdPrm.specPrm.concCMGW.offset = tar_data->len; + return TRUE; + } + + return FALSE; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_fillUDH | ++--------------------------------------------------------------------+ + + PURPOSE : +*/ +LOCAL void concSMS_fillUDH ( T_ACI_UDH_DATA* udh, + UBYTE ref_num, + UBYTE max_num, + UBYTE seq_num ) +{ + /* fill user data header structure for 8-bit ref number */ + + udh->len = 0x05; + + /* Information Element Identifier */ + udh->data[0] = SMS_IEI_CONC_8BIT; + + /* Information Element Identifier Length */ + udh->data[1] = 0x03; + + /* Information Element Data */ + udh->data[2] = (UBYTE)(ref_num & 0x00FF); /* since we use only 8-Bit ref number */ + udh->data[3] = max_num; + udh->data[4] = seq_num; +} + + + +#ifdef TI_PS_FF_CONC_SMS +/********************** Init Functions *********************************/ + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_retrieveConcBuf | ++--------------------------------------------------------------------+ + + PURPOSE : This function searches for the concatenation buffer + which has 'index' in its first element. Returns + 'CONC_ERROR' if index is not the first element or list is + incomplete. + +*/ +LOCAL T_CONC_INIT_RETURN concSMS_retrieveConcBuf ( T_CONC_BUF **concBuf, + UBYTE index, + UBYTE mem) +{ + UBYTE i; + T_CONC_BUF_ELEM *concBufElem; + + TRACE_FUNCTION ("concSMS_retrieveConcBuf ()"); + + *concBuf = NULL; + + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + concSMS_printConcatList(); + /* find conc. buffer element for this rec number */ + concBufElem = find_element(concBuf_list[i].list, + index, + concSMS_findRecNumElemCB); + + /* element was found and check if memory type of the first segment + * equals to the set memory type (mem1 or mem2) + */ + if ((concBufElem NEQ NULL) AND (concBufElem->mem EQ mem)) + + { + break; + } + } + + if (concBufElem EQ NULL) + { + /* no concatenation handler needed */ + return CONC_NOT_NEEDED; + } + + *concBuf = &concBuf_list[i]; + + + /* check if rec number is the first segment (with seq_num == 1) */ + if ( ( concBufElem->seq_num EQ 1 ) AND + ( smsShrdPrm.status EQ CMGD_DEL_INDEX ) ) + { + *concBuf = &concBuf_list[i]; + return CONC_NEEDED; + + } + else if( smsShrdPrm.status > CMGD_DEL_INDEX ) + { + /* The below check needs to be changed for deleting all + the concatmessages in case of DELET FLAG > 0. */ + + *concBuf = &concBuf_list[i]; + return CONC_NEEDED; + } + /* rec number is not the first element in conc. buffer + * allow reading of incomplete segments and tread them like "normal" SMS + */ + return CONC_NOT_NEEDED; +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_initSendFromMem | ++--------------------------------------------------------------------+ + + PURPOSE : This function initialises shared parameter for CMSS. + +*/ +GLOBAL T_CONC_INIT_RETURN concSMS_initSendFromMem ( T_ACI_CMD_SRC srcId, + UBYTE *index, + CHAR *da, + T_ACI_TOA *toda ) +{ + T_CONC_BUF *concBuf = NULL; + T_CONC_BUF_ELEM* elem = NULL; + T_CONC_INIT_RETURN ret = CONC_ERROR; + T_CONC_CMSS *prm = &concShrdPrm.specPrm.concCMSS; + + + TRACE_FUNCTION ("concSMS_initSendFromMem ()"); + + ret = concSMS_retrieveConcBuf ( &concBuf, *index, smsShrdPrm.mem2); + + if (ret EQ CONC_ERROR) + { + /* Error: segment is not the first segment of the SM */ + return CONC_ERROR; + } + + if (ret EQ CONC_NOT_NEEDED) + { + /* no conatenation handler needed */ + return CONC_NOT_NEEDED; + } + + concShrdPrm.sentSegs = 0; + concShrdPrm.srcId = srcId; + + if (da) + { + memcpy(prm->da, da, strlen(da)); + prm->da[strlen(da)] = '\0'; + prm->p_da = prm->da; + } + else + { + prm->p_da = NULL; + } + + if (toda) + { + memcpy(&prm->toda, toda, sizeof(T_ACI_TOA)); + prm->p_toda = &prm->toda; + } + else + { + prm->p_toda = NULL; + } + + /* save the first concatenated buffer element */ + prm->currConcBufListElem = concBuf->list; + + prm->skipStoSent = TRUE; + + /* skip segments with status SMS_STAT_StoSent */ + while (prm->currConcBufListElem) + { + elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg; + + if (elem->status EQ SMS_STAT_StoSent) + { + prm->currConcBufListElem = prm->currConcBufListElem->next; + } + else + { + break; + } + } + + /* + * All elements were set to SMS_STAT_StoSent. Assume that this message was + * sent completly and should be sent for the second time. + */ + if (prm->currConcBufListElem EQ NULL) + { + prm->skipStoSent = FALSE; + + /* save the first concatenated buffer element */ + prm->currConcBufListElem = concBuf->list; + + elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg; + } + + *index = elem ? elem->rec_num : NULL; + + if (elem NEQ NULL) + { + elem->status = SMS_STAT_StoSent; + } + + return CONC_NEEDED; + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_initReadFromMem | ++--------------------------------------------------------------------+ + + PURPOSE : This function initialises shared parameter for CMGR. + +*/ +GLOBAL T_CONC_INIT_RETURN concSMS_initReadFromMem ( T_ACI_CMD_SRC srcId, + UBYTE index, + T_ACI_SMS_READ rdMode ) +{ + T_CONC_BUF *concBuf; + T_CONC_INIT_RETURN ret; + + TRACE_FUNCTION ("concSMS_initReadFromMem ()"); + + ret = concSMS_retrieveConcBuf ( &concBuf, index, smsShrdPrm.mem2); + + if (ret EQ CONC_ERROR) + { + /* Error: segment is not the first segment of the SM */ + return CONC_ERROR; + } + + if (ret EQ CONC_NOT_NEEDED) + { + /* no conatenation handler needed */ + return CONC_NOT_NEEDED; + } + + concShrdPrm.srcId = srcId; + concShrdPrm.specPrm.concCMGR.rdMode = rdMode; + + /* save the second concatenated buffer element */ + concShrdPrm.specPrm.concCMGR.currConcBufListElem = concBuf->list->next; + + return CONC_NEEDED; + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_initDeleteFromMem | ++--------------------------------------------------------------------+ + + PURPOSE : This function initialises shared parameter for CMGD. + +*/ +GLOBAL T_CONC_INIT_RETURN concSMS_initDeleteFromMem ( T_ACI_CMD_SRC srcId, + UBYTE index ) +{ + T_CONC_BUF *concBuf; + T_CONC_INIT_RETURN ret; + + + TRACE_FUNCTION ("concSMS_initDeleteFromMem ()"); + + + ret = concSMS_retrieveConcBuf ( &concBuf, index, smsShrdPrm.mem1); + + if (ret EQ CONC_ERROR) + { + /* Error: segment is not the first segment of the SM */ + return CONC_ERROR; + } + + if (ret EQ CONC_NOT_NEEDED) + { + if (concBuf NEQ NULL) + { + RefNum_Del = concBuf->ref_num; + } + /*else if (*/ + else if (dFLAG EQ TRUE) + { + TRACE_EVENT("BUFFER FULL"); + } + else + { + RefNum_Del = 0xFF; + } + /* no conatenation handler needed */ + return CONC_NOT_NEEDED; + } + + + /* save the concatenation list */ + concShrdPrm.specPrm.concCMGD.currConcBufListElem = concBuf->list; + + concShrdPrm.specPrm.concCMGD.ref_num = concBuf->ref_num; + + concShrdPrm.specPrm.concCMGD.address = concBuf->address; + + concShrdPrm.srcId = srcId; + + concShrdPrm.specPrm.concCMGD.error_count = 0; + + return CONC_NEEDED; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_initSend | ++--------------------------------------------------------------------+ + + PURPOSE : This function initialises shared parameter for CMGS. + +*/ +GLOBAL T_CONC_INIT_RETURN concSMS_initSend ( + T_ACI_SM_DATA* tar_data, + T_ACI_UDH_DATA* udh, + T_ACI_CMD_SRC srcId, + CHAR* da, + T_ACI_TOA* toda, + T_SM_DATA_EXT* src_data, + CHAR* sca, + T_ACI_TOA* tosca, + SHORT isReply, + UBYTE alphabet ) +{ + UBYTE ret; + T_CONC_CMGS *prm = &concShrdPrm.specPrm.concCMGS; + + TRACE_FUNCTION ("concSMS_initSend ()"); + + + ret = concSMS_split ( tar_data, src_data, alphabet, CMGS_CONC ); + + if ( ret EQ FALSE ) + return CONC_NOT_NEEDED; + + concShrdPrm.srcId = srcId; + + if (da) + { + memcpy(prm->da, da, strlen(da)); + prm->da[strlen(da)] = '\0'; + prm->p_da = prm->da; + } + else + { + prm->p_da = NULL; + } + if (toda) + { + memcpy(&prm->toda, toda, sizeof(T_ACI_TOA)); + prm->p_toda = &prm->toda; + } + else + { + prm->p_toda = NULL; + } + + prm->data.len = src_data->len; + prm->data.data = src_data->data; + + if (sca) + { + memcpy(prm->sca, sca, strlen(sca)); + prm->sca[strlen(sca)] = '\0'; + prm->p_sca = prm->sca; + } + else + { + prm->p_sca = NULL; + } + if (tosca) + { + memcpy(&prm->tosca, tosca, sizeof(T_ACI_TOA)); + prm->p_tosca = &prm->tosca; + } + else + { + prm->p_tosca = NULL; + } + + prm->isReply = isReply; + prm->sent_bytes = 0; + + concShrdPrm.sentSegs = 0; + + /* fill user data header structure */ + concSMS_fillUDH ( udh, + concShrdPrm.udh.ref_num, + concShrdPrm.udh.max_num, + concShrdPrm.udh.seq_num ); + + return CONC_NEEDED; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_initStoreInMem | ++--------------------------------------------------------------------+ + + PURPOSE : This function initialises shared parameter for CMGW. + +*/ +GLOBAL T_CONC_INIT_RETURN concSMS_initStoreInMem ( T_ACI_SM_DATA* tar_data, + T_ACI_UDH_DATA* udh, + T_ACI_CMD_SRC srcId, + SHORT index, + CHAR* address, + T_ACI_TOA* toa, + T_ACI_SMS_STAT stat, + UBYTE msg_ref, + T_SM_DATA_EXT* src_data, + CHAR* sca, + T_ACI_TOA* tosca, + SHORT isReply, + UBYTE alphabet ) +{ + T_CONC_INIT_RETURN ret; + T_CONC_CMGW *prm = &concShrdPrm.specPrm.concCMGW; + + TRACE_FUNCTION ("concSMS_initStoreInMem ()"); + + + ret = (T_CONC_INIT_RETURN)concSMS_split ( tar_data, src_data, alphabet, CMGW_CONC ); + + if ( ret EQ FALSE ) + { + return CONC_NOT_NEEDED; + } + + concShrdPrm.srcId = srcId; + + if (address) + { + memcpy(prm->da, address, strlen(address)); + prm->da[strlen(address)] = '\0'; + prm->p_da = prm->da; + } + else + { + prm->p_da = NULL; + } + if (toa) + { + memcpy(&prm->toda, toa, sizeof(T_ACI_TOA)); + prm->p_toda = &prm->toda; + } + else + { + prm->p_toda = NULL; + } + + if ( stat NEQ SMS_STAT_NotPresent) + { + prm->stat = stat; + } + else + { + prm->stat = SMS_STAT_StoUnsent; + } + + prm->msg_ref = msg_ref; + prm->data.len = src_data->len; + prm->data.data = src_data->data; + + if (sca) + { + memcpy(prm->sca, sca, strlen(sca)); + prm->sca[strlen(sca)] = '\0'; + prm->p_sca = prm->sca; + } + else + { + prm->p_sca = NULL; + } + if (tosca) + { + memcpy(&prm->tosca, tosca, sizeof(T_ACI_TOA)); + prm->p_tosca = &prm->tosca; + } + else + { + prm->p_tosca = NULL; + } + + prm->isReply = isReply; + + /* fill user data header structure */ + concSMS_fillUDH ( udh, + concShrdPrm.udh.ref_num, + concShrdPrm.udh.max_num, + concShrdPrm.udh.seq_num ); + + return CONC_NEEDED; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_initCommand | ++--------------------------------------------------------------------+ + + PURPOSE : This function initialises shared parameter for CMGC. + +*/ +GLOBAL T_CONC_INIT_RETURN concSMS_initCommand ( T_ACI_CMD_SRC srcId, + SHORT fo, + SHORT ct, + SHORT pid, + SHORT mn, + CHAR* da, + T_ACI_TOA* toda, + T_ACI_CMD_DATA* data ) +{ + T_CONC_CMGC *prm = &concShrdPrm.specPrm.concCMGC; + + TRACE_FUNCTION ("concSMS_initCommand ()"); + + + if ( ct NEQ COMMAND_TYPE_DELETE) + return CONC_NOT_NEEDED; + + if ((mn < concShrdPrm.first_mr) OR + (mn > concShrdPrm.first_mr + concShrdPrm.sentSegs-1)) + return CONC_NOT_NEEDED; + + + if ( mn NEQ concShrdPrm.first_mr) + { + /* Error: segment is not the first segment of the SM */ + return CONC_ERROR; + } + else + { + concShrdPrm.srcId = srcId; + + prm->command_count = 0; + prm->fo = (UBYTE)fo; + prm->ct = (UBYTE)ct; + prm->pid = (UBYTE)pid; + + if (da) + { + memcpy(prm->da, da, strlen(da)); + prm->da[strlen(da)] = '\0'; + prm->p_da = prm->da; + } + else + { + prm->p_da = NULL; + } + + if (toda) + { + memcpy(&prm->toda, toda, sizeof(T_ACI_TOA)); + prm->p_toda = &prm->toda; + } + else + { + prm->p_toda = NULL; + } + + ACI_MALLOC(prm->data.data, MAX_SM_CMD_LEN); + memcpy ( prm->data.data, data->data, data->len ); + prm->data.len = data->len; + + } + return CONC_NEEDED; +} + + + + +/********************** RAT Callback Fucntions ****************************/ + + +GLOBAL void rConcSMS_PlusCMSS (UBYTE mr, UBYTE numSeg) +{ + UBYTE index; + T_CONC_BUF_ELEM* elem; + T_CONC_CMSS *prm = &concShrdPrm.specPrm.concCMSS; + + TRACE_FUNCTION ("rConcSMS_PlusCMSS()"); + + + /* save the first message reference */ + if (concShrdPrm.sentSegs EQ 0) + { + concShrdPrm.first_mr = mr; + } + + /* increment number of successfully sent elements */ + concShrdPrm.sentSegs++; + + /* get next concat. list element */ + prm->currConcBufListElem = prm->currConcBufListElem->next; + + if (prm->skipStoSent) + { + /* skip segments with status SMS_STAT_StoSent */ + while (prm->currConcBufListElem) + { + elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg; + + if (elem->status EQ SMS_STAT_StoSent) + { + prm->currConcBufListElem = prm->currConcBufListElem->next; + } + else + { + break; + } + } /* while */ + } + + if (prm->currConcBufListElem NEQ NULL) + { + elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg; + index = elem->rec_num; + + /* set mem2 (memory to which writing and sending operations are made) + temporary to the value stored in conc buffer */ + smsShrdPrm.mem2 = elem->mem; + + sAT_PlusCMSS_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, index, prm->p_da, prm->p_toda, + rConcSMS_PlusCMSS, rConcSMS_PlusCMS_CMSS); + + + elem->status = SMS_STAT_StoSent; + + + } + else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */ + { + +#ifdef _CONC_TESTING_ + char *sa; + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMSS: %d,%d",concShrdPrm.first_mr, concShrdPrm.sentSegs); + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); +#endif + + rAT_PlusCMSS(concShrdPrm.first_mr, (UBYTE)(concShrdPrm.sentSegs)); + + /* restore value for mem2 */ + smsShrdPrm.mem2 = concShrdPrm.mem_store; + + R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMSS ); + UNSET_CONC; + } +} + +GLOBAL void rConcSMS_PlusCMGS (UBYTE mr, UBYTE numSeg) +{ + T_ACI_SM_DATA data; + T_ACI_UDH_DATA udh; + USHORT len_left; + T_CONC_CMGS *prm = &concShrdPrm.specPrm.concCMGS; + + TRACE_FUNCTION ("rConcSMS_PlusCMGS()"); + + + /* save the first message reference */ + if (concShrdPrm.udh.seq_num EQ 1) + { + concShrdPrm.first_mr = mr; + } + + /* increment number of successfully sent elements */ + len_left = prm->data.len - prm->offset; + + concShrdPrm.sentSegs++; + + if (len_left NEQ 0) + { + prm->sent_bytes += concShrdPrm.max_sms_len; + + if ( len_left > concShrdPrm.max_sms_len ) + { + data.len = concShrdPrm.max_sms_len; + } + else + { + data.len = (UBYTE)len_left; + } + + memcpy (data.data, prm->data.data+prm->offset, data.len); + prm->offset += data.len; + + concShrdPrm.udh.seq_num++; + + + /* fill user data header structure */ + concSMS_fillUDH ( &udh, + concShrdPrm.udh.ref_num, + concShrdPrm.udh.max_num, + concShrdPrm.udh.seq_num ); + + sAT_PlusCMGS_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, prm->p_da, prm->p_toda, + &data, &udh, prm->p_sca, prm->p_tosca, + prm->isReply, rConcSMS_PlusCMGS, rConcSMS_PlusCMS_CMGS); + + + } + else + { + +#ifdef _CONC_TESTING_ + char *sa; + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMGS: %d,%d",concShrdPrm.first_mr, concShrdPrm.udh.seq_num); + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); + + ACI_MFREE(prm->data.data); + +#endif + + rAT_PlusCMGS (concShrdPrm.first_mr, (UBYTE)(concShrdPrm.udh.seq_num)); + R_AT ( RAT_OK, (T_ACI_CMD_SRC)concShrdPrm.srcId ) ( AT_CMD_CMGS ); + UNSET_CONC; + } +} + + + +GLOBAL void rConcSMS_PlusCMGR ( T_ACI_CMGL_SM* sm, + T_ACI_CMGR_CBM* cbm ) +{ + T_CONC_CMGR *prm = &concShrdPrm.specPrm.concCMGR; + + TRACE_FUNCTION ("rConcSMS_PlusCMGR ()"); + + if (prm->currConcBufListElem NEQ NULL) + { + T_CONC_BUF_ELEM *elem; + elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg; + + /* set mem1 (memory from which messages are read and deleted) + * temporary to the value stored in conc buffer */ + smsShrdPrm.mem1 = elem->mem; + + sAT_PlusCMGR_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num, + (T_ACI_SMS_READ)concShrdPrm.specPrm.concCMGR.rdMode, + rConcSMS_PlusCMGR); + + prm->currConcBufListElem = prm->currConcBufListElem->next; + +#ifdef _CONC_TESTING_ + rAT_PlusCMGR_Ext (sm, cbm); +#else + rAT_PlusCMGR (sm, cbm); +#endif + + } + else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */ + { +#ifdef _CONC_TESTING_ + rAT_PlusCMGR_Ext (sm, cbm); +#else + rAT_PlusCMGR (sm, cbm); +#endif + + /* restore value for mem1 */ + smsShrdPrm.mem1 = concShrdPrm.mem_store; + + + R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGR ); + UNSET_CONC; + } +} + +GLOBAL void rConcSMS_PercentCMGMDU (void) +{ + T_CONC_CMGR *prm = &concShrdPrm.specPrm.concCMGR; + + TRACE_FUNCTION ("rConcSMS_PercentCMGMDU ()"); + + if (prm->currConcBufListElem NEQ NULL) + { + T_CONC_BUF_ELEM *elem; + elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg; + + sAT_PercentCMGMDU_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num, + rConcSMS_PercentCMGMDU); + + prm->currConcBufListElem = prm->currConcBufListElem->next; + + } + else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */ + { + if( concShrdPrm.srcId NEQ CMD_SRC_LCL ) + R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_P_CMGMDU ); + UNSET_CONC; + } +} + +GLOBAL void rConcSMS_PlusCMGW ( UBYTE index, UBYTE numSeg, UBYTE mem) +{ + T_ACI_SM_DATA data; + T_ACI_UDH_DATA udh; + USHORT len_left; + T_CONC_CMGW *prm = &concShrdPrm.specPrm.concCMGW; + + static UBYTE first_rec; + + TRACE_FUNCTION ("rConcSMS_PlusCMGW ()"); + + + /* save the first index */ + if (concShrdPrm.udh.seq_num EQ 1) + { + first_rec = index; + } + + concSMS_addToConcatList((USHORT)concShrdPrm.udh.ref_num, + prm->p_da, + concShrdPrm.udh.max_num, + concShrdPrm.udh.seq_num, + index, + (T_ACI_SMS_STAT)prm->stat, + mem); + + concSMS_printConcatList(); + + len_left = prm->data.len - prm->offset; + + if (len_left NEQ 0) + { + prm->sent_bytes += concShrdPrm.max_sms_len; + + if ( len_left > concShrdPrm.max_sms_len ) + { + data.len = concShrdPrm.max_sms_len; + } + else + { + data.len = (UBYTE)len_left; + } + + memcpy (data.data, prm->data.data+prm->offset, data.len); + prm->offset += data.len; + + concShrdPrm.udh.seq_num++; + + /* fill user data header structure */ + concSMS_fillUDH ( &udh, + concShrdPrm.udh.ref_num, + concShrdPrm.udh.max_num, + concShrdPrm.udh.seq_num ); + + sAT_PlusCMGW_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, CMGW_IDX_FREE_ENTRY, + prm->p_da, prm->p_toda, (T_ACI_SMS_STAT)prm->stat, prm->msg_ref, + &data, &udh, prm->p_sca, prm->p_tosca, + prm->isReply, rConcSMS_PlusCMGW, rConcSMS_PlusCMS_CMGW); + + } + else + { + +#ifdef _CONC_TESTING_ + char *sa; + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMGW: %d,%d",first_rec, concShrdPrm.udh.seq_num); + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); +#endif + + rAT_PlusCMGW (first_rec, concShrdPrm.udh.seq_num, mem); + R_AT ( RAT_OK, (T_ACI_CMD_SRC)concShrdPrm.srcId ) ( AT_CMD_CMGW ); + UNSET_CONC; + } +} + + + + + + +GLOBAL void rConcSMS_PlusCMGD ( ) +{ + T_CONC_CMGD *prm = &concShrdPrm.specPrm.concCMGD; + T_CONC_BUF_ELEM *elem; + T_ACI_LIST *conc_list; + + TRACE_FUNCTION ("rConcSMS_PlusCMGD ()"); + + + elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg; + + /* remove the old element from concatenation list and free its memory */ + conc_list = concSMS_removeFromConcatList(prm->ref_num, prm->address, elem->rec_num); + + concSMS_printConcatList(); + + if (conc_list NEQ NULL) + { + TRACE_EVENT("conc_list not null"); + elem = (T_CONC_BUF_ELEM *)conc_list->msg; + + /* save the concatenation list */ + prm->currConcBufListElem= conc_list; + + /* set mem1 (memory from which messages are read and deleted) + temporary to the value stored in conc buffer */ + smsShrdPrm.mem1 = elem->mem; + + sAT_PlusCMGD_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num, smsShrdPrm.status, + rConcSMS_PlusCMGD, rConcSMS_PlusCMS_CMGD); + + } + else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */ + { + if (concShrdPrm.full.Conc_Full EQ TRUE) + { + concSMS_AddtoconcBuff(); + concShrdPrm.full.Conc_Full = FALSE; + } + + /* restore value for mem1 */ + smsShrdPrm.mem1 = concShrdPrm.mem_store; + + TRACE_EVENT("RAT_OK in rConcSMS_PlusCMGD"); + R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGD ); + UNSET_CONC; + } +} + + +GLOBAL void rConcSMS_PlusCMGC ( UBYTE mr ) +{ + UBYTE mn; + T_CONC_CMGC *prm = &concShrdPrm.specPrm.concCMGC; + + TRACE_FUNCTION ("rConcSMS_PlusCMGC ()"); + + /* save the first message reference */ + if (concShrdPrm.udh.seq_num EQ 1) + { + concShrdPrm.first_mr = mr; + } + + prm->command_count++; + + if (prm->command_count < concShrdPrm.sentSegs) + { + mn = concShrdPrm.first_mr + prm->command_count; + + sAT_PlusCMGC_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, prm->fo, prm->ct, + prm->pid, mn, prm->p_da, prm->p_toda, + (T_ACI_CMD_DATA*)&prm->data, rConcSMS_PlusCMGC); + } + else + { + +#ifdef _CONC_TESTING_ + char *sa; + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMGC: %d",concShrdPrm.first_mr /*, prm->command_count*/); + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); +#endif + + ACI_MFREE( prm->data.data ); + rAT_PlusCMGC (concShrdPrm.first_mr/*, prm->command_count*/); + R_AT ( RAT_OK,(T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGC ); + UNSET_CONC; + } +} + + +GLOBAL void rConcSMS_PlusCMS_CMSS (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err, + T_EXT_CMS_ERROR *ce) +{ + T_EXT_CMS_ERROR conc_error; +#ifdef _CONC_TESTING_ + char *sa; +#endif + + TRACE_FUNCTION ("rConcSMS_PlusCMS_CMSS ()"); + + + conc_error.id = CMSS_CONC; + conc_error.specErr.errConcCMSS.segs = + concShrdPrm.udh.max_num - concShrdPrm.sentSegs; + +#ifdef _CONC_TESTING_ + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMS ERROR: %d,%d",err, conc_error.specErr.errConcCMSS.segs); + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); + rCI_PlusCMS ( cmdId, err, NULL ); +#endif + + /* restore value for mem2 */ + smsShrdPrm.mem2 = concShrdPrm.mem_store; + + rAT_PlusCMS (cmdId, err, &conc_error); + UNSET_CONC; +} + + +GLOBAL void rConcSMS_PlusCMS_CMGS (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err, + T_EXT_CMS_ERROR *ce) +{ + T_EXT_CMS_ERROR conc_error; +#ifdef _CONC_TESTING_ + char *sa; +#endif + + TRACE_FUNCTION ("rConcSMS_PlusCMS_CMGS ()"); + + + conc_error.id = CMGS_CONC; + conc_error.specErr.errConcCMGS.sent_chars = + concShrdPrm.specPrm.concCMGS.sent_bytes; + conc_error.specErr.errConcCMGS.ref_num = concShrdPrm.udh.ref_num; + conc_error.specErr.errConcCMGS.next_seg = concShrdPrm.udh.seq_num; + conc_error.specErr.errConcCMGS.max_num = concShrdPrm.udh.max_num; + +#ifdef _CONC_TESTING_ + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMS ERROR: %d,%d,%d,%d,%d",err, + conc_error.specErr.errConcCMGS.sent_chars, + conc_error.specErr.errConcCMGS.ref_num, + conc_error.specErr.errConcCMGS.next_seg, + conc_error.specErr.errConcCMGS.max_num); + + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); + rCI_PlusCMS ( cmdId, err, NULL ); +#endif + + rAT_PlusCMS (cmdId, err, &conc_error); + UNSET_CONC; +} + + +GLOBAL void rConcSMS_PlusCMS_CMGW (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err, + T_EXT_CMS_ERROR *ce) +{ + T_EXT_CMS_ERROR conc_error; +#ifdef _CONC_TESTING_ + char *sa; +#endif + + TRACE_FUNCTION ("rConcSMS_PlusCMS_CMGW ()"); + + + conc_error.id = CMGW_CONC; + conc_error.specErr.errConcCMGW.sent_chars = + concShrdPrm.specPrm.concCMGW.sent_bytes; + conc_error.specErr.errConcCMGW.ref_num = concShrdPrm.udh.ref_num; + conc_error.specErr.errConcCMGW.next_seg = concShrdPrm.udh.seq_num; + conc_error.specErr.errConcCMGW.max_num = concShrdPrm.udh.max_num; + +#ifdef _CONC_TESTING_ + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMS ERROR: %d,%d,%d,%d,%d",err, + conc_error.specErr.errConcCMGW.sent_chars, + conc_error.specErr.errConcCMGW.ref_num, + conc_error.specErr.errConcCMGW.next_seg, + conc_error.specErr.errConcCMGW.max_num); + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); + rCI_PlusCMS ( cmdId, err, NULL ); +#endif + + rAT_PlusCMS (cmdId, err, &conc_error); + UNSET_CONC; +} + +GLOBAL void rConcSMS_PlusCMS_CMGD (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err, + T_EXT_CMS_ERROR *ce) +{ + T_CONC_CMGD *prm = &concShrdPrm.specPrm.concCMGD; + T_CONC_BUF_ELEM *elem; + T_EXT_CMS_ERROR conc_error; + + TRACE_FUNCTION ("rConcSMS_PlusCMS_CMGD ()"); + + conc_error.id = EMPTY; + + prm->error_count++; + if (prm->error_count EQ concShrdPrm.udh.max_num) + { + +#ifdef _CONC_TESTING_ + char *sa; + ACI_MALLOC(sa,KEY + BYTE_LTH); + sprintf(sa,"+CMS ERROR: %d",err); + io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT); + ACI_MFREE(sa); + rCI_PlusCMS ( cmdId, err, NULL ); +#endif + + elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg; + /* remove the old element from concatenation list and free its memory */ + concSMS_removeFromConcatList(prm->ref_num, prm->address, elem->rec_num); + concSMS_printConcatList(); + + /* restore value for mem1 */ + smsShrdPrm.mem1 = concShrdPrm.mem_store; + + rAT_PlusCMS ( cmdId, err, &conc_error); + UNSET_CONC; + } + else + { + /* continue with the next segment */ + rConcSMS_PlusCMGD(); + } +} +#endif /* TI_PS_FF_CONC_SMS */ + + + + +/*************** Functions which must be called by MFW ***************/ + + + + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : SMS_getSMSType | ++--------------------------------------------------------------------+ + + PURPOSE : This function must be called by the MFW to detect the SMS + type from the information element identifier. + +*/ +GLOBAL T_SMS_TYPE SMS_getSMSType( T_ACI_UDH_DATA* udh, char *address, UBYTE detMode) +{ + USHORT ref_num = 0; + UBYTE seq_num = 0; + UBYTE max_num = 0; + USHORT count; + T_CONC_BUF* concBuf; + + TRACE_FUNCTION ("SMS_getSMSType()"); + TRACE_EVENT_P1("SMS_getSMSType, mode: %d", detMode); + + + if (udh->len EQ 0) + { + /* SMS does not contain UDH --> normal SMS */ + return NORMAL; + } + + /* check if IE is conc SMS */ + if ((udh->data[0] EQ SMS_IEI_CONC_8BIT) OR (udh->data[0] EQ SMS_IEI_CONC_16BIT)) + { + if (udh->data[0] EQ SMS_IEI_CONC_8BIT) + { + ref_num = udh->data[2]; + max_num = udh->data[3]; + seq_num = udh->data[4]; + } + + if (udh->data[0] EQ SMS_IEI_CONC_16BIT) + { + ref_num = (udh->data[2] & 0x00FF) << 8u; + ref_num += udh->data[3]; + max_num = udh->data[4]; + seq_num = udh->data[5]; + } + + switch (detMode) + { + + case MODE1: + /* This mode is for rAT_PlusCMT. No Concatenation buffer is needed at all */ + break; + + case MODE2: + /* This mode is for rAT_PlusCMTI. This mode requires the allocation of a new + * Concatenation buffer (later in concSMS_Collect). Make sure that in case + * the conc buffer is full no new CSMS is handled anymore + */ + concBuf = concSMS_getConcBuffer( ref_num, address ); + + /* if a new conc buffer is be needed, check if available */ + if (concBuf EQ NULL) + { + if (concSMS_concBufferAvail() EQ FALSE) + { + return NORMAL_IND_CSMS; + } + + /* Limit the maximum number of CSMS segments to MAX_SEG_TOTAL. Check + * only if a new Concatenation buffer is required. + */ + if (concShrdPrm.elem_count+max_num > MAX_SEG_TOTAL) + { + return NORMAL_IND_CSMS; + } + } + break; + + case MODE3: + /* This mode is for rAT_PlusCMGL, rAT_PlusCMGR, sms_store_new_msg_info and + * sms_store_new_msg_info. Only segments that have been previously stored + * in the Concatenation buffer can be handled as CSMS. + */ + concBuf = concSMS_getConcBuffer( ref_num, address ); + if (concBuf EQ NULL) + { + return NORMAL_IND_CSMS; + } + + /* check if conc buffer is incomplete */ + count = get_list_count(concBuf->list); + if ((count < concBuf->max_num) AND (count < CONC_MAX_SEGS)) + { + return NORMAL_IND_CSMS; + } + break; + + default: + TRACE_ERROR("Wrong detection mode in SMS_getSMSType"); + return UNKNOWN; + } + + /* check if sequence number is in range */ + if (seq_num <= CONC_MAX_SEGS) + { + return CONCATE; + } + else + { + return NORMAL_IND_CSMS; + } + } + else + { + /* unknown IE in UDH --> no CSMS */ + return UNKNOWN; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_GetFirstIndex | ++--------------------------------------------------------------------+ + + PURPOSE : This function provides MFW with the first index of a given + concatenated SMS (identified by its message reference). + + returns first index: (0 means no message found...) +*/ +#define FIRST_SEQ_NUM (1) + +GLOBAL T_CONC_BUF_ELEM *concSMS_GetFirstIndex_ext ( USHORT msg_ref, char *address ) +{ + + + T_CONC_BUF *concBuf; + T_CONC_BUF_ELEM *concBufElem; + + TRACE_FUNCTION ("concSMS_GetFirstIndex()"); + + /* search for concatenation buffer */ + concBuf = concSMS_getConcBuffer( msg_ref, address ); + + if( concBuf EQ NULL ) + { + TRACE_EVENT_P1("ERROR: unknown msg_ref: 0x%04x", msg_ref); + return( NULL ); + } + + /* search for the first sequence */ + concBufElem = find_element(concBuf->list, FIRST_SEQ_NUM, concSMS_findSeqNumElemCB); + + if( concBufElem EQ NULL ) + { + TRACE_EVENT("ERROR: first sequence not found"); + return( NULL ); + } + + TRACE_EVENT_P1("first rec_num: %d", concBufElem->rec_num); + TRACE_EVENT_P1 ("concSMS_GetFirstIndex_ext(), rec_num=%d", concBufElem->rec_num); + + /* return index of first segment */ + return(concBufElem); + +} + +GLOBAL UBYTE concSMS_GetFirstIndex ( USHORT msg_ref, char *address ) +{ + T_CONC_BUF_ELEM *concBufElem = concSMS_GetFirstIndex_ext(msg_ref, address); + + if( concBufElem EQ NULL ) + { + TRACE_EVENT("ERROR: first sequence not found"); + return(0); + } + else + return(concBufElem->rec_num); + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_GetMsgRef | ++--------------------------------------------------------------------+ + + PURPOSE : This function provides MFW with the message reference of a given + concatenated SMS (decoded from the header). + + returns msg ref. +*/ + +GLOBAL USHORT concSMS_GetMsgRef ( T_ACI_CMGL_SM *sm ) +{ + USHORT ref_num; + + TRACE_FUNCTION ("concSMS_GetMsgRef()"); + + if( sm EQ NULL ) + { + TRACE_ERROR("sm is NULL"); + return 0; + } + + /* 8-bit reference number */ + if (sm->udh.data[0] EQ SMS_IEI_CONC_8BIT) + { + ref_num = sm->udh.data[2]; + } + + /* 16-bit reference number */ + else if (sm->udh.data[0] EQ SMS_IEI_CONC_16BIT) + { + /* MSB */ + ref_num = (sm->udh.data[2] & 0x00FF) << 8u; /* 23.040 9.1.2.1 */ + + /* LSB */ + ref_num |= sm->udh.data[3]; + } + else + { + TRACE_ERROR("sm->udh.data unknown"); + return 0; + } + + TRACE_EVENT_P1("ref_num: 0x%04x", ref_num); + + return(ref_num); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_Collect | ++--------------------------------------------------------------------+ + + PURPOSE : This function must be called by the MFW. The function + reassembles the received SM segments. + + Set 'isStored' to: + TRUE, if rAT_PlusCMTI() was called + FALSE, if rAT_PlusCMT() was called + FALSE, if rAT_PlusCMGR() was called + +*/ +GLOBAL T_CONC_ASSEMBLY_RETURN concSMS_Collect ( T_SM_DATA_EXT *data_conc, + T_ACI_CMGL_SM *sm, + UBYTE isStored, + T_ACI_SMS_STOR mem_aci) +{ + USHORT ref_num = 0; + UBYTE max_num = 0; + UBYTE seq_num = 0; + UBYTE rec_num; + T_SM_ASSEMBLY *assembly_elem; + T_SEG_BUF_ELEM *segBufElem; + T_SM_DATA_EXT data; + T_ACI_SMS_STAT status; + UBYTE next_exp_num; + UBYTE ret; + static UBYTE i = 0; + UBYTE mem_psa; + + + + CHAR *address; + + TRACE_FUNCTION ("concSMS_Collect()"); + + /* initialize data_conc->len */ + data_conc->len = 0; /* ACI-SPR-16372 */ + /* extract parameters from user data header */ + + /* 8-bit reference number */ + if (sm->udh.data[0] EQ SMS_IEI_CONC_8BIT) + { + ref_num = sm->udh.data[2]; + max_num = sm->udh.data[3]; + seq_num = sm->udh.data[4]; + } + + /* 16-bit reference number */ + else if (sm->udh.data[0] EQ SMS_IEI_CONC_16BIT) + { + /* MSB */ + ref_num = (sm->udh.data[2] & 0x00FF) << 8u; /* 23.040 9.1.2.1 */ + + /* LSB */ + ref_num += sm->udh.data[3]; + + max_num = sm->udh.data[4]; + seq_num = sm->udh.data[5]; + } + + rec_num = sm->msg_ref; + status = sm->stat; + address = sm->adress; + + data.data = sm->data.data; + data.len = sm->data.len; + + TRACE_EVENT_P1("rec_num:%d", rec_num); + TRACE_EVENT_P1("concSMS_GetFirstIndex():%d", + concSMS_GetFirstIndex (ref_num, sm->adress)); + TRACE_EVENT_P1("ref_num:0x%04x", ref_num); + TRACE_EVENT_P1("concSMS_GetMsgRef():0x%04x", concSMS_GetMsgRef ( sm )); + TRACE_EVENT_P1("max_num:%d", max_num); + TRACE_EVENT_P1("seq_num:%d", seq_num); + + /* try to get an existing assembly buffer */ + assembly_elem = concSMS_getAsBuffer(ref_num, address); + + /* if no assembly buffer found, then assume that is a new conc. SM */ + if (assembly_elem EQ NULL) + { + next_exp_num = 1; + } + else + { + next_exp_num = assembly_elem->next_exp_num; + } + + + /* the received seq_num is not valid */ + if ( (seq_num EQ 0) OR (seq_num > max_num) OR (seq_num < next_exp_num) ) + { + return CONC_ERR_UNKN; + } + + + + /* + * If CMTI, then add every received segment to concatenation buffer. + * The segments in the concatenation buffer were also stored in non-volatile + * memory. + */ + if (isStored) + { + if (cmhSMS_getMemPsa(mem_aci, &mem_psa) EQ FALSE) + { + return CONC_ERR_UNKN; + } + + ret = concSMS_addToConcatList(ref_num, address, max_num, + seq_num, rec_num, status, mem_psa); + + if (ret EQ FALSE) + { + dFLAG = TRUE; + RefNum_Del = ref_num; + concShrdPrm.full.Conc_Full = TRUE; + concShrdPrm.full.RefNum = ref_num; + memcpy(Addres,address,sizeof(Addres)); + concShrdPrm.full.MaxNum = max_num; + concShrdPrm.full.SeqNum[i] = seq_num; + concShrdPrm.full.RecNum[i] = rec_num; + concShrdPrm.full.MemType[i] = mem_psa; + i++; + concShrdPrm.full.Numsegs = i; + /* error: concatenation buffer full */ + return CONC_ERR_BUF_FULL; + } + } + i = 0; + if ( seq_num > next_exp_num ) + { + /* + * the received segment is not in sequence + * -> add it to the segment buffer + */ + ret = concSMS_addToSegBuffer(ref_num, address, seq_num, + rec_num, status, &data); + if (ret EQ FALSE) + { + /* error: segment buffer full */ + return CONC_ERR_BUF_FULL; + } + return CONC_CONTINUED; + } + else + { + /* + * the received segment is in sequence + */ + + while (1) + { + + /* add segment to assembly buffer */ + assembly_elem = concSMS_addToAsBuffer (ref_num, address, max_num, &data); + + + /* free data memory only for data from segment buffer */ + if (data.data NEQ sm->data.data) + { + ACI_MFREE (data.data); + } + + /* error: no assembly buffer available */ + if (assembly_elem EQ NULL) + { + return CONC_ERR_BUF_FULL; + } + + /* assembly of concatenated SM is completed */ + if (assembly_elem->next_exp_num EQ max_num+1) + { + concSMS_removeFromAsBuffer(data_conc, ref_num, address); + concSMS_sortConcatList(ref_num, address); + return CONC_COMPLETED; + } + + /* maximum reached in assembly buffer , assembly is NOT completed */ + if (assembly_elem->seg_count EQ CONC_MAX_SEGS) + { + concSMS_getFromAsBuffer(data_conc, ref_num, address); + concSMS_sortConcatList(ref_num, address); + return CONC_COMPLETED; + } + + /* search and remove the next segment from segment buffer */ + segBufElem = concSMS_removeFromSegBuffer(ref_num, + address, + assembly_elem->next_exp_num); + if ( segBufElem EQ NULL ) + { + /* no segment found */ + return CONC_CONTINUED; + } + + /* for adding to concatenation list */ + rec_num = segBufElem->rec_num; + status = (T_ACI_SMS_STAT)segBufElem->status; + + /* for adding to assembly buffer */ + data.data = segBufElem->data.data; + data.len = segBufElem->data.len; + + ACI_MFREE(segBufElem); + } /* while */ + } /* if ( seq_num EQ next_exp_num ) */ +} + + + +GLOBAL void concSMS_Init() +{ + concShrdPrm.isConcatenated = FALSE; + + memset (&concShrdPrm, 0, sizeof(T_CONC_SHRD_PRM) ); + + memset (&assembly_list, 0, sizeof(T_SM_ASSEMBLY)*MAX_BUF_ELEMS); + memset (&segBuf_list, 0, sizeof(T_SEG_BUF) *MAX_BUF_ELEMS); + memset (&concBuf_list, 0, sizeof(T_CONC_BUF) *MAX_CONC_BUF_ELEMS); + + concShrdPrm.l_uncomp8bit_data = L_UNCOMP_8BIT_DATA; + concShrdPrm.l_uncomp7bit_data = L_UNCOMP_7BIT_DATA; + concShrdPrm.l_uncomp8bit_data_conc = L_UNCOMP_8BIT_DATA_CONC; + concShrdPrm.l_uncomp7bit_data_conc = L_UNCOMP_7BIT_DATA_CONC; + concShrdPrm.elem_count = 0; +#ifdef _CONC_TESTING_ +#ifndef _SIMULATION_ + concSMS_InitForTesting(); +#endif +#endif +} + + +/* only for test purposes */ +GLOBAL void concSMS_InitForTesting() +{ + concShrdPrm.concTesting = TRUE; + concShrdPrm.l_uncomp8bit_data = L_UNCOMP_8BIT_DATA_TST; + concShrdPrm.l_uncomp7bit_data = L_UNCOMP_7BIT_DATA_TST; + concShrdPrm.l_uncomp8bit_data_conc = L_UNCOMP_8BIT_DATA_CONC_TST; + concShrdPrm.l_uncomp7bit_data_conc = L_UNCOMP_7BIT_DATA_CONC_TST; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : MODULE : CONC_SMS | +| STATE : code ROUTINE : concSMS_delAllIncompleteMsg| ++--------------------------------------------------------------------+ + + PURPOSE : This function must be called by the MFW to clean all + segment buffers, assembly buffers and remove all + incompleted SM from concat. buffer and non-volatile memory. + +*/ +GLOBAL void concSMS_delAllIncompleteMsg( ) +{ + T_SEG_BUF *segBuf = NULL; + T_SEG_BUF_ELEM *segBufElem; + T_CONC_BUF *concBuf = NULL; + T_CONC_BUF_ELEM *concBufElem; + T_SM_ASSEMBLY *assembly_elem; + USHORT count; + + UBYTE i; + + TRACE_FUNCTION ("concSMS_delAllIncompleteMsg()"); + + + concShrdPrm.srcId = CMD_SRC_LCL; + + for (i=0; i<MAX_BUF_ELEMS; i++) + { + /* delete assembly buffer */ + if (assembly_list[i].in_use) + { + assembly_elem = &assembly_list[i]; + assembly_elem->in_use = FALSE; + ACI_MFREE(assembly_elem->data.data); + } + + + /* delete segment buffer */ + if (segBuf_list[i].in_use) + { + segBuf = &segBuf_list[i]; + + /* remove element from segment buffer */ + segBufElem = remove_first_element(segBuf->list); + + if (segBufElem NEQ NULL) + { + /* free memory */ + ACI_MFREE(segBufElem->data.data); + ACI_MFREE(segBufElem); + } + else + { + segBuf->in_use = FALSE; + } + } + } /* for */ + + + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + /* find concat. buffer in use */ + if (concBuf_list[i].in_use) + { + + /* get number of segments in this concat. buffer */ + count = get_list_count(concBuf_list[i].list); + + /* conc buffer is incomplete */ + if ((count < concBuf_list[i].max_num) AND (count < CONC_MAX_SEGS)) + { + if (count EQ 0) + { + /* last element of one conc buffer was deleted */ + concBuf_list[i].in_use = FALSE; + R_AT ( RAT_OK,(T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGC ); + continue; + } + concBuf = &concBuf_list[i]; + break; + } + } + } + + if (concBuf) + { + /* remove element from concat. buffer */ + concBufElem = remove_first_element(concBuf->list); + + if (concBufElem) + { + + /* delete segment from non-volatile memory */ +#ifdef TI_PS_FF_CONC_SMS + sAT_PlusCMGD_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, concBufElem->rec_num, + smsShrdPrm.status, concSMS_delAllIncompleteMsg, rConcSMS_PlusCMS_CMGD); +#else + sAT_PlusCMGD_Gl(concShrdPrm.srcId, concBufElem->rec_num, smsShrdPrm.status, + concSMS_delAllIncompleteMsg, rAT_PlusCMS); +#endif /* TI_PS_FF_CONC_SMS */ + + /* free memory */ + ACI_MFREE(concBufElem); + /* decrease total count of stored CSMS segments by 1*/ + concShrdPrm.elem_count--; + } + } +} + + + +/************** Help Functions ******************************/ + + +/* ++-------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : CONC_SMS | +| ROUTINE : concSMS_printConcatList | ++-------------------------------------------------------------------+ + + PURPOSE : +*/ + +LOCAL void concSMS_printConcatList () +{ + T_ACI_LIST *current; + UBYTE i; + T_CONC_BUF *concBuf; + T_CONC_BUF_ELEM *elem; + + + TRACE_EVENT("Concatenation List:"); + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + if (concBuf_list[i].in_use EQ TRUE) + { + concBuf = &concBuf_list[i]; + TRACE_EVENT_P2(" ref_num: 0x%04x , max_num: %u", + concBuf->ref_num, concBuf->max_num); + current = concBuf->list; + while (current) + { + elem = (T_CONC_BUF_ELEM*) current->msg; + TRACE_EVENT_P4(" seq_num: %d , rec_num: %d , status: %d, mem= %d", + elem->seq_num, elem->rec_num, elem->status, elem->mem); + current = current->next; + } + } + } +} + +/* Marcus: Issue 872: 03/10/2002 ++-------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : CONC_SMS | +| ROUTINE : concSMS_findMaxRefNum | ++-------------------------------------------------------------------+ + + PURPOSE : Find the highest value of concBuf_list[i].ref_num +*/ + +LOCAL USHORT concSMS_findMaxRefNum(void) +{ + UBYTE i; + USHORT ref_num = 0; + TRACE_FUNCTION("concSMS_findMaxRefNum()"); + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + if (concBuf_list[i].in_use EQ TRUE) + { + if ((concBuf_list[i].ref_num & 0x00ff)> ref_num) /* since we use only 8-Bit ref_num */ + ref_num = concBuf_list[i].ref_num & 0x00ff; + } + } + return ref_num; +} + + +GLOBAL void concSMS_clearIncompleteMsg() +{ + + T_SEG_BUF *segBuf = NULL; + T_SEG_BUF_ELEM *segBufElem; + T_SM_ASSEMBLY *assembly_elem; + T_CONC_BUF *concBuf = NULL; + T_CONC_BUF_ELEM *concBufElem; + UBYTE i; + + + + TRACE_FUNCTION ("concSMS_clearIncompleteMsg()"); + + + if (RefNum_Del EQ concShrdPrm.full.RefNum) + { + concShrdPrm.full.Conc_Full = FALSE; + concShrdPrm.full.RefNum = 0xFF; + } + + + for (i=0; i<MAX_BUF_ELEMS; i++) + { + /* delete assembly buffer */ + if (assembly_list[i].in_use AND assembly_list[i].ref_num EQ RefNum_Del) + { + assembly_elem = &assembly_list[i]; + assembly_elem->in_use = FALSE; + ACI_MFREE(assembly_elem->data.data); + break; + } + + + /* delete segment buffer */ + if (segBuf_list[i].in_use AND segBuf_list[i].ref_num EQ RefNum_Del) + { + + segBuf = &segBuf_list[i]; + + + /*remove element from segment buffer */ + segBufElem = remove_first_element(segBuf->list); + + if (segBufElem NEQ NULL) + { + segBuf->in_use = FALSE; + /* free memory */ + ACI_MFREE(segBufElem->data.data); + ACI_MFREE(segBufElem); + + + } + else + { + + segBuf->in_use = FALSE; + + } + break; + } + + } + + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + /* find concat. buffer in use */ + if (concBuf_list[i].in_use AND concBuf_list[i].ref_num EQ RefNum_Del) + { + concBuf_list[i].in_use = FALSE; + concBuf = &concBuf_list[i]; + break; + + } + } + + if (concBuf) + { + /* remove element from concat. buffer */ + concBufElem = remove_first_element(concBuf->list); + + if (concBufElem) + { + /* free memory */ + ACI_MFREE(concBufElem); + /* decrease total count of stored CSMS segments by 1*/ + concShrdPrm.elem_count--; + + } + } +} + + + +GLOBAL void concSMS_AddtoconcBuff(void) +{ + UBYTE i; + + + TRACE_FUNCTION("concSMS_AddtoconcBuff()"); + + for (i=0;i<concShrdPrm.full.Numsegs;i++) + { + concSMS_addToConcatList(concShrdPrm.full.RefNum,Addres, + concShrdPrm.full.MaxNum,concShrdPrm.full.SeqNum[i], + concShrdPrm.full.RecNum[i],SMS_STAT_RecRead,concShrdPrm.full.MemType[i]); + } +} + +/* ++-------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : CONC_SMS | +| ROUTINE : concSMS_DeleteConcList | ++-------------------------------------------------------------------+ + + PURPOSE : This function is used to delete the concatinated SMS, when + the CMGD command contails the delete flag greater than ZERO. + +*/ + +GLOBAL void concSMS_DeleteConcList ( ) +{ + T_CONC_CMGD *prm = &concShrdPrm.specPrm.concCMGD; + T_CONC_BUF_ELEM *elem; + T_ACI_LIST *conc_list; + + TRACE_FUNCTION ("concSMS_DeleteConcList()"); + + + elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg; + + /* remove the old element from concatenation list and free its memory */ + conc_list = concSMS_removeFromConcatList(prm->ref_num, prm->address, elem->rec_num); + + concSMS_printConcatList(); + + if (conc_list NEQ NULL) + { + TRACE_EVENT("conc_list not null"); + elem = (T_CONC_BUF_ELEM *)conc_list->msg; + + /* save the concatenation list */ + prm->currConcBufListElem= conc_list; + } + else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */ + { + TRACE_EVENT("Concat List is NULL : concSMS_DeleteConcList"); + UNSET_CONC; + } +} + +#ifdef TI_PS_FF_CONC_SMS +GLOBAL void rConcSMS_PercentCMGR ( T_ACI_CMGL_SM* sm, + T_ACI_CMGR_CBM* cbm ) +{ + T_CONC_CMGR *prm = &concShrdPrm.specPrm.concCMGR; + + TRACE_FUNCTION ("rConcSMS_PercentCMGR ()"); + + if (prm->currConcBufListElem NEQ NULL) + { + T_CONC_BUF_ELEM *elem; + elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg; + + sAT_PercentCMGR_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num, + (T_ACI_SMS_READ) concShrdPrm.specPrm.concCMGR.rdMode, + rConcSMS_PercentCMGR); + + prm->currConcBufListElem = prm->currConcBufListElem->next; + +#ifdef _CONC_TESTING_ + rAT_PercentCMGR_Ext (sm, cbm); +#else + rAT_PercentCMGR (sm, cbm); +#endif + + } + else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */ + { +#ifdef _CONC_TESTING_ + rAT_PercentCMGR_Ext (sm, cbm); +#else + rAT_PercentCMGR (sm, cbm); +#endif + + R_AT ( RAT_OK, (T_ACI_CMD_SRC)concShrdPrm.srcId ) ( AT_CMD_P_CMGR ); + UNSET_CONC; + } +} + +#endif /* TI_PS_FF_CONC_SMS */ +/* + * This functions checks if the conc can be extended. If the maximum + * capacity is reached the CSMS will be handled as normal (single) SMS. + */ +BOOL concSMS_concBufferAvail() +{ + USHORT count=0; + int i; + + TRACE_FUNCTION("concSMS_concBufferAvail"); + + /* check if there is a free conc buffer available */ + for (i=0; i<MAX_CONC_BUF_ELEMS; i++) + { + if (concBuf_list[i].in_use EQ TRUE) + { + count++; + } + } + if (count >= MAX_CONC_BUF_ELEMS) + { + return FALSE; /* all conc buffer in use, no free available */ + } + + return TRUE; +} + +