comparison src/g23m-aci/aci/conc_sms.c @ 162:53929b40109c

src/g23m-aci: initial import from TCS3.2/LoCosto
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 11 Oct 2016 02:02:43 +0000
parents
children
comparison
equal deleted inserted replaced
161:4557e2a9c18e 162:53929b40109c
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : $Workfile::
4 | Modul : CONC_SMS
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : SMS Concatenation Handler
18 +-----------------------------------------------------------------------------
19 */
20
21 #ifndef CONC_SMS_C
22 #define CONC_SMS_C
23 #endif
24
25 /*==== INCLUDES ===================================================*/
26
27 #include "aci_all.h"
28
29 #include "aci_cmh.h"
30 #include "ati_cmd.h"
31 #include "aci_cmd.h"
32
33 #include "aci_fd.h"
34 #include "aci_mem.h"
35
36 #include "psa.h"
37 #include "psa_sms.h"
38
39 #include "cmh.h"
40 #include "cmh_sms.h"
41
42 #include "psa_cc.h"
43
44 #include "typedefs.h"
45 #include "aci_lst.h"
46
47 #include "psa_util.h"
48 #include "conc_sms.h"
49
50 #ifdef _CONC_TESTING_
51 #include "aci_io.h"
52 #include "aci_mfw.h"
53 #endif
54
55 /*==== VARIABLES ==================================================*/
56
57 GLOBAL T_SM_ASSEMBLY assembly_list[MAX_BUF_ELEMS];
58 GLOBAL T_SEG_BUF segBuf_list [MAX_BUF_ELEMS];
59 GLOBAL T_CONC_BUF concBuf_list [MAX_CONC_BUF_ELEMS];
60 LOCAL USHORT RefNum_Del = 0xFF;
61 LOCAL BOOL dFLAG = FALSE;
62 LOCAL CHAR Addres[MAX_SMS_ADDR_DIG];
63
64
65
66 /*==== FUNCTIONS ==================================================*/
67
68 LOCAL void concSMS_printConcatList ();
69 LOCAL USHORT concSMS_findMaxRefNum(void); // Marcus: Issue 872: 03/10/2002
70
71
72
73 /*
74 +--------------------------------------------------------------------+
75 | PROJECT : MODULE : CONC_SMS |
76 | STATE : code ROUTINE : concSMS_findSeqNumSB |
77 +--------------------------------------------------------------------+
78
79 PURPOSE : find 'seq_num' in segment buffer
80 */
81 LOCAL BOOL concSMS_findSeqNumSB ( UBYTE critrerium,
82 void *elem )
83 {
84 T_SEG_BUF_ELEM *compared = (T_SEG_BUF_ELEM *)elem;
85
86 if ( compared->seq_num == critrerium )
87 return TRUE;
88 else
89 return FALSE;
90 }
91
92
93
94 /*
95 +--------------------------------------------------------------------+
96 | PROJECT : MODULE : CONC_SMS |
97 | STATE : code ROUTINE : concSMS_findSeqNumElemCB |
98 +--------------------------------------------------------------------+
99
100 PURPOSE : find 'seq_num' in concatenation buffer
101 */
102 LOCAL BOOL concSMS_findSeqNumElemCB ( UBYTE critrerium,
103 void *elem )
104 {
105 T_CONC_BUF_ELEM *compared = (T_CONC_BUF_ELEM *)elem;
106
107 if ( compared->seq_num == critrerium )
108 return TRUE;
109 else
110 return FALSE;
111 }
112
113
114
115 /*
116 +--------------------------------------------------------------------+
117 | PROJECT : MODULE : CONC_SMS |
118 | STATE : code ROUTINE : concSMS_findRecNumElemCB |
119 +--------------------------------------------------------------------+
120
121 PURPOSE : find 'rec_num' in concatenation buffer
122 */
123 LOCAL BOOL concSMS_findRecNumElemCB ( UBYTE critrerium,
124 void *elem )
125 {
126 T_CONC_BUF_ELEM *compared = (T_CONC_BUF_ELEM *)elem;
127
128 if ( compared->rec_num == critrerium )
129 return TRUE;
130 else
131 return FALSE;
132 }
133
134 /*
135 +--------------------------------------------------------------------+
136 | PROJECT : MODULE : CONC_SMS |
137 | STATE : code ROUTINE : concSMS_getAsBuffer |
138 +--------------------------------------------------------------------+
139
140 PURPOSE : This functions searchs the assembly buffer for ref_num
141 and address.
142 */
143 LOCAL T_SM_ASSEMBLY* concSMS_getAsBuffer( USHORT ref_num, CHAR *address )
144 {
145 UBYTE i;
146
147 TRACE_FUNCTION ("concSMS_getAsBuffer()");
148
149 /* search for the element */
150 for (i=0; i<MAX_BUF_ELEMS; i++)
151 {
152 if ( (assembly_list[i].ref_num EQ ref_num) AND
153 (assembly_list[i].in_use) )
154 {
155 if ((address NEQ NULL) /* AND (address[0] NEQ '\0') */)
156 {
157 if (!strcmp(assembly_list[i].address, address))
158 {
159 return &assembly_list[i];
160 }
161 }
162 else
163 {
164 return &assembly_list[i];
165 }
166 }
167 }
168
169 return NULL;
170 }
171
172
173 /*
174 +--------------------------------------------------------------------+
175 | PROJECT : MODULE : CONC_SMS |
176 | STATE : code ROUTINE : concSMS_addToAsBuffer |
177 +--------------------------------------------------------------------+
178
179 PURPOSE : This function adds data to the assembly buffer. It returns
180 NULL if buffer is full.
181
182 */
183 LOCAL T_SM_ASSEMBLY* concSMS_addToAsBuffer ( USHORT ref_num,
184 CHAR *address,
185 UBYTE max_num,
186 T_SM_DATA_EXT *data )
187 {
188 UBYTE i;
189 T_SM_ASSEMBLY *assembly_elem = NULL;
190
191 TRACE_FUNCTION ("concSMS_addToAsBuffer()");
192
193
194 /* search for the element */
195 assembly_elem = concSMS_getAsBuffer( ref_num, address );
196
197 #ifdef _CONC_TESTING_
198 TRACE_EVENT_P1("addToAsBuffer:[0].in_use: %d", assembly_list[0].in_use);
199 TRACE_EVENT_P1("addToAsBuffer:[1].in_use: %d", assembly_list[1].in_use);
200 #endif
201
202 /* element not found */
203 if (assembly_elem EQ NULL)
204 {
205 /* search for an unused list entry */
206 for (i=0; i<MAX_BUF_ELEMS; i++)
207 {
208 if (assembly_list[i].in_use EQ FALSE)
209 {
210 assembly_elem = &assembly_list[i];
211 break;
212 }
213 }
214
215 /* buffer is full */
216 if (assembly_elem EQ NULL)
217 return NULL;
218
219
220 /* create new assembly buffer for this ref_num*/
221 assembly_elem->in_use = TRUE;
222 assembly_elem->ref_num = ref_num;
223
224 if ( (address NEQ NULL) AND (address[0] NEQ '\0') )
225 strcpy(assembly_elem->address, address);
226 else
227 assembly_elem->address[0] = '\0';
228
229 assembly_elem->next_exp_num = 1;
230 assembly_elem->segs_left = max_num;
231 assembly_elem->seg_count = 0;
232 } /* if (assembly_elem EQ NULL) */
233
234 if (assembly_elem->seg_count EQ 0)
235 {
236 /* alloc memory for data to assemble */
237
238 UBYTE segs;
239
240 segs = MINIMUM(assembly_elem->segs_left, CONC_MAX_SEGS);
241 ACI_MALLOC(assembly_elem->data.data, (USHORT)(MAX_SM_LEN*segs));
242 assembly_elem->segs_left -= segs;
243 assembly_elem->data.len = 0;
244 }
245
246 memcpy(assembly_elem->data.data+assembly_elem->data.len,
247 data->data, data->len);
248
249 assembly_elem->data.len += data->len;
250 assembly_elem->data.data[assembly_elem->data.len] = '\0';
251 assembly_elem->next_exp_num++;
252 assembly_elem->seg_count++;
253
254 #ifdef _CONC_TESTING_
255 if (assembly_elem->data.len < TTRACE_LEN)
256 {
257 TRACE_EVENT_P1("addToAsBuffer:data.data: %s", assembly_elem->data.data);
258 }
259 TRACE_EVENT_P1("addToAsBuffer:data.len: %d", assembly_elem->data.len);
260 TRACE_EVENT_P1("addToAsBuffer:next_exp_num: %d", assembly_elem->next_exp_num);
261 TRACE_EVENT_P1("addToAsBuffer:seg_count: %d", assembly_elem->seg_count);
262 #endif
263
264 return assembly_elem;
265 }
266
267
268 /*
269 +---------------------------------------------------------------------+
270 | PROJECT : MODULE : CONC_SMS |
271 | STATE : code ROUTINE : concSMS_removeFromAsBuffer |
272 +---------------------------------------------------------------------+
273
274 PURPOSE : This functions gets data from the assembly buffer and
275 sets it to 'unused'. The assembly is completed.
276
277 */
278 LOCAL UBYTE concSMS_removeFromAsBuffer(T_SM_DATA_EXT *data_conc,
279 USHORT ref_num,
280 CHAR *address)
281 {
282 T_SM_ASSEMBLY *assembly_buf;
283
284 TRACE_FUNCTION ("concSMS_removeFromAsBuffer()");
285
286
287 /* search for the element */
288 assembly_buf = concSMS_getAsBuffer( ref_num, address );
289
290 if (assembly_buf EQ NULL)
291 return FALSE;
292
293 assembly_buf->in_use = FALSE;
294
295 data_conc->data = assembly_buf->data.data;
296 data_conc->len = assembly_buf->data.len;
297
298 return TRUE;
299 }
300
301
302 /*
303 +---------------------------------------------------------------------+
304 | PROJECT : MODULE : CONC_SMS |
305 | STATE : code ROUTINE : concSMS_getFromAsBuffer |
306 +---------------------------------------------------------------------+
307
308 PURPOSE : This functions gets data from the assembly buffer and
309 resets the seg_count. The assembly buffer is still in use
310 and the assembly is not completed.
311
312 */
313 LOCAL UBYTE concSMS_getFromAsBuffer(T_SM_DATA_EXT *data_conc,
314 USHORT ref_num,
315 CHAR *address)
316 {
317 T_SM_ASSEMBLY *assembly_buf;
318
319 TRACE_FUNCTION ("concSMS_getFromAsBuffer()");
320
321
322 /* search for the element */
323 assembly_buf = concSMS_getAsBuffer( ref_num, address );
324
325 /* assemlby buffer not found */
326 if (assembly_buf EQ NULL)
327 return FALSE;
328
329 assembly_buf->seg_count = 0;
330
331 data_conc->data = assembly_buf->data.data;
332 data_conc->len = assembly_buf->data.len;
333
334 return TRUE;
335 }
336
337
338 /*
339 +--------------------------------------------------------------------+
340 | PROJECT : MODULE : CONC_SMS |
341 | STATE : code ROUTINE : concSMS_getSegBuffer |
342 +--------------------------------------------------------------------+
343
344 PURPOSE : This functions searchs the segment buffer for ref_num
345 and address.
346 */
347 LOCAL T_SEG_BUF* concSMS_getSegBuffer( USHORT ref_num, CHAR *address )
348 {
349 UBYTE i;
350
351 TRACE_FUNCTION ("concSMS_getSegBuffer()");
352
353
354 /* search for the element */
355 for (i=0; i<MAX_BUF_ELEMS; i++)
356 {
357 if ((segBuf_list[i].ref_num EQ ref_num) AND
358 (segBuf_list[i].in_use))
359 {
360
361 if ((address NEQ NULL) /* AND (address[0] NEQ '\0') */)
362 {
363 if (!strcmp(segBuf_list[i].address, address))
364 return &segBuf_list[i];
365 }
366 else
367 {
368 return &segBuf_list[i];
369 }
370 }
371 }
372
373 return NULL;
374 }
375
376
377 /*
378 +--------------------------------------------------------------------+
379 | PROJECT : MODULE : CONC_SMS |
380 | STATE : code ROUTINE : concSMS_addToSegBuffer |
381 +--------------------------------------------------------------------+
382
383 PURPOSE : This functions adds one segment to the buffer and returns
384 FALSE if no segment buffer is available or the current
385 seg buffer is full.
386
387 */
388 LOCAL UBYTE concSMS_addToSegBuffer ( USHORT ref_num,
389 CHAR *address,
390 UBYTE seq_num,
391 UBYTE rec_num,
392 T_ACI_SMS_STAT status,
393 T_SM_DATA_EXT *data )
394 {
395 T_SEG_BUF *segBuf = NULL;
396 T_SEG_BUF_ELEM *segBufElem;
397 USHORT count;
398 UBYTE i;
399
400 TRACE_FUNCTION ("concSMS_addToSegBuffer()");
401
402
403 /* search for the segment buffer */
404 segBuf = concSMS_getSegBuffer( ref_num, address );
405
406 /* element not found */
407 if (segBuf EQ NULL)
408 {
409 /* search for an unused list entry */
410 for (i=0; i<MAX_BUF_ELEMS; i++)
411 {
412 if (segBuf_list[i].in_use EQ FALSE)
413 {
414 segBuf = &segBuf_list[i];
415 break;
416 }
417 }
418
419 /* no segment buffer available */
420 if ( segBuf EQ NULL)
421 return FALSE;
422
423 /* initialise new buffer */
424 segBuf->in_use = TRUE;
425 segBuf->ref_num = ref_num;
426 if ( (address) AND (address[0] NEQ '\0') )
427 strcpy(segBuf->address, address);
428 else
429 segBuf->address[0] = '\0';
430 segBuf->list = new_list();
431 }
432
433 count = get_list_count(segBuf->list);
434 if ( count >= CONC_MAX_SEGS )
435 {
436 /* clean segment buffer before it overflows */
437 while (1)
438 {
439 segBufElem = remove_first_element(segBuf->list);
440 if (segBufElem EQ NULL)
441 break;
442 ACI_MFREE(segBufElem->data.data);
443 ACI_MFREE(segBufElem);
444 }
445 segBuf->in_use = FALSE;
446 return FALSE;
447 }
448
449 /* create new segment buffer element */
450 ACI_MALLOC(segBufElem, sizeof(T_SEG_BUF_ELEM));
451 memset(segBufElem, 0, sizeof(T_SEG_BUF_ELEM));
452
453 /* fill new buffer element */
454 segBufElem->seq_num = seq_num;
455 segBufElem->rec_num = rec_num;
456 segBufElem->status = status;
457
458 /* alloc memory and copy user data to segment buffer */
459 ACI_MALLOC(segBufElem->data.data, data->len);
460 segBufElem->data.len = data->len;
461 memcpy(segBufElem->data.data, data->data, data->len);
462
463 /* insert element (segment) into the segment buffer */
464 insert_list(segBuf->list, segBufElem);
465
466 return TRUE;
467 }
468
469
470 /*
471 +--------------------------------------------------------------------+
472 | PROJECT : MODULE : CONC_SMS |
473 | STATE : code ROUTINE : concSMS_removeFromSegBuffer|
474 +--------------------------------------------------------------------+
475
476 PURPOSE : This function finds and removes the segment with
477 'seq_num' from the segment buffer.
478
479 */
480 LOCAL T_SEG_BUF_ELEM* concSMS_removeFromSegBuffer ( USHORT ref_num,
481 CHAR* address,
482 UBYTE seq_num )
483 {
484 T_SEG_BUF *segBuf = NULL;
485 T_SEG_BUF_ELEM *segBufElem;
486
487 USHORT count;
488
489 TRACE_FUNCTION ("concSMS_removeFromSegBuffer()");
490
491
492 /* search for the segment buffer */
493 segBuf = concSMS_getSegBuffer( ref_num, address );
494
495
496 /* segment buffer not found */
497 if (segBuf EQ NULL)
498 return NULL;
499
500 segBufElem = remove_element(segBuf->list, seq_num, concSMS_findSeqNumSB);
501
502 if (segBufElem EQ NULL)
503 {
504 return NULL; /* didn't find the segment buffer element for this seq_num */
505 }
506
507 count = get_list_count(segBuf->list);
508
509 if (count EQ 0)
510 {
511 ACI_MFREE (segBuf->list);
512 segBuf->list = NULL;
513 segBuf->in_use = FALSE;
514 }
515
516 return segBufElem;
517
518 }
519
520
521 /*
522 +--------------------------------------------------------------------+
523 | PROJECT : MODULE : CONC_SMS |
524 | STATE : code ROUTINE : concSMS_getConcBuffer |
525 +--------------------------------------------------------------------+
526
527 PURPOSE : This functions searchs the concatenations buffer for
528 ref_num and address.
529 */
530 LOCAL T_CONC_BUF* concSMS_getConcBuffer( USHORT ref_num, CHAR *address )
531 {
532 UBYTE i;
533
534 TRACE_FUNCTION ("concSMS_getConcBuffer()");
535
536 /* search for the element */
537 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
538 {
539 if ((concBuf_list[i].ref_num EQ ref_num) AND
540 (concBuf_list[i].in_use))
541 {
542 if ((address NEQ NULL) /* AND (address[0] NEQ '\0') */)
543 {
544 if (!strcmp(concBuf_list[i].address, address))
545 {
546 return &concBuf_list[i];
547 }
548 }
549 else
550 {
551 return &concBuf_list[i];
552 }
553 }
554 }
555
556 return NULL;
557 }
558
559
560 /*
561 +--------------------------------------------------------------------+
562 | PROJECT : MODULE : CONC_SMS |
563 | STATE : code ROUTINE : concSMS_addToConcatList |
564 +--------------------------------------------------------------------+
565
566 PURPOSE :
567 */
568 LOCAL BOOL concSMS_addToConcatList ( USHORT ref_num,
569 CHAR *address,
570 UBYTE max_num,
571 UBYTE seq_num,
572 UBYTE rec_num,
573 T_ACI_SMS_STAT status,
574 UBYTE mem)
575 {
576 T_CONC_BUF *concBuf;
577 T_CONC_BUF_ELEM *concBufElem;
578 UBYTE i;
579
580 TRACE_FUNCTION ("concSMS_addToConcatList()");
581
582
583 /* search for concatenation buffer */
584 concBuf = concSMS_getConcBuffer( ref_num, address );
585
586
587 /* element not found */
588 if (concBuf EQ NULL)
589 {
590
591 /* search for an unused list entry */
592 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
593 {
594 if (concBuf_list[i].in_use EQ FALSE)
595 {
596 concBuf = &concBuf_list[i];
597 break;
598 }
599 }
600
601 /* buffer is full */
602 if ( concBuf EQ NULL)
603 return FALSE;
604
605
606 concBuf->in_use = TRUE;
607 concBuf->ref_num = ref_num;
608
609 if ( (address) AND (address[0] NEQ '\0') )
610 strcpy(concBuf->address, address);
611 else
612 concBuf->address[0] = '\0';
613
614 concBuf->max_num = max_num;
615 concBuf->list = new_list();
616 }
617
618
619 /* don't add elements with same seq_num to the Concatenation Buffer */
620 concBufElem = find_element(concBuf->list,seq_num,concSMS_findSeqNumElemCB);
621 if (concBufElem)
622 return FALSE;
623
624
625
626 /* create new conc. buffer element */
627 ACI_MALLOC(concBufElem, sizeof(T_CONC_BUF_ELEM));
628
629 /* increase total count of stored CSMS segments by 1*/
630 concShrdPrm.elem_count++;
631
632 concBufElem->seq_num = seq_num;
633 concBufElem->rec_num = rec_num;
634 concBufElem->status = status;
635 concBufElem->mem = mem;
636
637 /* insert element into the conc. buffer */
638 insert_list(concBuf->list, concBufElem);
639
640 concSMS_printConcatList();
641
642 return TRUE;
643 }
644
645
646
647 /*
648 +---------------------------------------------------------------------+
649 | PROJECT : MODULE : CONC_SMS |
650 | STATE : code ROUTINE : concSMS_removeFromConcatList|
651 +---------------------------------------------------------------------+
652
653 PURPOSE : This function removes and FREES the memory for the element.
654 */
655 LOCAL T_ACI_LIST *concSMS_removeFromConcatList ( USHORT ref_num,
656 CHAR *address,
657 UBYTE rec_num )
658 {
659 T_CONC_BUF *concBuf = NULL;
660 T_CONC_BUF_ELEM *concBufElem;
661 USHORT count;
662
663 TRACE_FUNCTION ("concSMS_removeFromConcatList()");
664
665
666 /* search for concatenation buffer */
667 concBuf = concSMS_getConcBuffer( ref_num, address );
668
669 /* concatenation buffer not found */
670 if (concBuf EQ NULL)
671 {
672 TRACE_EVENT_P1("conc_buf NULL: rec: %d", rec_num);
673 return NULL;
674 }
675
676 concBufElem = remove_element(concBuf->list, rec_num, concSMS_findRecNumElemCB);
677
678 if (concBufElem EQ NULL)
679 {
680 TRACE_EVENT_P1("concBufElem NULL: rec: %d", rec_num);
681 return NULL;
682 }
683
684 /* free memory for this element */
685 ACI_MFREE(concBufElem);
686
687 /* decrease total count of stored CSMS segments by 1*/
688 concShrdPrm.elem_count--;
689
690 count = get_list_count(concBuf->list);
691
692 if (count EQ 0)
693 {
694 ACI_MFREE (concBuf->list);
695 concBuf->list = NULL;
696 concBuf->in_use = FALSE;
697 return NULL;
698 }
699 return concBuf->list;
700 }
701
702
703 /*
704 +---------------------------------------------------------------------+
705 | PROJECT : MODULE : CONC_SMS |
706 | STATE : code ROUTINE : concSMS_sortConcatList |
707 +---------------------------------------------------------------------+
708
709 PURPOSE : This function sorts the concat. buffer acc. to its seq_num.
710 */
711 LOCAL void concSMS_sortConcatList ( USHORT ref_num,
712 CHAR *address )
713 {
714 T_CONC_BUF *concBuf = NULL;
715 T_CONC_BUF_ELEM *concBufElem;
716 UBYTE seq_num;
717 UBYTE rec_num = 0;
718 T_ACI_LIST *oldlist, *newlist, *current;
719 USHORT count;
720
721 TRACE_FUNCTION ("concSMS_sortConcatList()");
722
723
724 /* search for concatenation buffer */
725 concBuf = concSMS_getConcBuffer( ref_num, address );
726
727 /* concatenation buffer not found */
728 if (concBuf EQ NULL)
729 return;
730
731 newlist = new_list();
732 oldlist = concBuf->list;
733
734 count = get_list_count(oldlist);
735
736 while (count)
737 {
738 seq_num = 255;
739 current = oldlist;
740 while (current)
741 {
742 concBufElem = (T_CONC_BUF_ELEM*)current->msg;
743 if ( concBufElem->seq_num < seq_num )
744 {
745 seq_num = concBufElem->seq_num;
746 rec_num = concBufElem->rec_num;
747 }
748 current = current->next;
749 }
750
751 concBufElem = remove_element(oldlist, rec_num, concSMS_findRecNumElemCB);
752
753 insert_list(newlist, concBufElem);
754
755 count = get_list_count(oldlist);
756 }
757 if (concBuf->list)
758 {
759 ACI_MFREE (concBuf->list);
760 concBuf->list = NULL;
761 }
762 concBuf->list = newlist;
763 }
764
765
766 /*
767 +--------------------------------------------------------------------+
768 | PROJECT : MODULE : CONC_SMS |
769 | STATE : code ROUTINE : concSMS_split |
770 +--------------------------------------------------------------------+
771
772 PURPOSE : return TRUE if splitting was done, otherwise FALSE
773 */
774 LOCAL UBYTE concSMS_split ( T_ACI_SM_DATA* tar_data,
775 T_SM_DATA_EXT* src_data,
776 UBYTE alphabet,
777 T_EXT_CMS_CMD_ID id)
778 {
779 #ifndef _SIMULATION_
780 T_TIME time_val; /* Used for input to random generator */
781 #endif
782
783 TRACE_FUNCTION ("concSMS_split ()");
784
785 if (alphabet EQ 0x00)
786 {
787 /* 7-bit data coding scheme */
788 if (src_data->len <= concShrdPrm.l_uncomp7bit_data)
789 {
790 tar_data->len = (UBYTE)src_data->len;
791 memcpy ( tar_data->data, src_data->data, tar_data->len );
792 return FALSE;
793 }
794 else
795 {
796 tar_data->len = concShrdPrm.l_uncomp7bit_data_conc;
797 concShrdPrm.max_sms_len = concShrdPrm.l_uncomp7bit_data_conc;
798 }
799 }
800 else
801 {
802 /* 8-bit data coding scheme */
803 if (src_data->len <= concShrdPrm.l_uncomp8bit_data)
804 {
805 tar_data->len = (UBYTE)src_data->len;
806 memcpy ( tar_data->data, src_data->data, tar_data->len );
807 return FALSE;
808 }
809 else
810 {
811 tar_data->len = concShrdPrm.l_uncomp8bit_data_conc;
812 concShrdPrm.max_sms_len = concShrdPrm.l_uncomp8bit_data_conc;
813 }
814 }
815
816 /* copy first segment to 'tar_data' */
817 memcpy ( tar_data->data, src_data->data, tar_data->len );
818
819 concShrdPrm.udh.ref_num = (UBYTE)concSMS_findMaxRefNum(); /* Marcus: Issue 872: 03/10/2002 */
820 concShrdPrm.udh.ref_num++;
821
822 concShrdPrm.udh.max_num = (src_data->len+(concShrdPrm.max_sms_len-1)) / concShrdPrm.max_sms_len;
823 concShrdPrm.udh.seq_num = 1;
824
825 if (id EQ CMGS_CONC)
826 {
827 #ifndef _SIMULATION_
828 vsi_t_time (VSI_CALLER &time_val);
829 srand((USHORT) time_val); /* initialize random generator */
830
831 /* For every conc sms going out, generate a random reference number and
832 * send it. Also when power cycled it will generate a new random number.
833 */
834 concShrdPrm.udh.ref_num = (UBYTE)rand();
835 #endif
836 concShrdPrm.specPrm.concCMGS.data.len = src_data->len;
837 concShrdPrm.specPrm.concCMGS.data.data = src_data->data;
838 concShrdPrm.specPrm.concCMGS.offset = tar_data->len;
839 return TRUE;
840 }
841
842 if (id EQ CMGW_CONC)
843 {
844 concShrdPrm.specPrm.concCMGW.data.len = src_data->len;
845 concShrdPrm.specPrm.concCMGW.data.data = src_data->data;
846 concShrdPrm.specPrm.concCMGW.offset = tar_data->len;
847 return TRUE;
848 }
849
850 return FALSE;
851 }
852
853
854 /*
855 +--------------------------------------------------------------------+
856 | PROJECT : MODULE : CONC_SMS |
857 | STATE : code ROUTINE : concSMS_fillUDH |
858 +--------------------------------------------------------------------+
859
860 PURPOSE :
861 */
862 LOCAL void concSMS_fillUDH ( T_ACI_UDH_DATA* udh,
863 UBYTE ref_num,
864 UBYTE max_num,
865 UBYTE seq_num )
866 {
867 /* fill user data header structure for 8-bit ref number */
868
869 udh->len = 0x05;
870
871 /* Information Element Identifier */
872 udh->data[0] = SMS_IEI_CONC_8BIT;
873
874 /* Information Element Identifier Length */
875 udh->data[1] = 0x03;
876
877 /* Information Element Data */
878 udh->data[2] = (UBYTE)(ref_num & 0x00FF); /* since we use only 8-Bit ref number */
879 udh->data[3] = max_num;
880 udh->data[4] = seq_num;
881 }
882
883
884
885 #ifdef TI_PS_FF_CONC_SMS
886 /********************** Init Functions *********************************/
887
888
889 /*
890 +--------------------------------------------------------------------+
891 | PROJECT : MODULE : CONC_SMS |
892 | STATE : code ROUTINE : concSMS_retrieveConcBuf |
893 +--------------------------------------------------------------------+
894
895 PURPOSE : This function searches for the concatenation buffer
896 which has 'index' in its first element. Returns
897 'CONC_ERROR' if index is not the first element or list is
898 incomplete.
899
900 */
901 LOCAL T_CONC_INIT_RETURN concSMS_retrieveConcBuf ( T_CONC_BUF **concBuf,
902 UBYTE index,
903 UBYTE mem)
904 {
905 UBYTE i;
906 T_CONC_BUF_ELEM *concBufElem;
907
908 TRACE_FUNCTION ("concSMS_retrieveConcBuf ()");
909
910 *concBuf = NULL;
911
912 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
913 {
914 concSMS_printConcatList();
915 /* find conc. buffer element for this rec number */
916 concBufElem = find_element(concBuf_list[i].list,
917 index,
918 concSMS_findRecNumElemCB);
919
920 /* element was found and check if memory type of the first segment
921 * equals to the set memory type (mem1 or mem2)
922 */
923 if ((concBufElem NEQ NULL) AND (concBufElem->mem EQ mem))
924
925 {
926 break;
927 }
928 }
929
930 if (concBufElem EQ NULL)
931 {
932 /* no concatenation handler needed */
933 return CONC_NOT_NEEDED;
934 }
935
936 *concBuf = &concBuf_list[i];
937
938
939 /* check if rec number is the first segment (with seq_num == 1) */
940 if ( ( concBufElem->seq_num EQ 1 ) AND
941 ( smsShrdPrm.status EQ CMGD_DEL_INDEX ) )
942 {
943 *concBuf = &concBuf_list[i];
944 return CONC_NEEDED;
945
946 }
947 else if( smsShrdPrm.status > CMGD_DEL_INDEX )
948 {
949 /* The below check needs to be changed for deleting all
950 the concatmessages in case of DELET FLAG > 0. */
951
952 *concBuf = &concBuf_list[i];
953 return CONC_NEEDED;
954 }
955 /* rec number is not the first element in conc. buffer
956 * allow reading of incomplete segments and tread them like "normal" SMS
957 */
958 return CONC_NOT_NEEDED;
959 }
960
961
962
963 /*
964 +--------------------------------------------------------------------+
965 | PROJECT : MODULE : CONC_SMS |
966 | STATE : code ROUTINE : concSMS_initSendFromMem |
967 +--------------------------------------------------------------------+
968
969 PURPOSE : This function initialises shared parameter for CMSS.
970
971 */
972 GLOBAL T_CONC_INIT_RETURN concSMS_initSendFromMem ( T_ACI_CMD_SRC srcId,
973 UBYTE *index,
974 CHAR *da,
975 T_ACI_TOA *toda )
976 {
977 T_CONC_BUF *concBuf = NULL;
978 T_CONC_BUF_ELEM* elem = NULL;
979 T_CONC_INIT_RETURN ret = CONC_ERROR;
980 T_CONC_CMSS *prm = &concShrdPrm.specPrm.concCMSS;
981
982
983 TRACE_FUNCTION ("concSMS_initSendFromMem ()");
984
985 ret = concSMS_retrieveConcBuf ( &concBuf, *index, smsShrdPrm.mem2);
986
987 if (ret EQ CONC_ERROR)
988 {
989 /* Error: segment is not the first segment of the SM */
990 return CONC_ERROR;
991 }
992
993 if (ret EQ CONC_NOT_NEEDED)
994 {
995 /* no conatenation handler needed */
996 return CONC_NOT_NEEDED;
997 }
998
999 concShrdPrm.sentSegs = 0;
1000 concShrdPrm.srcId = srcId;
1001
1002 if (da)
1003 {
1004 memcpy(prm->da, da, strlen(da));
1005 prm->da[strlen(da)] = '\0';
1006 prm->p_da = prm->da;
1007 }
1008 else
1009 {
1010 prm->p_da = NULL;
1011 }
1012
1013 if (toda)
1014 {
1015 memcpy(&prm->toda, toda, sizeof(T_ACI_TOA));
1016 prm->p_toda = &prm->toda;
1017 }
1018 else
1019 {
1020 prm->p_toda = NULL;
1021 }
1022
1023 /* save the first concatenated buffer element */
1024 prm->currConcBufListElem = concBuf->list;
1025
1026 prm->skipStoSent = TRUE;
1027
1028 /* skip segments with status SMS_STAT_StoSent */
1029 while (prm->currConcBufListElem)
1030 {
1031 elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg;
1032
1033 if (elem->status EQ SMS_STAT_StoSent)
1034 {
1035 prm->currConcBufListElem = prm->currConcBufListElem->next;
1036 }
1037 else
1038 {
1039 break;
1040 }
1041 }
1042
1043 /*
1044 * All elements were set to SMS_STAT_StoSent. Assume that this message was
1045 * sent completly and should be sent for the second time.
1046 */
1047 if (prm->currConcBufListElem EQ NULL)
1048 {
1049 prm->skipStoSent = FALSE;
1050
1051 /* save the first concatenated buffer element */
1052 prm->currConcBufListElem = concBuf->list;
1053
1054 elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg;
1055 }
1056
1057 *index = elem ? elem->rec_num : NULL;
1058
1059 if (elem NEQ NULL)
1060 {
1061 elem->status = SMS_STAT_StoSent;
1062 }
1063
1064 return CONC_NEEDED;
1065
1066 }
1067
1068
1069 /*
1070 +--------------------------------------------------------------------+
1071 | PROJECT : MODULE : CONC_SMS |
1072 | STATE : code ROUTINE : concSMS_initReadFromMem |
1073 +--------------------------------------------------------------------+
1074
1075 PURPOSE : This function initialises shared parameter for CMGR.
1076
1077 */
1078 GLOBAL T_CONC_INIT_RETURN concSMS_initReadFromMem ( T_ACI_CMD_SRC srcId,
1079 UBYTE index,
1080 T_ACI_SMS_READ rdMode )
1081 {
1082 T_CONC_BUF *concBuf;
1083 T_CONC_INIT_RETURN ret;
1084
1085 TRACE_FUNCTION ("concSMS_initReadFromMem ()");
1086
1087 ret = concSMS_retrieveConcBuf ( &concBuf, index, smsShrdPrm.mem2);
1088
1089 if (ret EQ CONC_ERROR)
1090 {
1091 /* Error: segment is not the first segment of the SM */
1092 return CONC_ERROR;
1093 }
1094
1095 if (ret EQ CONC_NOT_NEEDED)
1096 {
1097 /* no conatenation handler needed */
1098 return CONC_NOT_NEEDED;
1099 }
1100
1101 concShrdPrm.srcId = srcId;
1102 concShrdPrm.specPrm.concCMGR.rdMode = rdMode;
1103
1104 /* save the second concatenated buffer element */
1105 concShrdPrm.specPrm.concCMGR.currConcBufListElem = concBuf->list->next;
1106
1107 return CONC_NEEDED;
1108
1109 }
1110
1111
1112 /*
1113 +--------------------------------------------------------------------+
1114 | PROJECT : MODULE : CONC_SMS |
1115 | STATE : code ROUTINE : concSMS_initDeleteFromMem |
1116 +--------------------------------------------------------------------+
1117
1118 PURPOSE : This function initialises shared parameter for CMGD.
1119
1120 */
1121 GLOBAL T_CONC_INIT_RETURN concSMS_initDeleteFromMem ( T_ACI_CMD_SRC srcId,
1122 UBYTE index )
1123 {
1124 T_CONC_BUF *concBuf;
1125 T_CONC_INIT_RETURN ret;
1126
1127
1128 TRACE_FUNCTION ("concSMS_initDeleteFromMem ()");
1129
1130
1131 ret = concSMS_retrieveConcBuf ( &concBuf, index, smsShrdPrm.mem1);
1132
1133 if (ret EQ CONC_ERROR)
1134 {
1135 /* Error: segment is not the first segment of the SM */
1136 return CONC_ERROR;
1137 }
1138
1139 if (ret EQ CONC_NOT_NEEDED)
1140 {
1141 if (concBuf NEQ NULL)
1142 {
1143 RefNum_Del = concBuf->ref_num;
1144 }
1145 /*else if (*/
1146 else if (dFLAG EQ TRUE)
1147 {
1148 TRACE_EVENT("BUFFER FULL");
1149 }
1150 else
1151 {
1152 RefNum_Del = 0xFF;
1153 }
1154 /* no conatenation handler needed */
1155 return CONC_NOT_NEEDED;
1156 }
1157
1158
1159 /* save the concatenation list */
1160 concShrdPrm.specPrm.concCMGD.currConcBufListElem = concBuf->list;
1161
1162 concShrdPrm.specPrm.concCMGD.ref_num = concBuf->ref_num;
1163
1164 concShrdPrm.specPrm.concCMGD.address = concBuf->address;
1165
1166 concShrdPrm.srcId = srcId;
1167
1168 concShrdPrm.specPrm.concCMGD.error_count = 0;
1169
1170 return CONC_NEEDED;
1171 }
1172
1173
1174 /*
1175 +--------------------------------------------------------------------+
1176 | PROJECT : MODULE : CONC_SMS |
1177 | STATE : code ROUTINE : concSMS_initSend |
1178 +--------------------------------------------------------------------+
1179
1180 PURPOSE : This function initialises shared parameter for CMGS.
1181
1182 */
1183 GLOBAL T_CONC_INIT_RETURN concSMS_initSend (
1184 T_ACI_SM_DATA* tar_data,
1185 T_ACI_UDH_DATA* udh,
1186 T_ACI_CMD_SRC srcId,
1187 CHAR* da,
1188 T_ACI_TOA* toda,
1189 T_SM_DATA_EXT* src_data,
1190 CHAR* sca,
1191 T_ACI_TOA* tosca,
1192 SHORT isReply,
1193 UBYTE alphabet )
1194 {
1195 UBYTE ret;
1196 T_CONC_CMGS *prm = &concShrdPrm.specPrm.concCMGS;
1197
1198 TRACE_FUNCTION ("concSMS_initSend ()");
1199
1200
1201 ret = concSMS_split ( tar_data, src_data, alphabet, CMGS_CONC );
1202
1203 if ( ret EQ FALSE )
1204 return CONC_NOT_NEEDED;
1205
1206 concShrdPrm.srcId = srcId;
1207
1208 if (da)
1209 {
1210 memcpy(prm->da, da, strlen(da));
1211 prm->da[strlen(da)] = '\0';
1212 prm->p_da = prm->da;
1213 }
1214 else
1215 {
1216 prm->p_da = NULL;
1217 }
1218 if (toda)
1219 {
1220 memcpy(&prm->toda, toda, sizeof(T_ACI_TOA));
1221 prm->p_toda = &prm->toda;
1222 }
1223 else
1224 {
1225 prm->p_toda = NULL;
1226 }
1227
1228 prm->data.len = src_data->len;
1229 prm->data.data = src_data->data;
1230
1231 if (sca)
1232 {
1233 memcpy(prm->sca, sca, strlen(sca));
1234 prm->sca[strlen(sca)] = '\0';
1235 prm->p_sca = prm->sca;
1236 }
1237 else
1238 {
1239 prm->p_sca = NULL;
1240 }
1241 if (tosca)
1242 {
1243 memcpy(&prm->tosca, tosca, sizeof(T_ACI_TOA));
1244 prm->p_tosca = &prm->tosca;
1245 }
1246 else
1247 {
1248 prm->p_tosca = NULL;
1249 }
1250
1251 prm->isReply = isReply;
1252 prm->sent_bytes = 0;
1253
1254 concShrdPrm.sentSegs = 0;
1255
1256 /* fill user data header structure */
1257 concSMS_fillUDH ( udh,
1258 concShrdPrm.udh.ref_num,
1259 concShrdPrm.udh.max_num,
1260 concShrdPrm.udh.seq_num );
1261
1262 return CONC_NEEDED;
1263 }
1264
1265
1266 /*
1267 +--------------------------------------------------------------------+
1268 | PROJECT : MODULE : CONC_SMS |
1269 | STATE : code ROUTINE : concSMS_initStoreInMem |
1270 +--------------------------------------------------------------------+
1271
1272 PURPOSE : This function initialises shared parameter for CMGW.
1273
1274 */
1275 GLOBAL T_CONC_INIT_RETURN concSMS_initStoreInMem ( T_ACI_SM_DATA* tar_data,
1276 T_ACI_UDH_DATA* udh,
1277 T_ACI_CMD_SRC srcId,
1278 SHORT index,
1279 CHAR* address,
1280 T_ACI_TOA* toa,
1281 T_ACI_SMS_STAT stat,
1282 UBYTE msg_ref,
1283 T_SM_DATA_EXT* src_data,
1284 CHAR* sca,
1285 T_ACI_TOA* tosca,
1286 SHORT isReply,
1287 UBYTE alphabet )
1288 {
1289 T_CONC_INIT_RETURN ret;
1290 T_CONC_CMGW *prm = &concShrdPrm.specPrm.concCMGW;
1291
1292 TRACE_FUNCTION ("concSMS_initStoreInMem ()");
1293
1294
1295 ret = (T_CONC_INIT_RETURN)concSMS_split ( tar_data, src_data, alphabet, CMGW_CONC );
1296
1297 if ( ret EQ FALSE )
1298 {
1299 return CONC_NOT_NEEDED;
1300 }
1301
1302 concShrdPrm.srcId = srcId;
1303
1304 if (address)
1305 {
1306 memcpy(prm->da, address, strlen(address));
1307 prm->da[strlen(address)] = '\0';
1308 prm->p_da = prm->da;
1309 }
1310 else
1311 {
1312 prm->p_da = NULL;
1313 }
1314 if (toa)
1315 {
1316 memcpy(&prm->toda, toa, sizeof(T_ACI_TOA));
1317 prm->p_toda = &prm->toda;
1318 }
1319 else
1320 {
1321 prm->p_toda = NULL;
1322 }
1323
1324 if ( stat NEQ SMS_STAT_NotPresent)
1325 {
1326 prm->stat = stat;
1327 }
1328 else
1329 {
1330 prm->stat = SMS_STAT_StoUnsent;
1331 }
1332
1333 prm->msg_ref = msg_ref;
1334 prm->data.len = src_data->len;
1335 prm->data.data = src_data->data;
1336
1337 if (sca)
1338 {
1339 memcpy(prm->sca, sca, strlen(sca));
1340 prm->sca[strlen(sca)] = '\0';
1341 prm->p_sca = prm->sca;
1342 }
1343 else
1344 {
1345 prm->p_sca = NULL;
1346 }
1347 if (tosca)
1348 {
1349 memcpy(&prm->tosca, tosca, sizeof(T_ACI_TOA));
1350 prm->p_tosca = &prm->tosca;
1351 }
1352 else
1353 {
1354 prm->p_tosca = NULL;
1355 }
1356
1357 prm->isReply = isReply;
1358
1359 /* fill user data header structure */
1360 concSMS_fillUDH ( udh,
1361 concShrdPrm.udh.ref_num,
1362 concShrdPrm.udh.max_num,
1363 concShrdPrm.udh.seq_num );
1364
1365 return CONC_NEEDED;
1366 }
1367
1368
1369 /*
1370 +--------------------------------------------------------------------+
1371 | PROJECT : MODULE : CONC_SMS |
1372 | STATE : code ROUTINE : concSMS_initCommand |
1373 +--------------------------------------------------------------------+
1374
1375 PURPOSE : This function initialises shared parameter for CMGC.
1376
1377 */
1378 GLOBAL T_CONC_INIT_RETURN concSMS_initCommand ( T_ACI_CMD_SRC srcId,
1379 SHORT fo,
1380 SHORT ct,
1381 SHORT pid,
1382 SHORT mn,
1383 CHAR* da,
1384 T_ACI_TOA* toda,
1385 T_ACI_CMD_DATA* data )
1386 {
1387 T_CONC_CMGC *prm = &concShrdPrm.specPrm.concCMGC;
1388
1389 TRACE_FUNCTION ("concSMS_initCommand ()");
1390
1391
1392 if ( ct NEQ COMMAND_TYPE_DELETE)
1393 return CONC_NOT_NEEDED;
1394
1395 if ((mn < concShrdPrm.first_mr) OR
1396 (mn > concShrdPrm.first_mr + concShrdPrm.sentSegs-1))
1397 return CONC_NOT_NEEDED;
1398
1399
1400 if ( mn NEQ concShrdPrm.first_mr)
1401 {
1402 /* Error: segment is not the first segment of the SM */
1403 return CONC_ERROR;
1404 }
1405 else
1406 {
1407 concShrdPrm.srcId = srcId;
1408
1409 prm->command_count = 0;
1410 prm->fo = (UBYTE)fo;
1411 prm->ct = (UBYTE)ct;
1412 prm->pid = (UBYTE)pid;
1413
1414 if (da)
1415 {
1416 memcpy(prm->da, da, strlen(da));
1417 prm->da[strlen(da)] = '\0';
1418 prm->p_da = prm->da;
1419 }
1420 else
1421 {
1422 prm->p_da = NULL;
1423 }
1424
1425 if (toda)
1426 {
1427 memcpy(&prm->toda, toda, sizeof(T_ACI_TOA));
1428 prm->p_toda = &prm->toda;
1429 }
1430 else
1431 {
1432 prm->p_toda = NULL;
1433 }
1434
1435 ACI_MALLOC(prm->data.data, MAX_SM_CMD_LEN);
1436 memcpy ( prm->data.data, data->data, data->len );
1437 prm->data.len = data->len;
1438
1439 }
1440 return CONC_NEEDED;
1441 }
1442
1443
1444
1445
1446 /********************** RAT Callback Fucntions ****************************/
1447
1448
1449 GLOBAL void rConcSMS_PlusCMSS (UBYTE mr, UBYTE numSeg)
1450 {
1451 UBYTE index;
1452 T_CONC_BUF_ELEM* elem;
1453 T_CONC_CMSS *prm = &concShrdPrm.specPrm.concCMSS;
1454
1455 TRACE_FUNCTION ("rConcSMS_PlusCMSS()");
1456
1457
1458 /* save the first message reference */
1459 if (concShrdPrm.sentSegs EQ 0)
1460 {
1461 concShrdPrm.first_mr = mr;
1462 }
1463
1464 /* increment number of successfully sent elements */
1465 concShrdPrm.sentSegs++;
1466
1467 /* get next concat. list element */
1468 prm->currConcBufListElem = prm->currConcBufListElem->next;
1469
1470 if (prm->skipStoSent)
1471 {
1472 /* skip segments with status SMS_STAT_StoSent */
1473 while (prm->currConcBufListElem)
1474 {
1475 elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg;
1476
1477 if (elem->status EQ SMS_STAT_StoSent)
1478 {
1479 prm->currConcBufListElem = prm->currConcBufListElem->next;
1480 }
1481 else
1482 {
1483 break;
1484 }
1485 } /* while */
1486 }
1487
1488 if (prm->currConcBufListElem NEQ NULL)
1489 {
1490 elem = (T_CONC_BUF_ELEM*)prm->currConcBufListElem->msg;
1491 index = elem->rec_num;
1492
1493 /* set mem2 (memory to which writing and sending operations are made)
1494 temporary to the value stored in conc buffer */
1495 smsShrdPrm.mem2 = elem->mem;
1496
1497 sAT_PlusCMSS_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, index, prm->p_da, prm->p_toda,
1498 rConcSMS_PlusCMSS, rConcSMS_PlusCMS_CMSS);
1499
1500
1501 elem->status = SMS_STAT_StoSent;
1502
1503
1504 }
1505 else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */
1506 {
1507
1508 #ifdef _CONC_TESTING_
1509 char *sa;
1510 ACI_MALLOC(sa,KEY + BYTE_LTH);
1511 sprintf(sa,"+CMSS: %d,%d",concShrdPrm.first_mr, concShrdPrm.sentSegs);
1512 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1513 ACI_MFREE(sa);
1514 #endif
1515
1516 rAT_PlusCMSS(concShrdPrm.first_mr, (UBYTE)(concShrdPrm.sentSegs));
1517
1518 /* restore value for mem2 */
1519 smsShrdPrm.mem2 = concShrdPrm.mem_store;
1520
1521 R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMSS );
1522 UNSET_CONC;
1523 }
1524 }
1525
1526 GLOBAL void rConcSMS_PlusCMGS (UBYTE mr, UBYTE numSeg)
1527 {
1528 T_ACI_SM_DATA data;
1529 T_ACI_UDH_DATA udh;
1530 USHORT len_left;
1531 T_CONC_CMGS *prm = &concShrdPrm.specPrm.concCMGS;
1532
1533 TRACE_FUNCTION ("rConcSMS_PlusCMGS()");
1534
1535
1536 /* save the first message reference */
1537 if (concShrdPrm.udh.seq_num EQ 1)
1538 {
1539 concShrdPrm.first_mr = mr;
1540 }
1541
1542 /* increment number of successfully sent elements */
1543 len_left = prm->data.len - prm->offset;
1544
1545 concShrdPrm.sentSegs++;
1546
1547 if (len_left NEQ 0)
1548 {
1549 prm->sent_bytes += concShrdPrm.max_sms_len;
1550
1551 if ( len_left > concShrdPrm.max_sms_len )
1552 {
1553 data.len = concShrdPrm.max_sms_len;
1554 }
1555 else
1556 {
1557 data.len = (UBYTE)len_left;
1558 }
1559
1560 memcpy (data.data, prm->data.data+prm->offset, data.len);
1561 prm->offset += data.len;
1562
1563 concShrdPrm.udh.seq_num++;
1564
1565
1566 /* fill user data header structure */
1567 concSMS_fillUDH ( &udh,
1568 concShrdPrm.udh.ref_num,
1569 concShrdPrm.udh.max_num,
1570 concShrdPrm.udh.seq_num );
1571
1572 sAT_PlusCMGS_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, prm->p_da, prm->p_toda,
1573 &data, &udh, prm->p_sca, prm->p_tosca,
1574 prm->isReply, rConcSMS_PlusCMGS, rConcSMS_PlusCMS_CMGS);
1575
1576
1577 }
1578 else
1579 {
1580
1581 #ifdef _CONC_TESTING_
1582 char *sa;
1583 ACI_MALLOC(sa,KEY + BYTE_LTH);
1584 sprintf(sa,"+CMGS: %d,%d",concShrdPrm.first_mr, concShrdPrm.udh.seq_num);
1585 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1586 ACI_MFREE(sa);
1587
1588 ACI_MFREE(prm->data.data);
1589
1590 #endif
1591
1592 rAT_PlusCMGS (concShrdPrm.first_mr, (UBYTE)(concShrdPrm.udh.seq_num));
1593 R_AT ( RAT_OK, (T_ACI_CMD_SRC)concShrdPrm.srcId ) ( AT_CMD_CMGS );
1594 UNSET_CONC;
1595 }
1596 }
1597
1598
1599
1600 GLOBAL void rConcSMS_PlusCMGR ( T_ACI_CMGL_SM* sm,
1601 T_ACI_CMGR_CBM* cbm )
1602 {
1603 T_CONC_CMGR *prm = &concShrdPrm.specPrm.concCMGR;
1604
1605 TRACE_FUNCTION ("rConcSMS_PlusCMGR ()");
1606
1607 if (prm->currConcBufListElem NEQ NULL)
1608 {
1609 T_CONC_BUF_ELEM *elem;
1610 elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg;
1611
1612 /* set mem1 (memory from which messages are read and deleted)
1613 * temporary to the value stored in conc buffer */
1614 smsShrdPrm.mem1 = elem->mem;
1615
1616 sAT_PlusCMGR_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num,
1617 (T_ACI_SMS_READ)concShrdPrm.specPrm.concCMGR.rdMode,
1618 rConcSMS_PlusCMGR);
1619
1620 prm->currConcBufListElem = prm->currConcBufListElem->next;
1621
1622 #ifdef _CONC_TESTING_
1623 rAT_PlusCMGR_Ext (sm, cbm);
1624 #else
1625 rAT_PlusCMGR (sm, cbm);
1626 #endif
1627
1628 }
1629 else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */
1630 {
1631 #ifdef _CONC_TESTING_
1632 rAT_PlusCMGR_Ext (sm, cbm);
1633 #else
1634 rAT_PlusCMGR (sm, cbm);
1635 #endif
1636
1637 /* restore value for mem1 */
1638 smsShrdPrm.mem1 = concShrdPrm.mem_store;
1639
1640
1641 R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGR );
1642 UNSET_CONC;
1643 }
1644 }
1645
1646 GLOBAL void rConcSMS_PercentCMGMDU (void)
1647 {
1648 T_CONC_CMGR *prm = &concShrdPrm.specPrm.concCMGR;
1649
1650 TRACE_FUNCTION ("rConcSMS_PercentCMGMDU ()");
1651
1652 if (prm->currConcBufListElem NEQ NULL)
1653 {
1654 T_CONC_BUF_ELEM *elem;
1655 elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg;
1656
1657 sAT_PercentCMGMDU_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num,
1658 rConcSMS_PercentCMGMDU);
1659
1660 prm->currConcBufListElem = prm->currConcBufListElem->next;
1661
1662 }
1663 else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */
1664 {
1665 if( concShrdPrm.srcId NEQ CMD_SRC_LCL )
1666 R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_P_CMGMDU );
1667 UNSET_CONC;
1668 }
1669 }
1670
1671 GLOBAL void rConcSMS_PlusCMGW ( UBYTE index, UBYTE numSeg, UBYTE mem)
1672 {
1673 T_ACI_SM_DATA data;
1674 T_ACI_UDH_DATA udh;
1675 USHORT len_left;
1676 T_CONC_CMGW *prm = &concShrdPrm.specPrm.concCMGW;
1677
1678 static UBYTE first_rec;
1679
1680 TRACE_FUNCTION ("rConcSMS_PlusCMGW ()");
1681
1682
1683 /* save the first index */
1684 if (concShrdPrm.udh.seq_num EQ 1)
1685 {
1686 first_rec = index;
1687 }
1688
1689 concSMS_addToConcatList((USHORT)concShrdPrm.udh.ref_num,
1690 prm->p_da,
1691 concShrdPrm.udh.max_num,
1692 concShrdPrm.udh.seq_num,
1693 index,
1694 (T_ACI_SMS_STAT)prm->stat,
1695 mem);
1696
1697 concSMS_printConcatList();
1698
1699 len_left = prm->data.len - prm->offset;
1700
1701 if (len_left NEQ 0)
1702 {
1703 prm->sent_bytes += concShrdPrm.max_sms_len;
1704
1705 if ( len_left > concShrdPrm.max_sms_len )
1706 {
1707 data.len = concShrdPrm.max_sms_len;
1708 }
1709 else
1710 {
1711 data.len = (UBYTE)len_left;
1712 }
1713
1714 memcpy (data.data, prm->data.data+prm->offset, data.len);
1715 prm->offset += data.len;
1716
1717 concShrdPrm.udh.seq_num++;
1718
1719 /* fill user data header structure */
1720 concSMS_fillUDH ( &udh,
1721 concShrdPrm.udh.ref_num,
1722 concShrdPrm.udh.max_num,
1723 concShrdPrm.udh.seq_num );
1724
1725 sAT_PlusCMGW_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, CMGW_IDX_FREE_ENTRY,
1726 prm->p_da, prm->p_toda, (T_ACI_SMS_STAT)prm->stat, prm->msg_ref,
1727 &data, &udh, prm->p_sca, prm->p_tosca,
1728 prm->isReply, rConcSMS_PlusCMGW, rConcSMS_PlusCMS_CMGW);
1729
1730 }
1731 else
1732 {
1733
1734 #ifdef _CONC_TESTING_
1735 char *sa;
1736 ACI_MALLOC(sa,KEY + BYTE_LTH);
1737 sprintf(sa,"+CMGW: %d,%d",first_rec, concShrdPrm.udh.seq_num);
1738 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1739 ACI_MFREE(sa);
1740 #endif
1741
1742 rAT_PlusCMGW (first_rec, concShrdPrm.udh.seq_num, mem);
1743 R_AT ( RAT_OK, (T_ACI_CMD_SRC)concShrdPrm.srcId ) ( AT_CMD_CMGW );
1744 UNSET_CONC;
1745 }
1746 }
1747
1748
1749
1750
1751
1752
1753 GLOBAL void rConcSMS_PlusCMGD ( )
1754 {
1755 T_CONC_CMGD *prm = &concShrdPrm.specPrm.concCMGD;
1756 T_CONC_BUF_ELEM *elem;
1757 T_ACI_LIST *conc_list;
1758
1759 TRACE_FUNCTION ("rConcSMS_PlusCMGD ()");
1760
1761
1762 elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg;
1763
1764 /* remove the old element from concatenation list and free its memory */
1765 conc_list = concSMS_removeFromConcatList(prm->ref_num, prm->address, elem->rec_num);
1766
1767 concSMS_printConcatList();
1768
1769 if (conc_list NEQ NULL)
1770 {
1771 TRACE_EVENT("conc_list not null");
1772 elem = (T_CONC_BUF_ELEM *)conc_list->msg;
1773
1774 /* save the concatenation list */
1775 prm->currConcBufListElem= conc_list;
1776
1777 /* set mem1 (memory from which messages are read and deleted)
1778 temporary to the value stored in conc buffer */
1779 smsShrdPrm.mem1 = elem->mem;
1780
1781 sAT_PlusCMGD_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num, smsShrdPrm.status,
1782 rConcSMS_PlusCMGD, rConcSMS_PlusCMS_CMGD);
1783
1784 }
1785 else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */
1786 {
1787 if (concShrdPrm.full.Conc_Full EQ TRUE)
1788 {
1789 concSMS_AddtoconcBuff();
1790 concShrdPrm.full.Conc_Full = FALSE;
1791 }
1792
1793 /* restore value for mem1 */
1794 smsShrdPrm.mem1 = concShrdPrm.mem_store;
1795
1796 TRACE_EVENT("RAT_OK in rConcSMS_PlusCMGD");
1797 R_AT ( RAT_OK, (T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGD );
1798 UNSET_CONC;
1799 }
1800 }
1801
1802
1803 GLOBAL void rConcSMS_PlusCMGC ( UBYTE mr )
1804 {
1805 UBYTE mn;
1806 T_CONC_CMGC *prm = &concShrdPrm.specPrm.concCMGC;
1807
1808 TRACE_FUNCTION ("rConcSMS_PlusCMGC ()");
1809
1810 /* save the first message reference */
1811 if (concShrdPrm.udh.seq_num EQ 1)
1812 {
1813 concShrdPrm.first_mr = mr;
1814 }
1815
1816 prm->command_count++;
1817
1818 if (prm->command_count < concShrdPrm.sentSegs)
1819 {
1820 mn = concShrdPrm.first_mr + prm->command_count;
1821
1822 sAT_PlusCMGC_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, prm->fo, prm->ct,
1823 prm->pid, mn, prm->p_da, prm->p_toda,
1824 (T_ACI_CMD_DATA*)&prm->data, rConcSMS_PlusCMGC);
1825 }
1826 else
1827 {
1828
1829 #ifdef _CONC_TESTING_
1830 char *sa;
1831 ACI_MALLOC(sa,KEY + BYTE_LTH);
1832 sprintf(sa,"+CMGC: %d",concShrdPrm.first_mr /*, prm->command_count*/);
1833 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1834 ACI_MFREE(sa);
1835 #endif
1836
1837 ACI_MFREE( prm->data.data );
1838 rAT_PlusCMGC (concShrdPrm.first_mr/*, prm->command_count*/);
1839 R_AT ( RAT_OK,(T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGC );
1840 UNSET_CONC;
1841 }
1842 }
1843
1844
1845 GLOBAL void rConcSMS_PlusCMS_CMSS (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err,
1846 T_EXT_CMS_ERROR *ce)
1847 {
1848 T_EXT_CMS_ERROR conc_error;
1849 #ifdef _CONC_TESTING_
1850 char *sa;
1851 #endif
1852
1853 TRACE_FUNCTION ("rConcSMS_PlusCMS_CMSS ()");
1854
1855
1856 conc_error.id = CMSS_CONC;
1857 conc_error.specErr.errConcCMSS.segs =
1858 concShrdPrm.udh.max_num - concShrdPrm.sentSegs;
1859
1860 #ifdef _CONC_TESTING_
1861 ACI_MALLOC(sa,KEY + BYTE_LTH);
1862 sprintf(sa,"+CMS ERROR: %d,%d",err, conc_error.specErr.errConcCMSS.segs);
1863 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1864 ACI_MFREE(sa);
1865 rCI_PlusCMS ( cmdId, err, NULL );
1866 #endif
1867
1868 /* restore value for mem2 */
1869 smsShrdPrm.mem2 = concShrdPrm.mem_store;
1870
1871 rAT_PlusCMS (cmdId, err, &conc_error);
1872 UNSET_CONC;
1873 }
1874
1875
1876 GLOBAL void rConcSMS_PlusCMS_CMGS (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err,
1877 T_EXT_CMS_ERROR *ce)
1878 {
1879 T_EXT_CMS_ERROR conc_error;
1880 #ifdef _CONC_TESTING_
1881 char *sa;
1882 #endif
1883
1884 TRACE_FUNCTION ("rConcSMS_PlusCMS_CMGS ()");
1885
1886
1887 conc_error.id = CMGS_CONC;
1888 conc_error.specErr.errConcCMGS.sent_chars =
1889 concShrdPrm.specPrm.concCMGS.sent_bytes;
1890 conc_error.specErr.errConcCMGS.ref_num = concShrdPrm.udh.ref_num;
1891 conc_error.specErr.errConcCMGS.next_seg = concShrdPrm.udh.seq_num;
1892 conc_error.specErr.errConcCMGS.max_num = concShrdPrm.udh.max_num;
1893
1894 #ifdef _CONC_TESTING_
1895 ACI_MALLOC(sa,KEY + BYTE_LTH);
1896 sprintf(sa,"+CMS ERROR: %d,%d,%d,%d,%d",err,
1897 conc_error.specErr.errConcCMGS.sent_chars,
1898 conc_error.specErr.errConcCMGS.ref_num,
1899 conc_error.specErr.errConcCMGS.next_seg,
1900 conc_error.specErr.errConcCMGS.max_num);
1901
1902 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1903 ACI_MFREE(sa);
1904 rCI_PlusCMS ( cmdId, err, NULL );
1905 #endif
1906
1907 rAT_PlusCMS (cmdId, err, &conc_error);
1908 UNSET_CONC;
1909 }
1910
1911
1912 GLOBAL void rConcSMS_PlusCMS_CMGW (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err,
1913 T_EXT_CMS_ERROR *ce)
1914 {
1915 T_EXT_CMS_ERROR conc_error;
1916 #ifdef _CONC_TESTING_
1917 char *sa;
1918 #endif
1919
1920 TRACE_FUNCTION ("rConcSMS_PlusCMS_CMGW ()");
1921
1922
1923 conc_error.id = CMGW_CONC;
1924 conc_error.specErr.errConcCMGW.sent_chars =
1925 concShrdPrm.specPrm.concCMGW.sent_bytes;
1926 conc_error.specErr.errConcCMGW.ref_num = concShrdPrm.udh.ref_num;
1927 conc_error.specErr.errConcCMGW.next_seg = concShrdPrm.udh.seq_num;
1928 conc_error.specErr.errConcCMGW.max_num = concShrdPrm.udh.max_num;
1929
1930 #ifdef _CONC_TESTING_
1931 ACI_MALLOC(sa,KEY + BYTE_LTH);
1932 sprintf(sa,"+CMS ERROR: %d,%d,%d,%d,%d",err,
1933 conc_error.specErr.errConcCMGW.sent_chars,
1934 conc_error.specErr.errConcCMGW.ref_num,
1935 conc_error.specErr.errConcCMGW.next_seg,
1936 conc_error.specErr.errConcCMGW.max_num);
1937 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1938 ACI_MFREE(sa);
1939 rCI_PlusCMS ( cmdId, err, NULL );
1940 #endif
1941
1942 rAT_PlusCMS (cmdId, err, &conc_error);
1943 UNSET_CONC;
1944 }
1945
1946 GLOBAL void rConcSMS_PlusCMS_CMGD (T_ACI_AT_CMD cmdId, T_ACI_CMS_ERR err,
1947 T_EXT_CMS_ERROR *ce)
1948 {
1949 T_CONC_CMGD *prm = &concShrdPrm.specPrm.concCMGD;
1950 T_CONC_BUF_ELEM *elem;
1951 T_EXT_CMS_ERROR conc_error;
1952
1953 TRACE_FUNCTION ("rConcSMS_PlusCMS_CMGD ()");
1954
1955 conc_error.id = EMPTY;
1956
1957 prm->error_count++;
1958 if (prm->error_count EQ concShrdPrm.udh.max_num)
1959 {
1960
1961 #ifdef _CONC_TESTING_
1962 char *sa;
1963 ACI_MALLOC(sa,KEY + BYTE_LTH);
1964 sprintf(sa,"+CMS ERROR: %d",err);
1965 io_sendMessage(concShrdPrm.srcId, sa, ATI_NORMAL_OUTPUT);
1966 ACI_MFREE(sa);
1967 rCI_PlusCMS ( cmdId, err, NULL );
1968 #endif
1969
1970 elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg;
1971 /* remove the old element from concatenation list and free its memory */
1972 concSMS_removeFromConcatList(prm->ref_num, prm->address, elem->rec_num);
1973 concSMS_printConcatList();
1974
1975 /* restore value for mem1 */
1976 smsShrdPrm.mem1 = concShrdPrm.mem_store;
1977
1978 rAT_PlusCMS ( cmdId, err, &conc_error);
1979 UNSET_CONC;
1980 }
1981 else
1982 {
1983 /* continue with the next segment */
1984 rConcSMS_PlusCMGD();
1985 }
1986 }
1987 #endif /* TI_PS_FF_CONC_SMS */
1988
1989
1990
1991
1992 /*************** Functions which must be called by MFW ***************/
1993
1994
1995
1996
1997
1998
1999 /*
2000 +--------------------------------------------------------------------+
2001 | PROJECT : MODULE : CONC_SMS |
2002 | STATE : code ROUTINE : SMS_getSMSType |
2003 +--------------------------------------------------------------------+
2004
2005 PURPOSE : This function must be called by the MFW to detect the SMS
2006 type from the information element identifier.
2007
2008 */
2009 GLOBAL T_SMS_TYPE SMS_getSMSType( T_ACI_UDH_DATA* udh, char *address, UBYTE detMode)
2010 {
2011 USHORT ref_num = 0;
2012 UBYTE seq_num = 0;
2013 UBYTE max_num = 0;
2014 USHORT count;
2015 T_CONC_BUF* concBuf;
2016
2017 TRACE_FUNCTION ("SMS_getSMSType()");
2018 TRACE_EVENT_P1("SMS_getSMSType, mode: %d", detMode);
2019
2020
2021 if (udh->len EQ 0)
2022 {
2023 /* SMS does not contain UDH --> normal SMS */
2024 return NORMAL;
2025 }
2026
2027 /* check if IE is conc SMS */
2028 if ((udh->data[0] EQ SMS_IEI_CONC_8BIT) OR (udh->data[0] EQ SMS_IEI_CONC_16BIT))
2029 {
2030 if (udh->data[0] EQ SMS_IEI_CONC_8BIT)
2031 {
2032 ref_num = udh->data[2];
2033 max_num = udh->data[3];
2034 seq_num = udh->data[4];
2035 }
2036
2037 if (udh->data[0] EQ SMS_IEI_CONC_16BIT)
2038 {
2039 ref_num = (udh->data[2] & 0x00FF) << 8u;
2040 ref_num += udh->data[3];
2041 max_num = udh->data[4];
2042 seq_num = udh->data[5];
2043 }
2044
2045 switch (detMode)
2046 {
2047
2048 case MODE1:
2049 /* This mode is for rAT_PlusCMT. No Concatenation buffer is needed at all */
2050 break;
2051
2052 case MODE2:
2053 /* This mode is for rAT_PlusCMTI. This mode requires the allocation of a new
2054 * Concatenation buffer (later in concSMS_Collect). Make sure that in case
2055 * the conc buffer is full no new CSMS is handled anymore
2056 */
2057 concBuf = concSMS_getConcBuffer( ref_num, address );
2058
2059 /* if a new conc buffer is be needed, check if available */
2060 if (concBuf EQ NULL)
2061 {
2062 if (concSMS_concBufferAvail() EQ FALSE)
2063 {
2064 return NORMAL_IND_CSMS;
2065 }
2066
2067 /* Limit the maximum number of CSMS segments to MAX_SEG_TOTAL. Check
2068 * only if a new Concatenation buffer is required.
2069 */
2070 if (concShrdPrm.elem_count+max_num > MAX_SEG_TOTAL)
2071 {
2072 return NORMAL_IND_CSMS;
2073 }
2074 }
2075 break;
2076
2077 case MODE3:
2078 /* This mode is for rAT_PlusCMGL, rAT_PlusCMGR, sms_store_new_msg_info and
2079 * sms_store_new_msg_info. Only segments that have been previously stored
2080 * in the Concatenation buffer can be handled as CSMS.
2081 */
2082 concBuf = concSMS_getConcBuffer( ref_num, address );
2083 if (concBuf EQ NULL)
2084 {
2085 return NORMAL_IND_CSMS;
2086 }
2087
2088 /* check if conc buffer is incomplete */
2089 count = get_list_count(concBuf->list);
2090 if ((count < concBuf->max_num) AND (count < CONC_MAX_SEGS))
2091 {
2092 return NORMAL_IND_CSMS;
2093 }
2094 break;
2095
2096 default:
2097 TRACE_ERROR("Wrong detection mode in SMS_getSMSType");
2098 return UNKNOWN;
2099 }
2100
2101 /* check if sequence number is in range */
2102 if (seq_num <= CONC_MAX_SEGS)
2103 {
2104 return CONCATE;
2105 }
2106 else
2107 {
2108 return NORMAL_IND_CSMS;
2109 }
2110 }
2111 else
2112 {
2113 /* unknown IE in UDH --> no CSMS */
2114 return UNKNOWN;
2115 }
2116 }
2117
2118 /*
2119 +--------------------------------------------------------------------+
2120 | PROJECT : MODULE : CONC_SMS |
2121 | STATE : code ROUTINE : concSMS_GetFirstIndex |
2122 +--------------------------------------------------------------------+
2123
2124 PURPOSE : This function provides MFW with the first index of a given
2125 concatenated SMS (identified by its message reference).
2126
2127 returns first index: (0 means no message found...)
2128 */
2129 #define FIRST_SEQ_NUM (1)
2130
2131 GLOBAL T_CONC_BUF_ELEM *concSMS_GetFirstIndex_ext ( USHORT msg_ref, char *address )
2132 {
2133
2134
2135 T_CONC_BUF *concBuf;
2136 T_CONC_BUF_ELEM *concBufElem;
2137
2138 TRACE_FUNCTION ("concSMS_GetFirstIndex()");
2139
2140 /* search for concatenation buffer */
2141 concBuf = concSMS_getConcBuffer( msg_ref, address );
2142
2143 if( concBuf EQ NULL )
2144 {
2145 TRACE_EVENT_P1("ERROR: unknown msg_ref: 0x%04x", msg_ref);
2146 return( NULL );
2147 }
2148
2149 /* search for the first sequence */
2150 concBufElem = find_element(concBuf->list, FIRST_SEQ_NUM, concSMS_findSeqNumElemCB);
2151
2152 if( concBufElem EQ NULL )
2153 {
2154 TRACE_EVENT("ERROR: first sequence not found");
2155 return( NULL );
2156 }
2157
2158 TRACE_EVENT_P1("first rec_num: %d", concBufElem->rec_num);
2159 TRACE_EVENT_P1 ("concSMS_GetFirstIndex_ext(), rec_num=%d", concBufElem->rec_num);
2160
2161 /* return index of first segment */
2162 return(concBufElem);
2163
2164 }
2165
2166 GLOBAL UBYTE concSMS_GetFirstIndex ( USHORT msg_ref, char *address )
2167 {
2168 T_CONC_BUF_ELEM *concBufElem = concSMS_GetFirstIndex_ext(msg_ref, address);
2169
2170 if( concBufElem EQ NULL )
2171 {
2172 TRACE_EVENT("ERROR: first sequence not found");
2173 return(0);
2174 }
2175 else
2176 return(concBufElem->rec_num);
2177
2178 }
2179
2180
2181 /*
2182 +--------------------------------------------------------------------+
2183 | PROJECT : MODULE : CONC_SMS |
2184 | STATE : code ROUTINE : concSMS_GetMsgRef |
2185 +--------------------------------------------------------------------+
2186
2187 PURPOSE : This function provides MFW with the message reference of a given
2188 concatenated SMS (decoded from the header).
2189
2190 returns msg ref.
2191 */
2192
2193 GLOBAL USHORT concSMS_GetMsgRef ( T_ACI_CMGL_SM *sm )
2194 {
2195 USHORT ref_num;
2196
2197 TRACE_FUNCTION ("concSMS_GetMsgRef()");
2198
2199 if( sm EQ NULL )
2200 {
2201 TRACE_ERROR("sm is NULL");
2202 return 0;
2203 }
2204
2205 /* 8-bit reference number */
2206 if (sm->udh.data[0] EQ SMS_IEI_CONC_8BIT)
2207 {
2208 ref_num = sm->udh.data[2];
2209 }
2210
2211 /* 16-bit reference number */
2212 else if (sm->udh.data[0] EQ SMS_IEI_CONC_16BIT)
2213 {
2214 /* MSB */
2215 ref_num = (sm->udh.data[2] & 0x00FF) << 8u; /* 23.040 9.1.2.1 */
2216
2217 /* LSB */
2218 ref_num |= sm->udh.data[3];
2219 }
2220 else
2221 {
2222 TRACE_ERROR("sm->udh.data unknown");
2223 return 0;
2224 }
2225
2226 TRACE_EVENT_P1("ref_num: 0x%04x", ref_num);
2227
2228 return(ref_num);
2229 }
2230
2231 /*
2232 +--------------------------------------------------------------------+
2233 | PROJECT : MODULE : CONC_SMS |
2234 | STATE : code ROUTINE : concSMS_Collect |
2235 +--------------------------------------------------------------------+
2236
2237 PURPOSE : This function must be called by the MFW. The function
2238 reassembles the received SM segments.
2239
2240 Set 'isStored' to:
2241 TRUE, if rAT_PlusCMTI() was called
2242 FALSE, if rAT_PlusCMT() was called
2243 FALSE, if rAT_PlusCMGR() was called
2244
2245 */
2246 GLOBAL T_CONC_ASSEMBLY_RETURN concSMS_Collect ( T_SM_DATA_EXT *data_conc,
2247 T_ACI_CMGL_SM *sm,
2248 UBYTE isStored,
2249 T_ACI_SMS_STOR mem_aci)
2250 {
2251 USHORT ref_num = 0;
2252 UBYTE max_num = 0;
2253 UBYTE seq_num = 0;
2254 UBYTE rec_num;
2255 T_SM_ASSEMBLY *assembly_elem;
2256 T_SEG_BUF_ELEM *segBufElem;
2257 T_SM_DATA_EXT data;
2258 T_ACI_SMS_STAT status;
2259 UBYTE next_exp_num;
2260 UBYTE ret;
2261 static UBYTE i = 0;
2262 UBYTE mem_psa;
2263
2264
2265
2266 CHAR *address;
2267
2268 TRACE_FUNCTION ("concSMS_Collect()");
2269
2270 /* initialize data_conc->len */
2271 data_conc->len = 0; /* ACI-SPR-16372 */
2272 /* extract parameters from user data header */
2273
2274 /* 8-bit reference number */
2275 if (sm->udh.data[0] EQ SMS_IEI_CONC_8BIT)
2276 {
2277 ref_num = sm->udh.data[2];
2278 max_num = sm->udh.data[3];
2279 seq_num = sm->udh.data[4];
2280 }
2281
2282 /* 16-bit reference number */
2283 else if (sm->udh.data[0] EQ SMS_IEI_CONC_16BIT)
2284 {
2285 /* MSB */
2286 ref_num = (sm->udh.data[2] & 0x00FF) << 8u; /* 23.040 9.1.2.1 */
2287
2288 /* LSB */
2289 ref_num += sm->udh.data[3];
2290
2291 max_num = sm->udh.data[4];
2292 seq_num = sm->udh.data[5];
2293 }
2294
2295 rec_num = sm->msg_ref;
2296 status = sm->stat;
2297 address = sm->adress;
2298
2299 data.data = sm->data.data;
2300 data.len = sm->data.len;
2301
2302 TRACE_EVENT_P1("rec_num:%d", rec_num);
2303 TRACE_EVENT_P1("concSMS_GetFirstIndex():%d",
2304 concSMS_GetFirstIndex (ref_num, sm->adress));
2305 TRACE_EVENT_P1("ref_num:0x%04x", ref_num);
2306 TRACE_EVENT_P1("concSMS_GetMsgRef():0x%04x", concSMS_GetMsgRef ( sm ));
2307 TRACE_EVENT_P1("max_num:%d", max_num);
2308 TRACE_EVENT_P1("seq_num:%d", seq_num);
2309
2310 /* try to get an existing assembly buffer */
2311 assembly_elem = concSMS_getAsBuffer(ref_num, address);
2312
2313 /* if no assembly buffer found, then assume that is a new conc. SM */
2314 if (assembly_elem EQ NULL)
2315 {
2316 next_exp_num = 1;
2317 }
2318 else
2319 {
2320 next_exp_num = assembly_elem->next_exp_num;
2321 }
2322
2323
2324 /* the received seq_num is not valid */
2325 if ( (seq_num EQ 0) OR (seq_num > max_num) OR (seq_num < next_exp_num) )
2326 {
2327 return CONC_ERR_UNKN;
2328 }
2329
2330
2331
2332 /*
2333 * If CMTI, then add every received segment to concatenation buffer.
2334 * The segments in the concatenation buffer were also stored in non-volatile
2335 * memory.
2336 */
2337 if (isStored)
2338 {
2339 if (cmhSMS_getMemPsa(mem_aci, &mem_psa) EQ FALSE)
2340 {
2341 return CONC_ERR_UNKN;
2342 }
2343
2344 ret = concSMS_addToConcatList(ref_num, address, max_num,
2345 seq_num, rec_num, status, mem_psa);
2346
2347 if (ret EQ FALSE)
2348 {
2349 dFLAG = TRUE;
2350 RefNum_Del = ref_num;
2351 concShrdPrm.full.Conc_Full = TRUE;
2352 concShrdPrm.full.RefNum = ref_num;
2353 memcpy(Addres,address,sizeof(Addres));
2354 concShrdPrm.full.MaxNum = max_num;
2355 concShrdPrm.full.SeqNum[i] = seq_num;
2356 concShrdPrm.full.RecNum[i] = rec_num;
2357 concShrdPrm.full.MemType[i] = mem_psa;
2358 i++;
2359 concShrdPrm.full.Numsegs = i;
2360 /* error: concatenation buffer full */
2361 return CONC_ERR_BUF_FULL;
2362 }
2363 }
2364 i = 0;
2365 if ( seq_num > next_exp_num )
2366 {
2367 /*
2368 * the received segment is not in sequence
2369 * -> add it to the segment buffer
2370 */
2371 ret = concSMS_addToSegBuffer(ref_num, address, seq_num,
2372 rec_num, status, &data);
2373 if (ret EQ FALSE)
2374 {
2375 /* error: segment buffer full */
2376 return CONC_ERR_BUF_FULL;
2377 }
2378 return CONC_CONTINUED;
2379 }
2380 else
2381 {
2382 /*
2383 * the received segment is in sequence
2384 */
2385
2386 while (1)
2387 {
2388
2389 /* add segment to assembly buffer */
2390 assembly_elem = concSMS_addToAsBuffer (ref_num, address, max_num, &data);
2391
2392
2393 /* free data memory only for data from segment buffer */
2394 if (data.data NEQ sm->data.data)
2395 {
2396 ACI_MFREE (data.data);
2397 }
2398
2399 /* error: no assembly buffer available */
2400 if (assembly_elem EQ NULL)
2401 {
2402 return CONC_ERR_BUF_FULL;
2403 }
2404
2405 /* assembly of concatenated SM is completed */
2406 if (assembly_elem->next_exp_num EQ max_num+1)
2407 {
2408 concSMS_removeFromAsBuffer(data_conc, ref_num, address);
2409 concSMS_sortConcatList(ref_num, address);
2410 return CONC_COMPLETED;
2411 }
2412
2413 /* maximum reached in assembly buffer , assembly is NOT completed */
2414 if (assembly_elem->seg_count EQ CONC_MAX_SEGS)
2415 {
2416 concSMS_getFromAsBuffer(data_conc, ref_num, address);
2417 concSMS_sortConcatList(ref_num, address);
2418 return CONC_COMPLETED;
2419 }
2420
2421 /* search and remove the next segment from segment buffer */
2422 segBufElem = concSMS_removeFromSegBuffer(ref_num,
2423 address,
2424 assembly_elem->next_exp_num);
2425 if ( segBufElem EQ NULL )
2426 {
2427 /* no segment found */
2428 return CONC_CONTINUED;
2429 }
2430
2431 /* for adding to concatenation list */
2432 rec_num = segBufElem->rec_num;
2433 status = (T_ACI_SMS_STAT)segBufElem->status;
2434
2435 /* for adding to assembly buffer */
2436 data.data = segBufElem->data.data;
2437 data.len = segBufElem->data.len;
2438
2439 ACI_MFREE(segBufElem);
2440 } /* while */
2441 } /* if ( seq_num EQ next_exp_num ) */
2442 }
2443
2444
2445
2446 GLOBAL void concSMS_Init()
2447 {
2448 concShrdPrm.isConcatenated = FALSE;
2449
2450 memset (&concShrdPrm, 0, sizeof(T_CONC_SHRD_PRM) );
2451
2452 memset (&assembly_list, 0, sizeof(T_SM_ASSEMBLY)*MAX_BUF_ELEMS);
2453 memset (&segBuf_list, 0, sizeof(T_SEG_BUF) *MAX_BUF_ELEMS);
2454 memset (&concBuf_list, 0, sizeof(T_CONC_BUF) *MAX_CONC_BUF_ELEMS);
2455
2456 concShrdPrm.l_uncomp8bit_data = L_UNCOMP_8BIT_DATA;
2457 concShrdPrm.l_uncomp7bit_data = L_UNCOMP_7BIT_DATA;
2458 concShrdPrm.l_uncomp8bit_data_conc = L_UNCOMP_8BIT_DATA_CONC;
2459 concShrdPrm.l_uncomp7bit_data_conc = L_UNCOMP_7BIT_DATA_CONC;
2460 concShrdPrm.elem_count = 0;
2461 #ifdef _CONC_TESTING_
2462 #ifndef _SIMULATION_
2463 concSMS_InitForTesting();
2464 #endif
2465 #endif
2466 }
2467
2468
2469 /* only for test purposes */
2470 GLOBAL void concSMS_InitForTesting()
2471 {
2472 concShrdPrm.concTesting = TRUE;
2473 concShrdPrm.l_uncomp8bit_data = L_UNCOMP_8BIT_DATA_TST;
2474 concShrdPrm.l_uncomp7bit_data = L_UNCOMP_7BIT_DATA_TST;
2475 concShrdPrm.l_uncomp8bit_data_conc = L_UNCOMP_8BIT_DATA_CONC_TST;
2476 concShrdPrm.l_uncomp7bit_data_conc = L_UNCOMP_7BIT_DATA_CONC_TST;
2477 }
2478
2479
2480 /*
2481 +--------------------------------------------------------------------+
2482 | PROJECT : MODULE : CONC_SMS |
2483 | STATE : code ROUTINE : concSMS_delAllIncompleteMsg|
2484 +--------------------------------------------------------------------+
2485
2486 PURPOSE : This function must be called by the MFW to clean all
2487 segment buffers, assembly buffers and remove all
2488 incompleted SM from concat. buffer and non-volatile memory.
2489
2490 */
2491 GLOBAL void concSMS_delAllIncompleteMsg( )
2492 {
2493 T_SEG_BUF *segBuf = NULL;
2494 T_SEG_BUF_ELEM *segBufElem;
2495 T_CONC_BUF *concBuf = NULL;
2496 T_CONC_BUF_ELEM *concBufElem;
2497 T_SM_ASSEMBLY *assembly_elem;
2498 USHORT count;
2499
2500 UBYTE i;
2501
2502 TRACE_FUNCTION ("concSMS_delAllIncompleteMsg()");
2503
2504
2505 concShrdPrm.srcId = CMD_SRC_LCL;
2506
2507 for (i=0; i<MAX_BUF_ELEMS; i++)
2508 {
2509 /* delete assembly buffer */
2510 if (assembly_list[i].in_use)
2511 {
2512 assembly_elem = &assembly_list[i];
2513 assembly_elem->in_use = FALSE;
2514 ACI_MFREE(assembly_elem->data.data);
2515 }
2516
2517
2518 /* delete segment buffer */
2519 if (segBuf_list[i].in_use)
2520 {
2521 segBuf = &segBuf_list[i];
2522
2523 /* remove element from segment buffer */
2524 segBufElem = remove_first_element(segBuf->list);
2525
2526 if (segBufElem NEQ NULL)
2527 {
2528 /* free memory */
2529 ACI_MFREE(segBufElem->data.data);
2530 ACI_MFREE(segBufElem);
2531 }
2532 else
2533 {
2534 segBuf->in_use = FALSE;
2535 }
2536 }
2537 } /* for */
2538
2539
2540 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
2541 {
2542 /* find concat. buffer in use */
2543 if (concBuf_list[i].in_use)
2544 {
2545
2546 /* get number of segments in this concat. buffer */
2547 count = get_list_count(concBuf_list[i].list);
2548
2549 /* conc buffer is incomplete */
2550 if ((count < concBuf_list[i].max_num) AND (count < CONC_MAX_SEGS))
2551 {
2552 if (count EQ 0)
2553 {
2554 /* last element of one conc buffer was deleted */
2555 concBuf_list[i].in_use = FALSE;
2556 R_AT ( RAT_OK,(T_ACI_CMD_SRC) concShrdPrm.srcId ) ( AT_CMD_CMGC );
2557 continue;
2558 }
2559 concBuf = &concBuf_list[i];
2560 break;
2561 }
2562 }
2563 }
2564
2565 if (concBuf)
2566 {
2567 /* remove element from concat. buffer */
2568 concBufElem = remove_first_element(concBuf->list);
2569
2570 if (concBufElem)
2571 {
2572
2573 /* delete segment from non-volatile memory */
2574 #ifdef TI_PS_FF_CONC_SMS
2575 sAT_PlusCMGD_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, concBufElem->rec_num,
2576 smsShrdPrm.status, concSMS_delAllIncompleteMsg, rConcSMS_PlusCMS_CMGD);
2577 #else
2578 sAT_PlusCMGD_Gl(concShrdPrm.srcId, concBufElem->rec_num, smsShrdPrm.status,
2579 concSMS_delAllIncompleteMsg, rAT_PlusCMS);
2580 #endif /* TI_PS_FF_CONC_SMS */
2581
2582 /* free memory */
2583 ACI_MFREE(concBufElem);
2584 /* decrease total count of stored CSMS segments by 1*/
2585 concShrdPrm.elem_count--;
2586 }
2587 }
2588 }
2589
2590
2591
2592 /************** Help Functions ******************************/
2593
2594
2595 /*
2596 +-------------------------------------------------------------------+
2597 | PROJECT : GSM-PS (6147) MODULE : CONC_SMS |
2598 | ROUTINE : concSMS_printConcatList |
2599 +-------------------------------------------------------------------+
2600
2601 PURPOSE :
2602 */
2603
2604 LOCAL void concSMS_printConcatList ()
2605 {
2606 T_ACI_LIST *current;
2607 UBYTE i;
2608 T_CONC_BUF *concBuf;
2609 T_CONC_BUF_ELEM *elem;
2610
2611
2612 TRACE_EVENT("Concatenation List:");
2613 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
2614 {
2615 if (concBuf_list[i].in_use EQ TRUE)
2616 {
2617 concBuf = &concBuf_list[i];
2618 TRACE_EVENT_P2(" ref_num: 0x%04x , max_num: %u",
2619 concBuf->ref_num, concBuf->max_num);
2620 current = concBuf->list;
2621 while (current)
2622 {
2623 elem = (T_CONC_BUF_ELEM*) current->msg;
2624 TRACE_EVENT_P4(" seq_num: %d , rec_num: %d , status: %d, mem= %d",
2625 elem->seq_num, elem->rec_num, elem->status, elem->mem);
2626 current = current->next;
2627 }
2628 }
2629 }
2630 }
2631
2632 /* Marcus: Issue 872: 03/10/2002
2633 +-------------------------------------------------------------------+
2634 | PROJECT : GSM-PS (6147) MODULE : CONC_SMS |
2635 | ROUTINE : concSMS_findMaxRefNum |
2636 +-------------------------------------------------------------------+
2637
2638 PURPOSE : Find the highest value of concBuf_list[i].ref_num
2639 */
2640
2641 LOCAL USHORT concSMS_findMaxRefNum(void)
2642 {
2643 UBYTE i;
2644 USHORT ref_num = 0;
2645 TRACE_FUNCTION("concSMS_findMaxRefNum()");
2646 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
2647 {
2648 if (concBuf_list[i].in_use EQ TRUE)
2649 {
2650 if ((concBuf_list[i].ref_num & 0x00ff)> ref_num) /* since we use only 8-Bit ref_num */
2651 ref_num = concBuf_list[i].ref_num & 0x00ff;
2652 }
2653 }
2654 return ref_num;
2655 }
2656
2657
2658 GLOBAL void concSMS_clearIncompleteMsg()
2659 {
2660
2661 T_SEG_BUF *segBuf = NULL;
2662 T_SEG_BUF_ELEM *segBufElem;
2663 T_SM_ASSEMBLY *assembly_elem;
2664 T_CONC_BUF *concBuf = NULL;
2665 T_CONC_BUF_ELEM *concBufElem;
2666 UBYTE i;
2667
2668
2669
2670 TRACE_FUNCTION ("concSMS_clearIncompleteMsg()");
2671
2672
2673 if (RefNum_Del EQ concShrdPrm.full.RefNum)
2674 {
2675 concShrdPrm.full.Conc_Full = FALSE;
2676 concShrdPrm.full.RefNum = 0xFF;
2677 }
2678
2679
2680 for (i=0; i<MAX_BUF_ELEMS; i++)
2681 {
2682 /* delete assembly buffer */
2683 if (assembly_list[i].in_use AND assembly_list[i].ref_num EQ RefNum_Del)
2684 {
2685 assembly_elem = &assembly_list[i];
2686 assembly_elem->in_use = FALSE;
2687 ACI_MFREE(assembly_elem->data.data);
2688 break;
2689 }
2690
2691
2692 /* delete segment buffer */
2693 if (segBuf_list[i].in_use AND segBuf_list[i].ref_num EQ RefNum_Del)
2694 {
2695
2696 segBuf = &segBuf_list[i];
2697
2698
2699 /*remove element from segment buffer */
2700 segBufElem = remove_first_element(segBuf->list);
2701
2702 if (segBufElem NEQ NULL)
2703 {
2704 segBuf->in_use = FALSE;
2705 /* free memory */
2706 ACI_MFREE(segBufElem->data.data);
2707 ACI_MFREE(segBufElem);
2708
2709
2710 }
2711 else
2712 {
2713
2714 segBuf->in_use = FALSE;
2715
2716 }
2717 break;
2718 }
2719
2720 }
2721
2722 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
2723 {
2724 /* find concat. buffer in use */
2725 if (concBuf_list[i].in_use AND concBuf_list[i].ref_num EQ RefNum_Del)
2726 {
2727 concBuf_list[i].in_use = FALSE;
2728 concBuf = &concBuf_list[i];
2729 break;
2730
2731 }
2732 }
2733
2734 if (concBuf)
2735 {
2736 /* remove element from concat. buffer */
2737 concBufElem = remove_first_element(concBuf->list);
2738
2739 if (concBufElem)
2740 {
2741 /* free memory */
2742 ACI_MFREE(concBufElem);
2743 /* decrease total count of stored CSMS segments by 1*/
2744 concShrdPrm.elem_count--;
2745
2746 }
2747 }
2748 }
2749
2750
2751
2752 GLOBAL void concSMS_AddtoconcBuff(void)
2753 {
2754 UBYTE i;
2755
2756
2757 TRACE_FUNCTION("concSMS_AddtoconcBuff()");
2758
2759 for (i=0;i<concShrdPrm.full.Numsegs;i++)
2760 {
2761 concSMS_addToConcatList(concShrdPrm.full.RefNum,Addres,
2762 concShrdPrm.full.MaxNum,concShrdPrm.full.SeqNum[i],
2763 concShrdPrm.full.RecNum[i],SMS_STAT_RecRead,concShrdPrm.full.MemType[i]);
2764 }
2765 }
2766
2767 /*
2768 +-------------------------------------------------------------------+
2769 | PROJECT : GSM-PS (6147) MODULE : CONC_SMS |
2770 | ROUTINE : concSMS_DeleteConcList |
2771 +-------------------------------------------------------------------+
2772
2773 PURPOSE : This function is used to delete the concatinated SMS, when
2774 the CMGD command contails the delete flag greater than ZERO.
2775
2776 */
2777
2778 GLOBAL void concSMS_DeleteConcList ( )
2779 {
2780 T_CONC_CMGD *prm = &concShrdPrm.specPrm.concCMGD;
2781 T_CONC_BUF_ELEM *elem;
2782 T_ACI_LIST *conc_list;
2783
2784 TRACE_FUNCTION ("concSMS_DeleteConcList()");
2785
2786
2787 elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg;
2788
2789 /* remove the old element from concatenation list and free its memory */
2790 conc_list = concSMS_removeFromConcatList(prm->ref_num, prm->address, elem->rec_num);
2791
2792 concSMS_printConcatList();
2793
2794 if (conc_list NEQ NULL)
2795 {
2796 TRACE_EVENT("conc_list not null");
2797 elem = (T_CONC_BUF_ELEM *)conc_list->msg;
2798
2799 /* save the concatenation list */
2800 prm->currConcBufListElem= conc_list;
2801 }
2802 else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */
2803 {
2804 TRACE_EVENT("Concat List is NULL : concSMS_DeleteConcList");
2805 UNSET_CONC;
2806 }
2807 }
2808
2809 #ifdef TI_PS_FF_CONC_SMS
2810 GLOBAL void rConcSMS_PercentCMGR ( T_ACI_CMGL_SM* sm,
2811 T_ACI_CMGR_CBM* cbm )
2812 {
2813 T_CONC_CMGR *prm = &concShrdPrm.specPrm.concCMGR;
2814
2815 TRACE_FUNCTION ("rConcSMS_PercentCMGR ()");
2816
2817 if (prm->currConcBufListElem NEQ NULL)
2818 {
2819 T_CONC_BUF_ELEM *elem;
2820 elem = (T_CONC_BUF_ELEM *)prm->currConcBufListElem->msg;
2821
2822 sAT_PercentCMGR_Gl((T_ACI_CMD_SRC)concShrdPrm.srcId, elem->rec_num,
2823 (T_ACI_SMS_READ) concShrdPrm.specPrm.concCMGR.rdMode,
2824 rConcSMS_PercentCMGR);
2825
2826 prm->currConcBufListElem = prm->currConcBufListElem->next;
2827
2828 #ifdef _CONC_TESTING_
2829 rAT_PercentCMGR_Ext (sm, cbm);
2830 #else
2831 rAT_PercentCMGR (sm, cbm);
2832 #endif
2833
2834 }
2835 else /* if (concShrdPrm.currConcBufListElem NEQ NULL) */
2836 {
2837 #ifdef _CONC_TESTING_
2838 rAT_PercentCMGR_Ext (sm, cbm);
2839 #else
2840 rAT_PercentCMGR (sm, cbm);
2841 #endif
2842
2843 R_AT ( RAT_OK, (T_ACI_CMD_SRC)concShrdPrm.srcId ) ( AT_CMD_P_CMGR );
2844 UNSET_CONC;
2845 }
2846 }
2847
2848 #endif /* TI_PS_FF_CONC_SMS */
2849 /*
2850 * This functions checks if the conc can be extended. If the maximum
2851 * capacity is reached the CSMS will be handled as normal (single) SMS.
2852 */
2853 BOOL concSMS_concBufferAvail()
2854 {
2855 USHORT count=0;
2856 int i;
2857
2858 TRACE_FUNCTION("concSMS_concBufferAvail");
2859
2860 /* check if there is a free conc buffer available */
2861 for (i=0; i<MAX_CONC_BUF_ELEMS; i++)
2862 {
2863 if (concBuf_list[i].in_use EQ TRUE)
2864 {
2865 count++;
2866 }
2867 }
2868 if (count >= MAX_CONC_BUF_ELEMS)
2869 {
2870 return FALSE; /* all conc buffer in use, no free available */
2871 }
2872
2873 return TRUE;
2874 }
2875
2876