comparison src/aci2/aci/conc_sms.c @ 3:93999a60b835

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