comparison g23m-aci/aci/conc_sms.c @ 0:75a11d740a02

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