comparison gsm-fw/ccd/ccd.c @ 648:970d6199f2c5

gsm-fw/ccd/*.[ch]: initial import from the LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Thu, 04 Sep 2014 05:48:57 +0000
parents
children
comparison
equal deleted inserted replaced
647:a60b375014e3 648:970d6199f2c5
1 /*
2 +-----------------------------------------------------------------------------
3 | Project :
4 | Modul : ccd.c
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 : Condat Conder Decoder -
18 | Definition of encoding and decoding functions of
19 | air interface messages
20 +-----------------------------------------------------------------------------
21 */
22
23 #define CCD_C
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <setjmp.h>
30
31 #ifdef _MSDOS
32 #include <dos.h>
33 #include <conio.h>
34 #endif
35
36 /*
37 * Standard definitions like UCHAR, ERROR etc.
38 */
39
40 #include "typedefs.h"
41 #include "header.h"
42
43 /*
44 * Types and constants used by CCD
45 */
46 #include "ccd_globs.h"
47
48 /*
49 * Type definitions for CCD data tables
50 */
51 #include "ccdtable.h"
52
53 /*
54 * Function prototypes of CCD-CCDDATA interface
55 */
56 #include "ccddata.h"
57
58 /*
59 * Error codes and prototypes of exported functions by CCD
60 * (USE_DRIVER EQ undef)
61 * For prototypes only look at ccdapi.h.
62 */
63 #undef USE_DRIVER
64 #include "ccdapi.h"
65
66 /*
67 * Types and functions for bit access and manipulation
68 */
69 #include "bitfun.h"
70
71
72 /*
73 * Prototypes of ccd internal functions
74 */
75 #include "ccd.h"
76
77 #if !(defined (CCD_TEST))
78 #include "vsi.h"
79 #include "os.h"
80 #endif
81
82 #ifdef SHARED_VSI
83 #define VSI_CALLER 0,
84 #else
85 #define VSI_CALLER
86 #endif
87
88 #ifndef RUN_FLASH
89 /* task_null is used in ccd_signup. It must have the same RUN_... setting. */
90 static T_CCD_TASK_TABLE task_null;
91 #endif /* !RUN_FLASH */
92
93 //TISH modified for MSIM
94 #if defined (CCD_TEST) || defined (_TOOLS_) || defined (WIN32)
95 /* For the DLL and for all simple environment define the task list locally */
96 /* 10 entries should be more than enough */
97 #define MAX_ENTITIES 10
98 T_CCD_TASK_TABLE* ccd_task_list[MAX_ENTITIES];
99 #else
100 extern T_CCD_TASK_TABLE* ccd_task_list[];
101 #endif
102
103 #ifndef RUN_FLASH
104 const T_CCD_VarTabEntry* mvar;
105 const T_CCD_SpareTabEntry* spare;
106 const T_CCD_CalcTabEntry* calc;
107 const T_CCD_CompTabEntry* mcomp;
108 const T_CCD_ElemTabEntry* melem;
109 const T_CCD_CalcIndex* calcidx;
110 const T_CCD_ValTabEntry* mval;
111 #else
112 extern const T_CCD_VarTabEntry* mvar;
113 extern const T_CCD_SpareTabEntry* spare;
114 extern const T_CCD_CalcTabEntry* calc;
115 extern const T_CCD_CompTabEntry* mcomp;
116 extern const T_CCD_ElemTabEntry* melem;
117 extern const T_CCD_CalcIndex* calcidx;
118 extern const T_CCD_ValTabEntry* mval;
119 #endif
120
121 #ifndef RUN_FLASH
122 /*
123 * Attention: if one of the following static data shall be used in
124 * both, internal as well as external RAM, they must be made global.
125 */
126 static USHORT max_message_id;
127
128 /*
129 * CCD internal buffer for decoded message
130 */
131 static UBYTE *ccd_decMsgBuffer;
132 /*
133 * Layer-specific cache for the bitlength of the message-identifier;
134 * A value of 0 indicates an empty (undetermined) entry
135 */
136 static UBYTE *mi_length;
137
138 /*
139 * CCD internal variables used in each call to code or decode message
140 */
141
142 static U8 aim_rrc_rcm;
143 static U8 aim_rrlp;
144 static U8 aim_sat;
145
146 static T_CCD_Globs globs_all;
147 #endif /* !RUN_FLASH */
148
149 /*
150 * CCD will call its encoding/decoding functions through a jump table.
151 */
152 #include "ccd_codingtypes.h"
153 #ifndef RUN_FLASH
154 T_FUNC_POINTER codec[MAX_CODEC_ID+1][2];
155 #else
156 extern T_FUNC_POINTER codec[MAX_CODEC_ID+1][2];
157 #endif
158
159 #ifndef RUN_FLASH
160 /* initialized is used in ccd_signup. It must have the same RUN_... setting. */
161 /*
162 * Initialising flag
163 */
164 BOOL initialized = FALSE;
165 #endif /* !RUN_FLASH */
166
167 #ifdef SHARED_CCD
168 /*
169 * If CCD is used in a premptive multithreaded system we need
170 * a semaphore to protect the coding and decoding sections.
171 */
172 #ifndef RUN_FLASH
173 T_HANDLE semCCD_Codec, semCCD_Buffer;
174 #else
175 extern T_HANDLE semCCD_Codec, semCCD_Buffer;
176 #endif /* RUN_FLASH */
177 #endif /* SHARED_CCD */
178
179 static U8* mempat;
180 #define LOWSEGMASK 0xFFFFF000
181
182 #ifndef RUN_FLASH
183 #ifdef DEBUG_CCD
184 /*
185 +--------------------------------------------------------------------+
186 | PROJECT : CCD (6144) MODULE : CCD |
187 | STATE : code ROUTINE : TRACE_CCD |
188 +--------------------------------------------------------------------+
189
190 PURPOSE : Error processing of the CCD.
191
192 */
193
194 void TRACE_CCD (T_CCD_Globs *globs, char *format, ...)
195 {
196 va_list varpars;
197 char trace_buf[256];
198 int i=0;
199
200 if (!globs->TraceIt)
201 return;
202
203 va_start (varpars, format); /* Initialize variable arguments. */
204 #if defined CCD_TEST
205 /*
206 * use vsi_o_trace - prefix the tracestring with [CCD]
207 * so the PCO can display it in a CCD window
208 */
209 strcpy (trace_buf, "~CCD~");
210 i = 5;
211 #endif /* CCD_TEST */
212 vsprintf (trace_buf+i, format, varpars);
213 va_end (varpars); /* Reset variable arguments. */
214
215 #ifdef CCD_TEST
216 printf ("\n%s\n", trace_buf);
217 #else
218 vsi_o_ttrace (globs->me, TC_CCD, trace_buf);
219 #endif /* CCD_TEST */
220
221 }
222 #endif /* !RUN_FLASH */
223
224 #endif
225
226 /*
227 * Stack operations
228 */
229 #define ST_CLEAR(globs) globs->SP=0;globs->StackOvfl=FALSE;
230
231 #define ST_OK(globs) (globs->StackOvfl EQ FALSE)
232
233 #define ST_CHECK(A, globs) {if (!(globs->StackOvfl) AND globs->SP < MAX_UPN_STACK_SIZE)\
234 {(A);}\
235 else\
236 {globs->StackOvfl = TRUE;}}
237
238 #define ST_PUSH(A, globs) ST_CHECK ((globs->Stack[globs->SP++] = (A)), globs)
239
240 #define ST_POP(A, globs) ST_CHECK ((A = globs->Stack[--(globs->SP)]), globs)
241
242 #define ST_TOP(A, globs) ST_CHECK ((A = globs->Stack[globs->SP-1]), globs)
243
244 #ifndef RUN_FLASH
245 /*
246 * Attention: if the static function calcUPN shall be used in
247 * both, internal as well as external RAM, it must be made global.
248 */
249 /*
250 +--------------------------------------------------------------------+
251 | PROJECT : CCD (6144) MODULE : CCD |
252 | STATE : code ROUTINE : calcUPN |
253 +--------------------------------------------------------------------+
254
255 PURPOSE : calculates the UPN-term for an element.
256
257 */
258 LOCAL BOOL calcUPN (ULONG op,
259 ULONG num_ops,
260 ULONG *result,
261 T_CCD_Globs *globs)
262 {
263 BOOL opError;
264 ULONG op1=0,op2=0;
265
266 opError = FALSE;
267
268 #ifdef DEBUG_CCD
269 TRACE_CCD (globs, "Calculation of UPN-term ");
270 #endif
271
272 while (num_ops-- AND !opError AND ST_OK(globs))
273 {
274 switch (calc[op].operation)
275 {
276 case '+':
277 /*
278 * get the upper two elements from the stack, add them
279 * and push the result on the stack
280 */
281 if (globs->SP >= 2)
282 {
283 ST_POP(op2, globs);
284 ST_POP(op1, globs);
285 ST_PUSH ((op1 + op2), globs);
286 }
287 #ifdef DEBUG_CCD
288 else
289 TRACE_CCD (globs, "Control parameter '+' causes invalid calculation");
290 #endif
291 break;
292 case '-':
293 /*
294 * get the upper two elements from the stack, subtract them
295 * and push the result on the stack
296 */
297 if (globs->SP >= 2)
298 {
299 ST_POP(op2, globs);
300 ST_POP(op1, globs);
301 ST_PUSH ((op1 - op2), globs);
302 }
303 #ifdef DEBUG_CCD
304 else
305 TRACE_CCD (globs, "Control parameter '-' causes invalid calculation");
306 #endif
307 break;
308 case '*':
309 /*
310 * get the upper two elements from the stack, multiply them
311 * and push the result on the stack
312 */
313 if (globs->SP >= 2)
314 {
315 ST_POP(op2, globs);
316 ST_POP(op1, globs);
317 ST_PUSH ((op1 * op2), globs);
318 }
319 #ifdef DEBUG_CCD
320 else
321 TRACE_CCD (globs, "Control parameter '*' causes invalid calculation");
322 #endif
323 break;
324 case '/':
325 /*
326 * get the upper two elements from the stack, divide them
327 * and push the result on the stack
328 */
329 if (globs->SP >= 2)
330 {
331 ST_POP(op2, globs);
332 if (!op2)
333 {
334 ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK,
335 (USHORT) (globs->bitpos), (USHORT) -1);
336 }
337 else
338 {
339 ST_POP(op1, globs);
340 ST_PUSH ((op1 / op2), globs);
341 }
342 }
343 #ifdef DEBUG_CCD
344 else
345 TRACE_CCD (globs, "Control parameter '/' causes invalid calculation");
346 #endif
347 break;
348 case '&':
349 /*
350 * get the upper two elements from the stack, perform a
351 * binary AND
352 * and push the result on the stack
353 */
354 if (globs->SP >= 2)
355 {
356 ST_POP(op2, globs);
357 ST_POP(op1, globs);
358 ST_PUSH ((op1 & op2), globs);
359 }
360 #ifdef DEBUG_CCD
361 else
362 TRACE_CCD (globs, "Control parameter '&' causes invalid calculation");
363 #endif
364 break;
365 case '|':
366 /*
367 * get the upper two elements from the stack, perform a
368 * binary OR
369 * and push the result on the stack
370 */
371 if (globs->SP >= 2)
372 {
373 ST_POP(op2, globs);
374 ST_POP(op1, globs);
375 ST_PUSH ((op1 | op2), globs);
376 }
377 #ifdef DEBUG_CCD
378 else
379 TRACE_CCD (globs, "Control parameter '|' causes invalid calculation");
380 #endif
381 break;
382 case 'A':
383 /*
384 * get the upper two elements from the stack, perform a
385 * logical AND
386 * and push a TRUE or FALSE on the stack
387 */
388 if (globs->SP >= 2)
389 {
390 ST_POP(op2, globs);
391 ST_POP(op1, globs);
392 ST_PUSH ((op1 AND op2), globs);
393 }
394 #ifdef DEBUG_CCD
395 else
396 TRACE_CCD (globs, "Control parameter 'AND' causes invalid calculation");
397 #endif
398 break;
399 case 'O':
400 /*
401 * get the upper two elements from the stack, perform a
402 * logical OR
403 * and push a TRUE or FALSE on the stack
404 */
405 if (globs->SP >= 2)
406 {
407 ST_POP(op2, globs);
408 ST_POP(op1, globs);
409 ST_PUSH ((op1 OR op2), globs);
410 }
411 #ifdef DEBUG_CCD
412 else
413 TRACE_CCD (globs, "Control parameter 'OR' causes invalid calculation");
414 #endif
415 break;
416 case 'X':
417 /*
418 * get the upper two elements from the stack, perform a
419 * logical XOR
420 * and push a TRUE or FALSE on the stack
421 */
422 if (globs->SP >= 2)
423 {
424 ST_POP(op2, globs);
425 ST_POP(op1, globs);
426 ST_PUSH ( ((op1 AND !op2) OR (!op1 AND op2)) , globs);
427 }
428 #ifdef DEBUG_CCD
429 else
430 TRACE_CCD (globs, "Control parameter 'XOR' causes invalid calculation");
431 #endif
432 break;
433 case '=':
434 /*
435 * get the upper two elements from the stack, look if they
436 * are equal
437 * and push a TRUE or FALSE on the stack
438 */
439 if (globs->SP >= 2)
440 {
441 ST_POP(op2, globs);
442 ST_POP(op1, globs);
443 ST_PUSH ((op1 EQ op2), globs);
444 }
445 #ifdef DEBUG_CCD
446 else
447 TRACE_CCD (globs, "Control parameter '=' causes invalid calculation");
448 #endif
449 break;
450 case '#':
451 /*
452 * get the upper two elements from the stack, look if they
453 * are different
454 * and push a TRUE or FALSE on the stack
455 */
456 if (globs->SP >= 2)
457 {
458 ST_POP(op2, globs);
459 ST_POP(op1, globs);
460 ST_PUSH ((op1 NEQ op2), globs);
461 }
462 #ifdef DEBUG_CCD
463 else
464 TRACE_CCD (globs, "Control parameter '#' causes invalid calculation");
465 #endif
466 break;
467 case '>':
468 /*
469 * get the upper two elements from the stack, look if
470 * op1 > op2
471 * and push a TRUE or FALSE on the stack
472 */
473 if (globs->SP >= 2)
474 {
475 ST_POP(op2, globs);
476 ST_POP(op1, globs);
477 ST_PUSH ((op1 > op2), globs);
478 }
479 #ifdef DEBUG_CCD
480 else
481 TRACE_CCD (globs, "Control parameter '>' causes invalid calculation");
482 #endif
483 break;
484 case '<':
485 /*
486 * get the upper two elements from the stack, look if
487 * op1 < op2
488 * and push a TRUE or FALSE on the stack
489 */
490 if (globs->SP >= 2)
491 {
492 ST_POP(op2, globs);
493 ST_POP(op1, globs);
494 ST_PUSH ((op1 < op2), globs);
495 }
496 #ifdef DEBUG_CCD
497 else
498 TRACE_CCD (globs, "Control parameter '<' causes invalid calculation");
499 #endif
500 break;
501 case 'P':
502 /*
503 * push a constant on the stack
504 */
505 ST_PUSH (calc[op].operand, globs);
506 #ifdef DEBUG_CCD
507 if (globs->StackOvfl == TRUE)
508 TRACE_CCD (globs, "Constant can't be pused on UPN stack");
509 #endif
510 break;
511 case ':':
512 /*
513 * duplicate the upper element on the stack
514 */
515 if (globs->SP >= 1)
516 {
517 ST_TOP (op1, globs);
518 ST_PUSH (op1, globs);
519 }
520 #ifdef DEBUG_CCD
521 else
522 TRACE_CCD (globs, "No UPN stack element to duplicate");
523 #endif
524 break;
525 case 'R':
526 /*
527 * push the content of a C-structure variable on the stack
528 */
529 {
530 /* if no register available some compilers may react with
531 a warning like this: identifier p not bound to register
532 */
533 UBYTE *p;
534 ULONG value;
535
536 /*
537 * normaly we have to check if the element is a VAR
538 * and not an array/substructure.
539 * - but this must be done by ccdgen
540 */
541
542 /*
543 * setup the read pointer to the element in the C-structure
544 */
545 p = globs->pstruct + melem[(USHORT) calc[op].operand].structOffs;
546
547 /*
548 * Get the element table entry from the element to read.
549 * if the element of the condition is conditional too
550 * then look for the valid flag of this element.
551 * if the element is not valid,
552 * we dont need to check the contents of it
553 */
554 if (melem[(USHORT) calc[op].operand].optional)
555 {
556 if (*(UBYTE *) p EQ FALSE)
557 {
558 ST_PUSH (0L, globs);
559 break;
560 }
561 else
562 p++;
563 }
564
565 /*
566 * read the contents of the element
567 */
568 switch (mvar[melem[(USHORT) calc[op].operand].elemRef].cType)
569 {
570 case 'B':
571 value = (ULONG) * p;
572 break;
573 case 'S':
574 value = (ULONG) * (USHORT *) p;
575 break;
576 case 'L':
577 value = *(ULONG *) p;
578 break;
579 default:
580 value = 0L;
581 }
582 ST_PUSH (value, globs);
583 break;
584 }
585 case 'S':
586 /*
587 * get the upper element from the stack an
588 * set the position of the bitstream pointer to this
589 * value
590 */
591 if (globs->SP >= 1)
592 {
593 ST_POP(op1, globs);
594 #ifdef DEBUG_CCD
595 TRACE_CCD (globs, "SETBITPOS %d (byte %d.%d)",
596 (USHORT) op1, (USHORT) (op1 / 8), (USHORT) (op1 % 8));
597 #endif
598 bf_setBitpos ((USHORT) op1, globs);
599 }
600 #ifdef DEBUG_CCD
601 else
602 TRACE_CCD (globs, "Control parameter 'SETBITPOS' causes invalid calculation");
603 #endif
604 break;
605 case 'G':
606 /*
607 * push the position of the bitstream pointer on the
608 * stack
609 */
610 ST_PUSH ((ULONG) globs->bitpos, globs);
611 #ifdef DEBUG_CCD
612 TRACE_CCD (globs, "GETBITPOS %d (byte %d.%d)",
613 (USHORT) globs->bitpos, globs->bytepos, globs->byteoffs);
614 #endif
615 break;
616 case '^':
617 /*
618 * swap the upper two elements of the stack
619 */
620 if (globs->SP >= 2)
621 {
622 ST_POP(op1, globs);
623 ST_POP(op2, globs);
624 ST_PUSH(op1, globs);
625 ST_PUSH(op2, globs);
626 }
627 #ifdef DEBUG_CCD
628 else
629 TRACE_CCD (globs, "Control parameter '^' causes invalid calculation");
630 #endif
631 break;
632 case 'K':
633 /*
634 * Keep a value in the KEEP register.
635 */
636 if (globs->SP >= 1)
637 {
638 ST_POP(op1, globs);
639 globs->KeepReg[calc[op].operand] = op1;
640 }
641 #ifdef DEBUG_CCD
642 else
643 TRACE_CCD (globs, "Control parameter 'KEEP' causes invalid calculation");
644 #endif
645 break;
646 case 'L':
647 /*
648 * Copy the L part of a TLV element from the KEEP register to the UPN stack.
649 */
650 ST_PUSH(globs->KeepReg[0]*8, globs);
651 #ifdef DEBUG_CCD
652 if (globs->StackOvfl == TRUE)
653 TRACE_CCD (globs, "Control parameter 'LTAKE' causes invalid calculation");
654 #endif
655 break;
656 case 'T':
657 /*
658 * Take a value from the KEEP register and push it on the UPN stack.
659 */
660 ST_PUSH(globs->KeepReg[calc[op].operand], globs);
661 #ifdef DEBUG_CCD
662 if (globs->StackOvfl == TRUE)
663 TRACE_CCD (globs, "Control parameter 'TAKE' causes invalid calculation");
664 #endif
665 break;
666 case 'C':
667 /*
668 * Compare the value on the UPN stack with the one stored in the KEEP register.
669 * Push the higher value in the KEEP register.
670 */
671 if (globs->SP >= 1)
672 {
673 ST_POP(op1, globs);
674 if ((globs->KeepReg[calc[op].operand]) < op1)
675 {
676 globs->KeepReg[calc[op].operand] = op1;
677 }
678 }
679 #ifdef DEBUG_CCD
680 else
681 TRACE_CCD (globs, "Control parameter 'MAX' causes invalid calculation");
682 #endif
683 break;
684 case 'Z':
685 /*
686 * Used to mark presence of an address information part error label
687 */
688 globs->errLabel = ERR_ADDR_INFO_PART;
689 break;
690 case 'D':
691 /*
692 * Used to mark presence of a distribution part error label
693 */
694 globs->errLabel = ERR_DISTRIB_PART;
695 break;
696 case 'N':
697 /*
698 * Used to mark presence of a non distribution part error label
699 */
700 globs->errLabel = ERR_NON_DISTRIB_PART;
701 break;
702 case 'M':
703 /*
704 * Used to mark presence of a message escape error label
705 */
706 globs->errLabel = ERR_MESSAGE_ESCAPE;
707 break;
708 case 'I':
709 /*
710 * Used to mark presence of an ignore error label
711 */
712 globs->errLabel = ERR_IGNORE;
713 break;
714 case 'l':
715 /*
716 * Take a value from the CCD STO register and push it on the UPN stack.
717 */
718 opError = ccd_getStore (globs, calc[op].operand, &op1);
719 if (!opError)
720 {
721 ST_PUSH(op1, globs);
722 #ifdef DEBUG_CCD
723 TRACE_CCD (globs, "Push CCD STORE register [%d] value to UPN stack",
724 calc[op].operand);
725 }
726 else
727 {
728 TRACE_CCD (globs, "Reading from CCD STORE register [%d] impossible",
729 calc[op].operand);
730 #endif
731 }
732 break;
733 case 's':
734 /*
735 * Store a value in the CCD STO register.
736 */
737 if (globs->SP >= 1)
738 {
739 ST_POP(op1, globs);
740 opError = ccd_writeStore (globs, calc[op].operand, op1);
741 #ifdef DEBUG_CCD
742 TRACE_CCD (globs, "Store value in CCD STO register [%d]",
743 calc[op].operand);
744 }
745 else
746 {
747 TRACE_CCD (globs, "Control parameter 'STORE' causes invalid calculation");
748 #endif
749 }
750 break;
751
752 default:
753 opError = TRUE;
754 break;
755 }
756 op++;
757 }
758
759 if (!opError AND ST_OK(globs))
760 {
761 if (result NEQ (ULONG *) NULL)
762 ST_POP (*result, globs);
763 return (ST_OK(globs));
764 }
765 else
766 {
767 #ifdef DEBUG_CCD
768 if(opError)
769 TRACE_CCD (globs, "Calculation of UPN-term failed ");
770 else
771 TRACE_CCD (globs, "Calculation of UPN-term failed due to stack overflow");
772 #endif
773 return FALSE;
774 }
775 }
776 #endif /* !RUN_FLASH */
777
778 #ifndef RUN_FLASH
779 /*
780 +--------------------------------------------------------------------+
781 | PROJECT : CCD (6144) MODULE : CCD |
782 | STATE : code ROUTINE : ccd_conditionOK |
783 +--------------------------------------------------------------------+
784
785 PURPOSE : Check if the conditions for an element are true.
786 The elemRef references an element entry from the elem tab.
787 The function returns TRUE if the defined
788 conditions are TRUE.
789
790 */
791
792 BOOL ccd_conditionOK (const ULONG e_ref, T_CCD_Globs *globs)
793 {
794 ULONG result, cond_calc_ref, num_cond_calcs, cix_ref;
795
796 cix_ref = melem[e_ref].calcIdxRef;
797 num_cond_calcs = calcidx[cix_ref].numCondCalcs;
798 cond_calc_ref = calcidx[cix_ref].condCalcRef;
799
800
801 if (! calcUPN (cond_calc_ref,
802 num_cond_calcs,
803 &result,
804 globs))
805 return FALSE;
806
807 return (result EQ TRUE);
808 }
809 #endif /* !RUN_FLASH */
810
811 #ifndef RUN_FLASH
812 /*
813 +--------------------------------------------------------------------+
814 | PROJECT : CCD (6144) MODULE : CCD |
815 | STATE : code ROUTINE : ccd_calculateRep |
816 +--------------------------------------------------------------------+
817
818 PURPOSE : For a given element (referenced by elemRef) calculate the
819 repeat value.
820
821 */
822
823 BOOL ccd_calculateRep (const ULONG e_ref,
824 ULONG *repeat,
825 ULONG *max_repeat,
826 T_CCD_Globs *globs)
827 {
828 ULONG cix_ref, result;
829 ULONG remaining_repeats=0;
830 ULONG rep_calc_ref, num_rep_calcs;
831
832 BOOL is_variable;
833
834 cix_ref = melem[e_ref].calcIdxRef;
835 num_rep_calcs = calcidx[cix_ref].numRepCalcs;
836 rep_calc_ref = calcidx[cix_ref].repCalcRef;
837
838 *max_repeat = (ULONG) melem[e_ref].maxRepeat;
839
840 if (num_rep_calcs EQ 0)
841 {
842 if (melem[e_ref].repType EQ 'i')
843 {
844 switch (melem[e_ref].elemType)
845 {
846 case 'S':
847 remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
848 / spare[melem[e_ref].elemRef].bSize);
849 break;
850 case 'F': /* Code transparent pointer to base type */
851 case 'R': /* Pointer to base type */
852 case 'V':
853 remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
854 / mvar[melem[e_ref].elemRef].bSize);
855 break;
856 case 'D': /* Code transparent pointer to composition */
857 case 'P': /* Pointer to composition */
858 case 'C':
859 /* for repeated compositions the remaining repeats
860 are set to the max repeats because of the unknown
861 size of one composition */
862 remaining_repeats = (ULONG) melem[e_ref].maxRepeat;
863 break;
864 default:
865 ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
866 break;
867 }
868
869 *repeat = MINIMUM (*max_repeat, remaining_repeats);
870 is_variable = TRUE;
871 }
872 else
873 {
874 if (melem[e_ref].repType EQ 'b')
875 {
876 remaining_repeats = (ULONG)(globs->maxBitpos-globs->bitpos);
877 *repeat = MINIMUM (*max_repeat, remaining_repeats);
878 }
879 else
880 {
881 *repeat = MINIMUM (*max_repeat,
882 (ULONG) calcidx[cix_ref].repCalcRef);
883 if (*repeat < (ULONG) calcidx[cix_ref].repCalcRef)
884 ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE,
885 (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
886 }
887 is_variable = FALSE;
888 }
889 }
890 else
891 {
892 is_variable = FALSE;
893 if (! calcUPN (rep_calc_ref,
894 num_rep_calcs,
895 &result,
896 globs))
897 {
898 *repeat = *max_repeat = 0;
899
900 ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
901 }
902 else
903 {
904 if ((melem[e_ref].repType != 'b') && (melem[e_ref].repType != 's'))
905 {
906 is_variable = TRUE;
907 }
908 if (melem[e_ref].repType EQ 'i')
909 {
910 switch (melem[e_ref].elemType)
911 {
912 case 'S':
913 remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
914 / spare[melem[e_ref].elemRef].bSize);
915 break;
916 case 'F': /* Code transparent pointer to base type */
917 case 'R': /* Pointer to base type */
918 case 'V':
919 remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
920 / mvar[melem[e_ref].elemRef].bSize);
921 break;
922 default:
923 ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
924 break;
925 }
926 *repeat = MINIMUM (result, remaining_repeats);
927 }
928 else
929 {
930 *repeat = MINIMUM (result, *max_repeat);
931 if (*repeat < result)
932 ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE,
933 (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
934 }
935 }
936 }
937 return (is_variable);
938 }
939 #endif /* !RUN_FLASH */
940
941 #ifndef RUN_FLASH
942 /*
943 +--------------------------------------------------------------------+
944 | PROJECT : CCD (6144) MODULE : CCD |
945 | STATE : code ROUTINE : ccd_performOperations |
946 +--------------------------------------------------------------------+
947
948 PURPOSE : Perform the operation for an element. This operations
949 are executed before an element is encoded or decoded.
950 The Operations work with the UPN-Stack.
951
952 */
953
954 void ccd_performOperations (ULONG num_of_ops,
955 ULONG op_def_ref,
956 T_CCD_Globs *globs)
957 {
958 if (! calcUPN (op_def_ref,
959 num_of_ops,
960 NULL,
961 globs))
962 ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
963 }
964 #endif /* !RUN_FLASH */
965
966 #ifndef RUN_FLASH
967 /*
968 * Attention: if the static function ccd_isOptional shall be used in
969 * both, internal as well as external RAM, it must be made global.
970 */
971 /*
972 +--------------------------------------------------------------------+
973 | PROJECT : CCD (6144) MODULE : CCD |
974 | STATE : code ROUTINE : ccd_isOptional |
975 +--------------------------------------------------------------------+
976
977 PURPOSE : Checks if a given element is optional. If the element is
978 not optional and is a composition,
979 a recursive call is performed in order to check
980 if the composition contains only optional elements.
981 In this case the whole composition is optional.
982
983 In case of components concatenated with a CSN1 coding
984 rules the meaning of the word <optional> differs from the
985 traditional TI tool chain conventions. So far some coding
986 types (like tagged types, e.g. GSM3_TV) characterise
987 optional elements inherently. The value of their valid
988 flag indicates the presence or absence of such an element.
989 Components concatenated with a CSN1 coding type cause
990 these valid flags in the C header structure too. If you
991 find a bit in the received message stream indicating
992 optional values not included in the message (e. g. a
993 CSN1_S1 element is represented by ??, CCD will set the
994 valid flag to zero. But the whole element represented by
995 the flag is present; only the value is absent! Therefor
996 the valid flag in the C structure is not an indication of
997 an element’s absence.
998 */
999
1000 LOCAL BOOL ccd_isOptional (ULONG e_ref, T_CCD_Globs *globs)
1001 {
1002 ULONG cix_ref;
1003
1004 switch (melem[e_ref].codingType)
1005 {
1006 case CCDTYPE_CSN1_S1: /* Fall through. */
1007 case CCDTYPE_CSN1_S0:
1008 case CCDTYPE_CSN1_SHL:
1009
1010 cix_ref = melem[e_ref].calcIdxRef;
1011 /*
1012 * If this element is conditional, check the condition.
1013 */
1014 if (calcidx[cix_ref].numCondCalcs NEQ 0
1015 AND ! ccd_conditionOK (e_ref, globs))
1016 return TRUE;
1017
1018 if (melem[e_ref].repType == 'i' AND
1019 calcidx[melem[e_ref].calcIdxRef].repCalcRef == 0)
1020 return TRUE;
1021 else
1022 return FALSE;
1023 // break;
1024 // PATCH FROM M18
1025 case CCDTYPE_CSN1_CONCAT:
1026 return TRUE;
1027
1028 default:
1029 break;
1030 }
1031
1032 if (! melem[e_ref].optional)
1033 {
1034 /*
1035 * if the element is an array with an interval [0..x]
1036 * it can be handled like an optional element
1037 */
1038 if ( ! (melem[e_ref].repType EQ 'i'
1039 AND calcidx[melem[e_ref].calcIdxRef].repCalcRef EQ 0))
1040 {
1041 /*
1042 * if the element is not optional but it is a composition
1043 * we check recursive if the composition consists only of
1044 * optional elements
1045 */
1046 if (melem[e_ref].elemType EQ 'C' OR
1047 melem[e_ref].elemType EQ 'D' OR
1048 melem[e_ref].elemType EQ 'P')
1049 {
1050 ULONG el, lel, c_ref;
1051
1052 c_ref = melem[e_ref].elemRef;
1053
1054 el = (ULONG) mcomp[c_ref].componentRef;
1055 lel = el + mcomp[c_ref].numOfComponents;
1056
1057 while (el < lel)
1058 {
1059 if (! ccd_isOptional (el, globs))
1060 return FALSE;
1061 el++;
1062 }
1063 }
1064 else
1065 return FALSE;
1066 }
1067 }
1068 return TRUE;
1069 }
1070 #endif /* !RUN_FLASH */
1071
1072 #ifndef RUN_FLASH
1073 /*
1074 +--------------------------------------------------------------------+
1075 | PROJECT : CCD (6144) MODULE : CCD |
1076 | STATE : code ROUTINE : ccd_decodeComposition |
1077 +--------------------------------------------------------------------+
1078
1079 PURPOSE : decodes the bitstream to a C-Structure.The decoding
1080 rules contains the element definitions for the
1081 elements of this message.
1082 This function may called recursivly because of a
1083 substructured element definition.
1084 */
1085
1086 void ccd_decodeComposition (const ULONG c_ref, T_CCD_Globs *globs)
1087 {
1088 /*
1089 * index in table melem
1090 */
1091 ULONG e_ref; /* element reference */
1092 ULONG l_ref; /* reference to the last element of a component */
1093 SHORT codecRet;
1094 BOOL ExtendedGroupActive = FALSE;
1095 BOOL GroupExtended = FALSE;
1096 BOOL MoreData;
1097 BOOL SetPosExpected = FALSE;
1098 int i;
1099 ULONG act_err_label;
1100
1101 #ifdef DEBUG_CCD
1102 #ifndef CCD_SYMBOLS
1103 TRACE_CCD (globs, "ccd_decodeComposition()");
1104 #else
1105 TRACE_CCD (globs, "ccd_decodeComposition(): Composition = %s",
1106 mcomp[c_ref].name);
1107 #endif
1108 #endif
1109
1110 act_err_label = (ULONG) globs->errLabel;
1111 globs->ccd_recurs_level++;
1112
1113 /*
1114 * setup the index in the melem table for this composition.
1115 * If this function is called for the first time
1116 * (ccd_recurs_level == 1) the elem-table entry for the msg_type
1117 * was skipped.
1118 */
1119
1120 l_ref = mcomp[c_ref].componentRef
1121 + mcomp[c_ref].numOfComponents;
1122
1123 e_ref = mcomp[c_ref].componentRef
1124 + ((globs->ccd_recurs_level EQ 1) ? 1 : 0);
1125
1126 /*
1127 * decode all elements
1128 */
1129 while (e_ref < l_ref)
1130 {
1131 #ifdef ERR_TRC_STK_CCD
1132 /* save the value for tracing in error case */
1133 globs->error_stack[globs->ccd_recurs_level] = (USHORT) e_ref;
1134 #endif /* ERR_TRC_STK_CCD */
1135
1136 if (melem[e_ref].extGroup != ' ' && GroupExtended && !ExtendedGroupActive)
1137 {
1138 /*
1139 * the last read extension bit signals an
1140 * extension of the group but there are no
1141 * more elements defined for this group.
1142 * This indicates a protocol extension, that must be
1143 * skipped by ccd.
1144 */
1145
1146 do
1147 {
1148 /*
1149 * read the ext-bit to determine the extension
1150 * of this group
1151 */
1152 GroupExtended = (bf_readBit (globs) EQ 0);
1153 /*
1154 * skip to next octett
1155 */
1156 #ifdef DEBUG_CCD
1157 TRACE_CCD (globs, "skipping 7 bits");
1158 #endif
1159 bf_incBitpos (7, globs);
1160 } while (GroupExtended);
1161 }
1162
1163 /*
1164 * check if the bitstream has ended
1165 */
1166 if (bf_endOfBitstream(globs) AND !globs->TagPending)
1167 {
1168 ULONG cix_ref, num_prolog_steps;
1169
1170 cix_ref = melem[e_ref].calcIdxRef;
1171 num_prolog_steps = calcidx[cix_ref].numPrologSteps;
1172
1173 /* End of the bit stream is not reached if a call to bf_setBitpos()
1174 * is expected for the next element of the current substructure.
1175 * An instructive example is an empty "mob_id"
1176 */
1177 if (num_prolog_steps)
1178 {
1179 ULONG prolog_step_ref = calcidx[cix_ref].prologStepRef;
1180
1181 i = (int) (prolog_step_ref + num_prolog_steps);
1182
1183 while (i >= (int) prolog_step_ref)
1184 {
1185 if (calc[i].operation == 'S')
1186 {
1187 SetPosExpected = TRUE;
1188 break;
1189 }
1190 i--;
1191 }
1192 }
1193
1194 if (SetPosExpected EQ FALSE)
1195 {
1196 /*
1197 * no more bits to decode.
1198 * If at least one mandatory element is to decode
1199 * generate an error.
1200 */
1201
1202 while (e_ref < l_ref)
1203 {
1204 if (! ccd_isOptional (e_ref, globs))
1205 ccd_setError (globs, ERR_MAND_ELEM_MISS, BREAK, (USHORT) -1);
1206
1207 e_ref++;
1208 }
1209 /* after the while loop the recursion level will be decremented. */
1210 break;
1211 }
1212 }
1213
1214 /*
1215 * look for extension group processing
1216 */
1217 if (melem[e_ref].extGroup NEQ ' ')
1218 {
1219 /*
1220 * extended group symbol found
1221 */
1222 switch (melem[e_ref].extGroup)
1223 {
1224 case '+':
1225 /*
1226 * start of an extended group
1227 */
1228 ExtendedGroupActive = TRUE;
1229 /*
1230 * read the extension bit to determine the extension
1231 * of this group
1232 */
1233 GroupExtended = (bf_readBit (globs) EQ 0);
1234 /*
1235 * use the jump-table for selecting the decode function
1236 */
1237 codecRet =
1238 codec[melem[e_ref].codingType][DECODE_FUN](c_ref,
1239 (USHORT)e_ref, globs);
1240 if (codecRet NEQ 0x7f)
1241 {
1242 /*
1243 * set the e_ref to the next or the same element
1244 */
1245 e_ref += codecRet;
1246 }
1247 break;
1248
1249 case '-':
1250 /*
1251 * end of one extension,
1252 * decode first and the read the extension bit.
1253 */
1254 /*
1255 * use the jump-table for selecting the decode function
1256 */
1257 codecRet =
1258 codec[melem[e_ref].codingType][DECODE_FUN](c_ref,
1259 (USHORT)e_ref, globs);
1260 if (codecRet NEQ 0x7f)
1261 {
1262 /*
1263 * set the e_ref to the next or the same element
1264 */
1265 e_ref += codecRet;
1266 }
1267
1268 /*
1269 * look if the previously readed extension bit
1270 * alows an extension of this group
1271 */
1272 if (!GroupExtended)
1273 {
1274
1275 ExtendedGroupActive = FALSE;
1276 /*
1277 * overread the following elements in the group
1278 */
1279 /*
1280 * search the last element of the extended group
1281 */
1282 while (e_ref < l_ref
1283 AND melem[e_ref].extGroup NEQ '*')
1284 {
1285 #ifdef DEBUG_CCD
1286 #ifdef CCD_SYMBOLS
1287 if (melem[e_ref].elemType EQ 'V')
1288 TRACE_CCD (globs, "Skipping ext-group element %s",
1289 ccddata_get_alias((USHORT) e_ref, 1));
1290 else if (melem[e_ref].elemType EQ 'C')
1291 TRACE_CCD (globs, "Skipping ext-group element %s",
1292 mcomp[melem[e_ref].elemRef].name);
1293 else
1294 TRACE_CCD (globs, "Skipping ext-group spare");
1295 #else
1296 TRACE_CCD (globs, "Skipping ext-group element %c-%d",
1297 melem[e_ref].elemType,
1298 e_ref);
1299
1300 #endif
1301 #endif
1302 e_ref++;
1303 }
1304 /*
1305 * skip the last element
1306 */
1307 e_ref++;
1308 }
1309 else
1310 {
1311 /*
1312 * read the extension bit to determine if the group
1313 * extension holds on
1314 */
1315 GroupExtended = (bf_readBit (globs) EQ 0);
1316 }
1317 break;
1318
1319 case '*':
1320 if (!ExtendedGroupActive)
1321 {
1322 /*
1323 * this is a single element extended group
1324 * often used for later extension of the protocol
1325 */
1326 /*
1327 * read the extension bit to determine if a group
1328 * extension is present
1329 */
1330 GroupExtended = (bf_readBit (globs) EQ 0);
1331 }
1332 ExtendedGroupActive = FALSE;
1333
1334 /*
1335 * use the jump-table for selecting the decode function
1336 */
1337 codecRet =
1338 codec[melem[e_ref].codingType][DECODE_FUN](c_ref, e_ref, globs);
1339 if (codecRet NEQ 0x7f)
1340 {
1341 /*
1342 * set the e_ref to the next or the same element
1343 */
1344 e_ref += codecRet;
1345 }
1346 break;
1347
1348 case '!': /* Moredata bit */
1349 case '#':
1350 if ((MoreData = bf_readBit (globs)) EQ 1)
1351 {
1352 /*
1353 * moredata-bit is set to 1
1354 * process this element.
1355 */
1356
1357 /*
1358 * use the jump-table for selecting the decode function
1359 */
1360 codecRet =
1361 codec[melem[e_ref].codingType][DECODE_FUN](c_ref, e_ref, globs);
1362
1363 if (melem[e_ref].extGroup EQ '#')
1364 {
1365 /*
1366 * if more data are signaled with an additional
1367 * bit but there are no
1368 * more elements defined for this group.
1369 * This indicates a protocol extension, that must be
1370 * skipped by ccd.
1371 */
1372
1373 do
1374 {
1375 /*
1376 * read the ext-bit to determine the extension
1377 * of this group
1378 */
1379 GroupExtended = (bf_readBit (globs) EQ 1);
1380 /*
1381 * skip to next octett
1382 */
1383 #ifdef DEBUG_CCD
1384 TRACE_CCD (globs, "skipping 7 bits");
1385 #endif
1386 bf_incBitpos (7, globs);
1387 } while (!bf_endOfBitstream(globs) AND GroupExtended);
1388
1389 }
1390
1391 if (codecRet NEQ 0x7f)
1392 {
1393 /*
1394 * set the elemRef to the next or the same element(USHORT)
1395 */
1396 e_ref += codecRet;
1397 }
1398 }
1399
1400 if (!MoreData)
1401 {
1402 /*
1403 * more data bit is cleared,
1404 * overread the following elements in the group
1405 * search the last element of the extended group
1406 */
1407 while (e_ref < l_ref
1408 AND melem[e_ref].extGroup NEQ '#')
1409 {
1410 #ifdef DEBUG_CCD
1411 #ifdef CCD_SYMBOLS
1412 if (melem[e_ref].elemType EQ 'V')
1413 TRACE_CCD (globs, "Skipping ext-group element %s",
1414 ccddata_get_alias((USHORT) e_ref, 1));
1415 else if (melem[e_ref].elemType EQ 'C')
1416 TRACE_CCD (globs, "Skipping ext-group element %s",
1417 mcomp[melem[e_ref].elemRef].name);
1418 else
1419 TRACE_CCD (globs, "Skipping ext-group spare");
1420 #else
1421 TRACE_CCD (globs, "Skipping ext-group element %c-%d",
1422 melem[e_ref].elemType,
1423 e_ref);
1424
1425 #endif
1426 #endif
1427 e_ref++;
1428 }
1429
1430 /*
1431 * skip the last element of the moredata group
1432 */
1433 e_ref++;
1434 }
1435 break;
1436 default:
1437 ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK,
1438 (USHORT) (globs->bitpos), (USHORT) -1);
1439 break;
1440 }
1441 }
1442 else
1443 {
1444 /*
1445 * no processing action for an extended group
1446 */
1447
1448 /*
1449 * use the jump-table for selecting the decode function
1450 */
1451 codecRet =
1452 codec[melem[e_ref].codingType][DECODE_FUN](c_ref, e_ref, globs);
1453 if (codecRet NEQ 0x7f)
1454 {
1455 /*
1456 * set the e_ref to the next or the same element
1457 */
1458 e_ref += codecRet;
1459 }
1460 }
1461 }
1462
1463 /* Reset indicator of exhaustion in the IEI table*/
1464 for (i = 0; globs->iei_ctx[globs->ccd_recurs_level].iei_table[i].valid== TRUE; i++)
1465 {
1466 globs->iei_ctx[globs->ccd_recurs_level].iei_table[i].exhausted = FALSE;
1467 globs->iei_ctx[globs->ccd_recurs_level].iei_table[i].act_amount = 0;
1468
1469 }
1470
1471 globs->iei_ctx[globs->ccd_recurs_level].countSkipped = 0;
1472 globs->ccd_recurs_level--;
1473 globs->errLabel = (U8) act_err_label;
1474 }
1475 #endif /* !RUN_FLASH */
1476
1477 #ifndef RUN_FLASH
1478 /*
1479 * Attention: if this static function shall be used in
1480 * both, internal as well as external RAM, it must be made global.
1481 */
1482 static void SkipExtensionOctets (ULONG *e_ref, ULONG l_ref)
1483 {
1484 /* The extended group is terminated. Skip over its IEs. */
1485 while (*e_ref < l_ref && melem[*e_ref].extGroup != '*')
1486 (*e_ref)++;
1487 if (*e_ref < l_ref)
1488 (*e_ref)++;
1489 }
1490 #endif /* !RUN_FLASH */
1491
1492 #ifndef RUN_FLASH
1493 /*
1494 * Attention: if this static function shall be used in
1495 * both, internal as well as external RAM, it must be made global.
1496 */
1497 LOCAL BOOL CheckBP_RecodeXB (ULONG ExtBitPos1, ULONG ExtBitPos2,
1498 ULONG ExtBitPos3, T_CCD_Globs *globs)
1499 {
1500 /* Absence due to validity flag, condition or a ccdWarning. */
1501 if (ExtBitPos3 == globs->bitpos )
1502 {
1503 globs->bitpos --;
1504 if (ExtBitPos1 NEQ ExtBitPos2)
1505 bf_recodeBit ((USHORT) ExtBitPos1, 1, globs);
1506 return FALSE;
1507 }
1508 return TRUE;
1509 }
1510 #endif /* !RUN_FLASH */
1511
1512 #ifndef RUN_FLASH
1513 /*
1514 +--------------------------------------------------------------------+
1515 | PROJECT : CCD (6144) MODULE : CCD |
1516 | STATE : code ROUTINE : ccd_encodeComposition |
1517 +--------------------------------------------------------------------+
1518
1519 PURPOSE : codes the content of a C-Structure into a bitstream.
1520 This function may be called recursivly if an IE in the
1521 structure is itself a structured IE.
1522
1523 For extended octet groups the following rules apply.
1524
1525 Any IE within an extension octet is characterised by its
1526 extGroup which is one of the following:
1527
1528
1529 '+' octet begins with this IE.
1530 ' ' octet continues with this IE or a new octet begins.
1531 '-' octet ends with this IE.
1532 '*' octet group ends with this IE.
1533
1534 An octet may begin with '+', '-', ' ' or '*'.
1535 An octet beginning with '-' or '*' is made of only one IE (7 bits).
1536 A group made of one octet has only one IE with '*'.
1537 If '+' is present, next IEs ending with '*' or '-' are present too.
1538 If the beginning IE with ' ' is not IE
1539
1540 Examples of extended group configurations.
1541 _ _ _ _ _
1542 | | | | | | |
1543 |+|*| |+| |*| one octet
1544 |_|_| |_|_|_|
1545
1546 _ _ _ _ _ _ _ _ _ _ _
1547 | | | | | | | | | | | | | |
1548 |+|-| |*| |+|-|*| |+| |-|*| two octets
1549 |_|_|_|_| |_|_|_| |_|_|_|_|
1550
1551
1552 _ _ _ _ _ _ _ _ _ _
1553 | | | | | | | | | | |
1554 |+| | |-| |-| |-| |*| four octets
1555 |_|_|_|_|_|_|_|_|_|_|
1556
1557 Also groups after groups are possible.
1558 _ _ _ _ _ _ _ _ _
1559 | | | | | | | | | |
1560 |+| |-| |*|+|*|*|*|
1561 |_|_|_|_|_|_|_|_|_|
1562
1563 The status of encoding is given as follows:
1564
1565 ExtendedGroupActive is set to 1 if '+' is present in the encoding.
1566 ExtendedGroupActive is changed from 1 to 0 when encoding '*'.
1567 ExtendedGroupActive is set to 0 if an octet beginning with ' ' is
1568 not present.
1569 OpenNewOctet is set to 1 after encoding an IE with '-'.
1570 ExtBitPos1 is set to the globs->bitpos when writing extension bit:
1571 1) for '+' or
1572 2) for ' ' after '-'
1573
1574 Extension bit is set to 0 if a further octet is encoded for
1575 the group. If an octet is the last one within a group, the
1576 extension bit is set to 1.
1577
1578 While processing the first IE of an octet (e.g. for '+'),
1579 if the IE is absent, CCD will skip over all IEs up to the
1580 ending '*'.
1581 When processing IEs with ' ' and for ExtendedGroupActive=1 the valid
1582 flag is set to 1 in order to compensate probable mistakes in PS.
1583
1584 */
1585
1586 void ccd_encodeComposition (const ULONG c_ref, T_CCD_Globs *globs)
1587 {
1588 ULONG e_ref;
1589 ULONG l_ref;
1590 BOOL ExtendedGroupActive = FALSE, OpenNewOctet = FALSE;
1591 ULONG ext_bit_pos1=0, ext_bit_pos2=0, ext_bit_pos3=0, more_data_bit_pos=0;
1592 int ext_bit_pending=0;
1593 UBYTE codecRet;
1594
1595
1596 #ifdef DEBUG_CCD
1597 #ifndef CCD_SYMBOLS
1598 TRACE_CCD (globs, "ccd_encodeComposition()");
1599 #else
1600 TRACE_CCD (globs, "ccd_encodeComposition(): Composition = %s",
1601 mcomp[c_ref].name);
1602 #endif
1603 #endif
1604
1605 globs->ccd_recurs_level++;
1606
1607 /*
1608 * setup the index in the melem table for this composition.
1609 * If this function is called for the first time
1610 * (ccd_recurs_level == 1) the elem-table entry for the msg_type
1611 * was skipped.
1612 */
1613
1614 l_ref = (USHORT)(mcomp[c_ref].componentRef
1615 + mcomp[c_ref].numOfComponents);
1616
1617 e_ref = (USHORT)(mcomp[c_ref].componentRef
1618 + ((globs->ccd_recurs_level EQ 1) ? 1 : 0));
1619
1620 /*
1621 * code all elements
1622 */
1623 while (e_ref < l_ref)
1624 {
1625 #ifdef ERR_TRC_STK_CCD
1626 /*
1627 * Save the value for tracing in error case.
1628 */
1629 globs->error_stack[globs->ccd_recurs_level] = (USHORT) e_ref;
1630 #endif /* ERR_TRC_STK_CCD */
1631
1632 /*
1633 * look for extension group processing
1634 */
1635 if (melem[e_ref].extGroup NEQ ' ')
1636 {
1637 /*
1638 * extended group symbol found
1639 */
1640 switch (melem[e_ref].extGroup)
1641 {
1642 case '+':
1643
1644 /*
1645 * remember the position of the extension bit
1646 * because we maybe have to recode it.
1647 */
1648 ext_bit_pos1 = ext_bit_pos2 = (ULONG) globs->bitpos;
1649
1650
1651 /*
1652 * write the extension bit. It may overwritten
1653 * later. (ext=0 -> group extended)
1654 */
1655 bf_writeBit (0, globs);
1656 ext_bit_pos3 = (USHORT) globs->bitpos;
1657
1658 #if defined(_TOOLS_)
1659 if (ccd_patch (globs, 0))
1660 codecRet = 1;
1661 else
1662 #endif /* _TOOLS_ */
1663 /* Use the jump-table for selecting encode function. */
1664 codecRet = (UBYTE)
1665 codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
1666
1667 /* Absence due to validity flag, conditions or a ccdWarning. */
1668 if (!CheckBP_RecodeXB (ext_bit_pos1, ext_bit_pos2, ext_bit_pos3, globs))
1669 {
1670 ExtendedGroupActive = FALSE;
1671 SkipExtensionOctets (&e_ref, l_ref);
1672 continue;
1673 }
1674 /* Start of an extended group */
1675 else
1676 {
1677 OpenNewOctet = FALSE;
1678 }
1679
1680 ExtendedGroupActive = TRUE;
1681 ext_bit_pending = 1;
1682
1683 if (codecRet NEQ 0x7f)
1684 {
1685 /* Set the elemRef to the next or the same element. */
1686 e_ref += codecRet;
1687 }
1688 break;
1689
1690 /* End of one extension octet. */
1691 case '-':
1692 /* IE must be present if the previous one was not with '-'. */
1693 if (OpenNewOctet == FALSE)
1694 {
1695 #ifdef DEBUG_CCD
1696 if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
1697 {
1698 TRACE_CCD (globs, "Wrong value for valid flag!\n...changed to 1 for ccdID=%d",
1699 e_ref);
1700 }
1701 #endif
1702 /* IE has to be present. Don't trust PS code. */
1703 globs->pstruct [melem[e_ref].structOffs] = TRUE;
1704 }
1705 ext_bit_pos3 = (USHORT) globs->bitpos;
1706
1707 #if defined(_TOOLS_)
1708 if (ccd_patch (globs, 0))
1709 codecRet = 1;
1710 else
1711 #endif /* _TOOLS_ */
1712 /* Use the jump-table for selecting encode function. */
1713 codecRet = (UBYTE)
1714 codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
1715
1716 if (OpenNewOctet == TRUE)
1717 {
1718 /* Absence due to validity flag, conditions or a ccdWarning. */
1719 if (!CheckBP_RecodeXB (ext_bit_pos1, ext_bit_pos2, ext_bit_pos3, globs))
1720 {
1721 ExtendedGroupActive = FALSE;
1722 SkipExtensionOctets (&e_ref, l_ref);
1723 continue;
1724 }
1725 }
1726
1727 if (codecRet NEQ 0x7f)
1728 {
1729 /* Set the elemRef to the next or the same element. */
1730 e_ref += codecRet;
1731 }
1732
1733 /* IE with '-' belongs to the first octet. */
1734 if (ext_bit_pending EQ 1)
1735 {
1736 ext_bit_pending++;
1737 }
1738 /*
1739 * At least one octet has been encoded for the current group.
1740 * Swap the stored positions of the extension bits.
1741 */
1742 else
1743 {
1744 ext_bit_pos1 = ext_bit_pos2;
1745 }
1746
1747 /*
1748 * Store the position of the extension bit
1749 * because we maybe have to recode it.
1750 */
1751 ext_bit_pos2 = (ULONG) globs->bitpos;
1752 /*
1753 * write the extension bit. It may overwritten
1754 * later. (ext=0 -> group extended)
1755 */
1756 bf_writeBit (0, globs);
1757 OpenNewOctet = TRUE;
1758
1759 break;
1760
1761 case '*':
1762 if (!ExtendedGroupActive)
1763 {
1764 /*
1765 * This is a single element extended group, often
1766 * used for later extension of the protocol
1767 * Write '1' in extension bit since group is not extended yet.
1768 */
1769 bf_writeBit (1, globs);
1770 ext_bit_pos3 = (USHORT) globs->bitpos;
1771
1772 #if defined(_TOOLS_)
1773 if (ccd_patch (globs, 0))
1774 codecRet = 1;
1775 else
1776 #endif /* _TOOLS_ */
1777 /* Use the jump-table for selecting encode function. */
1778 codecRet = (UBYTE)
1779 codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
1780 /* Absence due to the valid flag or a ccdWarning. */
1781 if (ext_bit_pos3 == globs->bitpos)
1782 {
1783 globs->bitpos --;
1784 }
1785
1786 if (codecRet NEQ 0x7f)
1787 {
1788 /* Set the elemRef to the next or the same element. */
1789 e_ref += codecRet;
1790 }
1791 }
1792 else
1793 {
1794 ExtendedGroupActive = FALSE;
1795 /* IE must be present if the previous one was not with '-'. */
1796 if (OpenNewOctet == FALSE)
1797 {
1798 #ifdef DEBUG_CCD
1799 if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
1800 {
1801 TRACE_CCD (globs, "Wrong value for valid flag!\n...changed to 1 for ccdID=%d",
1802 e_ref);
1803 }
1804 #endif
1805 /* IE has to be present. Don't trust PS code. */
1806 globs->pstruct [melem[e_ref].structOffs] = TRUE;
1807 }
1808
1809 #if defined(_TOOLS_)
1810 if (ccd_patch (globs, 0))
1811 codecRet = 1;
1812 else
1813 #endif /* _TOOLS_ */
1814 /* Use the jump-table for selecting the encode function. */
1815 codecRet = (UBYTE)
1816 codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
1817 ext_bit_pos3 = (USHORT) globs->bitpos;
1818
1819 if (codecRet NEQ 0x7f)
1820 {
1821 /* Set the elemRef to the next or the same element. */
1822 e_ref += codecRet;
1823 }
1824
1825 if ((ext_bit_pos3-1) NEQ ext_bit_pos2)
1826 {
1827 /*
1828 * if the writepointer (ext_bit_pos3) have incremented
1829 * since the first extension bit (NEQ ext_bit_pos1)
1830 * at least one element of this group is valid
1831 * and written into the bitstream.
1832 */
1833 /*
1834 * the extended group is terminated,
1835 * so we have to switch the previously written
1836 * extBit from 0 to 1
1837 */
1838 bf_recodeBit ((USHORT) ext_bit_pos2, 1, globs);
1839 }
1840 else
1841 {
1842 /*
1843 * break of an extended group, no element are coded
1844 * since the last extension bit.
1845 */
1846 /*
1847 * the extended group is terminated,
1848 * so we have to switch the previously written
1849 * extBit from 0 to 1
1850 */
1851 if (ext_bit_pos1 NEQ ext_bit_pos2)
1852 {
1853 bf_recodeBit ((USHORT) ext_bit_pos1, 1, globs);
1854 }
1855 /*
1856 * delete the written ext-bit because the extended
1857 * group ended.
1858 */
1859 bf_setBitpos ((USHORT) ext_bit_pos2, globs);
1860 }
1861 }
1862 break;
1863 case '!':
1864 case '#':
1865 more_data_bit_pos = (ULONG) globs->bitpos;
1866 bf_writeBit (1, globs);
1867
1868 #if defined(_TOOLS_)
1869 if (ccd_patch (globs, 0))
1870 codecRet = 1;
1871 else
1872 #endif /* _TOOLS_ */
1873 /*
1874 * use the jump-table for selecting the encode function
1875 */
1876 codecRet = (UBYTE)
1877 codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
1878 if (codecRet NEQ 0x7f)
1879 {
1880 if (more_data_bit_pos+1 EQ globs->bitpos)
1881 {
1882 /*
1883 * rewrite the written moredata bit to 0
1884 */
1885 bf_setBitpos (more_data_bit_pos, globs);
1886 bf_writeBit (0, globs);
1887 /*
1888 * no coding performed -> extension group ended
1889 * We skip all elements in this group
1890 */
1891 while (melem[e_ref].extGroup EQ '!')
1892 e_ref++;
1893
1894 if (melem[e_ref].extGroup EQ '#')
1895 e_ref++;
1896 }
1897 else
1898 {
1899 if (melem[e_ref].extGroup EQ '#')
1900 {
1901 /*
1902 * code a zero bit for the last element
1903 */
1904 bf_writeBit (0, globs);
1905 }
1906 e_ref++;
1907 }
1908 }
1909 break;
1910 default:
1911 ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK,
1912 (USHORT) (globs->bitpos), (USHORT) -1);
1913 break;
1914 }
1915 }
1916 else
1917 {
1918 if (ExtendedGroupActive)
1919 {
1920 ext_bit_pos3 = (USHORT) globs->bitpos;
1921
1922 /* IE in the middle part of an ext-octet. */
1923 if (OpenNewOctet == FALSE)
1924 {
1925 #ifdef DEBUG_CCD
1926 if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
1927 {
1928 TRACE_CCD (globs, "Wrong value for valid flag!\n...changed to 1 for ccdID=%d",
1929 e_ref);
1930 }
1931 #endif
1932 globs->pstruct [melem[e_ref].structOffs] = TRUE;
1933 }
1934 }
1935
1936 #if defined(_TOOLS_)
1937 if (ccd_patch (globs, 0))
1938 codecRet = 1;
1939 else
1940 #endif /* _TOOLS_ */
1941 /* Use the jump-table for selecting encode function. */
1942 codecRet = (UBYTE)
1943 codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
1944
1945 /* The following is only meant for IEs after an IE with '-'. */
1946 if (ExtendedGroupActive)
1947 {
1948 if (OpenNewOctet == TRUE)
1949 {
1950 /* Absence due to validity flag, conditions or a ccdWarning. */
1951 if (!CheckBP_RecodeXB (ext_bit_pos1, ext_bit_pos2, ext_bit_pos3, globs))
1952 {
1953 ExtendedGroupActive = FALSE;
1954 SkipExtensionOctets (&e_ref, l_ref);
1955 continue;
1956 }
1957 /* Start of an extension octet */
1958 else
1959 {
1960 OpenNewOctet = FALSE;
1961 }
1962 }
1963 }
1964
1965 if (codecRet NEQ 0x7f)
1966 {
1967 /* Set the elemRef to the next or the same element. */
1968 e_ref += codecRet;
1969 }
1970 }
1971 }
1972
1973 globs->ccd_recurs_level--;
1974 }
1975 #endif /* !RUN_FLASH */
1976
1977 /* ---------------------------------------------------------------- */
1978 /* GLOBAL FUNCTIONS */
1979 /* ---------------------------------------------------------------- */
1980
1981 #ifndef RUN_FLASH
1982 /*
1983 +------------------------------------------------------------------------------
1984 | Function : ccd_check_pointer
1985 +------------------------------------------------------------------------------
1986 | Description : This function checks the validity of a pointer
1987 |
1988 | Parameters : ptr - the pointer
1989 |
1990 | Return : ccdOK if pointer valid, otherwise ccdError
1991 +------------------------------------------------------------------------------
1992 */
1993 int ccd_check_pointer (U8* ptr)
1994 {
1995 if (!ptr || ptr == mempat
1996 #ifdef WIN32
1997 /* For windows: check also if ptr is too small */
1998 || !(ptr && LOWSEGMASK)
1999 #endif
2000 )
2001 {
2002 return ccdError;
2003 }
2004 return ccdOK;
2005 }
2006 #endif /* !RUN_FLASH */
2007
2008 #ifndef RUN_FLASH
2009 /*
2010 +--------------------------------------------------------------------+
2011 | PROJECT : CCD (6144) MODULE : CCD |
2012 | STATE : code ROUTINE : ccd_begin |
2013 +--------------------------------------------------------------------+
2014
2015
2016 PARAMETERS: none
2017
2018 PURPOSE: Returns the address of the CCD buffer for decoded
2019 messages and locks it until ccd_end() is called
2020
2021 */
2022
2023 UBYTE* CCDDATA_PREF(ccd_begin) (void)
2024 {
2025 #ifdef SHARED_CCD
2026 /*
2027 * if the CCD is used in a premptive multithreaded system
2028 * we must lock this critical section
2029 */
2030 vsi_s_get (VSI_CALLER semCCD_Buffer);
2031 #endif
2032
2033 #ifdef DEBUG_CCD
2034 {
2035 #ifndef _TMS470
2036 T_CCD_Globs globs;
2037 globs.me = 0;
2038 globs.TraceIt = 1;
2039 TRACE_CCD (&globs, "CCD Begin");
2040 #endif
2041 }
2042 #endif
2043 return ccd_decMsgBuffer;
2044 }
2045 #endif /* !RUN_FLASH */
2046
2047 #ifndef RUN_FLASH
2048 /*
2049 +--------------------------------------------------------------------+
2050 | PROJECT : CCD (6144) MODULE : CCD |
2051 | STATE : code ROUTINE : ccd_end |
2052 +--------------------------------------------------------------------+
2053
2054
2055 PARAMETERS: none
2056
2057 PURPOSE: Unlocks the CCD buffer for decoded
2058 messages
2059
2060 */
2061
2062 void CCDDATA_PREF(ccd_end) (void)
2063 {
2064 #ifdef SHARED_CCD
2065 /*
2066 * if the CCD is used in a premptive multithreaded system
2067 * we must unlock this critical section of accessing the
2068 * decoded message buffer
2069 */
2070 vsi_s_release (VSI_CALLER semCCD_Buffer);
2071 #endif
2072 }
2073 #endif /* !RUN_FLASH */
2074
2075 #ifndef RUN_FLASH
2076 /*
2077 +--------------------------------------------------------------------+
2078 | PROJECT : CCD (6144) MODULE : CCD |
2079 | STATE : code ROUTINE : ccd_GetGlobVars |
2080 +--------------------------------------------------------------------+
2081
2082
2083 PARAMETERS:
2084
2085 PURPOSE: Determines which set of global variables to use
2086 and locks the CCD buffer (semaphore) if necessary.
2087
2088 */
2089 T_CCD_Globs* ccd_GetGlobVars (T_CCD_ERR_LIST_HEAD** eentry, T_CCD_STORE_LIST** stoentry)
2090 {
2091 T_CCD_TASK_TABLE* tentry;
2092 #ifndef SHARED_CCD
2093 int me = 0;
2094 #else
2095 T_HANDLE me;
2096 me = vsi_e_handle (0, NULL);
2097 if (me == VSI_ERROR)
2098 me = 0;
2099 #endif /* !SHARED_CCD */
2100
2101 tentry = ccd_task_list[me];
2102 tentry->ccd_globs->me = me;
2103 *eentry = tentry->ccd_err_list;
2104 *stoentry = tentry->ccd_store;
2105 #ifdef SHARED_CCD
2106 if (tentry->ccd_globs == &globs_all)
2107 {
2108 /*
2109 * if the CCD is used in a premptive multithreaded system
2110 * we must lock this critical section
2111 */
2112 vsi_s_get (VSI_CALLER semCCD_Codec);
2113 }
2114 #endif /* SHARED_CCD */
2115 return tentry->ccd_globs;
2116 }
2117 #endif /* !RUN_FLASH */
2118
2119 #ifndef RUN_FLASH
2120 /*
2121 +--------------------------------------------------------------------+
2122 | PROJECT : CCD (6144) MODULE : CCD |
2123 | STATE : code ROUTINE : ccd_FreeGlobVars |
2124 +--------------------------------------------------------------------+
2125
2126
2127 PARAMETERS: none
2128
2129 PURPOSE: Unlocks the CCD buffer for decoded messages
2130 if the entity is not GRR and if
2131 the CCD is used in a premptive multithreaded system.
2132
2133 */
2134 void ccd_FreeGlobVars (T_CCD_Globs* globs)
2135 {
2136 #ifdef SHARED_CCD
2137 if (globs == &globs_all)
2138 {
2139 vsi_s_release (VSI_CALLER semCCD_Codec);
2140 }
2141 #endif /* SHARED_CCD */
2142 }
2143 #endif /* !RUN_FLASH */
2144
2145 #ifndef RUN_FLASH
2146 #ifdef DEBUG_CCD
2147 /*
2148 +--------------------------------------------------------------------+
2149 | PROJECT : CCD (6144) MODULE : CCD |
2150 | STATE : code ROUTINE : ccd_dump_msg |
2151 +--------------------------------------------------------------------+
2152
2153 PARAMETERS: U16 l_buf
2154 - Number of bits in the encoded message or IE.
2155
2156 U16 o_buf
2157 - Offset of the bitstream buffer in bits.
2158
2159 U8 *buf
2160 - Bitstream buffer of the encoded message or IE.
2161
2162 T_CCD_Globs globs
2163 - Pointer to global variables
2164
2165 PURPOSE: Dump contents of air interface message - for debugging
2166
2167 */
2168 void ccd_dump_msg (U16 l_buf, U16 o_buf, U8 *buf, T_CCD_Globs *globs)
2169 {
2170
2171 if (!globs->TraceIt)
2172 return;
2173 else
2174 {
2175 int i, j, buflen;
2176 char s[64], c[4];
2177
2178 buflen = (l_buf + o_buf + 7) >> 3;
2179 TRACE_CCD (globs, "-------------------------------------------------");
2180 TRACE_CCD (globs, " CCD: Decode Message");
2181 TRACE_CCD (globs, " Before DECODING: lbuf= %d, obuf= %d", l_buf, o_buf);
2182 TRACE_CCD (globs, " Hex dump of message to be decoded:");
2183
2184 s[0] = '\0';
2185 for (i = o_buf>>3; i < buflen; i+=16)
2186 {
2187 for (j = 0; j < 16; j++)
2188 {
2189 if ((i+j) < buflen)
2190 {
2191 sprintf(c, " %02x", buf[i+j]);
2192 strcat (s, c);
2193 }
2194 }
2195 TRACE_CCD (globs, "%s", s);
2196 s[0] = '\0';
2197 }
2198 }
2199 }
2200 #endif /* DEBUG_CCD */
2201 #endif /* !RUN_FLASH */
2202
2203 #ifndef RUN_FLASH
2204 /*
2205 +--------------------------------------------------------------------+
2206 | PROJECT : CCD (6144) MODULE : CCD |
2207 | STATE : code ROUTINE : ccd_common_decode_init|
2208 +--------------------------------------------------------------------+
2209
2210 PARAMETERS:
2211
2212 PURPOSE: Perform common CCD initialization before message decode.
2213
2214 */
2215 void ccd_common_decode_init(U16 l_buf, U16 o_buf, U8 *buf, T_CCD_Globs *globs)
2216 {
2217 #if defined (DEBUG_CCD)
2218 /* to avoid the vsprintf if the traces won't appear anyhow */
2219 ULONG mask;
2220 if (vsi_gettracemask (globs->me, globs->me, &mask) != VSI_ERROR)
2221 {
2222 globs->TraceIt = mask & TC_CCD;
2223 }
2224 #endif
2225
2226 /*
2227 * no call to setjmp() done. So ccd_Error performs no longjmp in
2228 * case of an error
2229 */
2230 globs->jmp_mark_set = FALSE;
2231
2232 /* setup the bitbuffer */
2233 globs->bitbuf = buf;
2234 globs->bitpos = 0;
2235
2236 /* cleanup the read-caches */
2237 globs->lastbytepos16 = globs->lastbytepos32 = 0xffff;
2238
2239 /* setup the bitoffset */
2240 globs->bitoffs = o_buf;
2241
2242
2243 bf_incBitpos (o_buf, globs);
2244
2245 /*
2246 * calclate the max bitpos to read
2247 */
2248 globs->buflen = l_buf + o_buf;
2249 globs->maxBitpos = globs->buflen;
2250 globs->msgLen = globs->buflen;
2251 globs->errLabel = 0;
2252 globs->continue_array = TRUE;
2253 globs->SeekTLVExt = TRUE;
2254
2255 globs->ccd_recurs_level = 0;
2256 globs->CCD_Error = ccdOK;
2257 }
2258 #endif /* !RUN_FLASH */
2259
2260 #ifndef RUN_FLASH
2261 /*
2262 * Attention: if this static function shall be used in
2263 * both, internal as well as external RAM, it must be made global.
2264 */
2265 /*
2266 +--------------------------------------------------------------------+
2267 | PROJECT : CCD (6144) MODULE : CCD |
2268 | STATE : code ROUTINE : SeekForGSMExtensions |
2269 +--------------------------------------------------------------------+
2270
2271 PURPOSE: Check if there are elements left in the air message
2272 without being decoded. Assume that the next IE has the
2273 type T, TV or a TLV. Seek for Comprehension Required
2274 extensions.
2275 1) Rules to distinguish between the types:
2276 handling of unknown IEs (GSM 04.07, section 11.2.4)
2277 "Bit 8 of the IEI octet is set to "1" indicates a TV
2278 formatted type 1 standard IE or a T formatted type 2
2279 IEs, and to "0" indicates a TLV formatted type 4 IE.
2280 Hence, a 1 valued bit 8 indicates that the whole IE is
2281 one octet long, and a 0 valued bit 8 indicates that the
2282 following octet is a length octet.
2283 1) Rules to read the length:
2284 For TLV4 encode L in one byte.
2285 For TLV5 and ASN.1 encode in one byte or more. Use
2286 0x81, 0x82 etc in the first byte to say L is encoded
2287 in one, two etc bytes.
2288 For ASN.1 BER type use 0x80 in the first byte and
2289 two otets of 0 bits after the encoded IE.
2290 For all the three types it is possible to encode L
2291 in only one byte.
2292 TLV6 is not supported. TLV6 is not a GSM standard
2293 type. It has been defined in g23net software.
2294 */
2295 static void SeekForGSMExtensions (U8 entity, T_CCD_Globs *globs)
2296 {
2297 U8 *MsgBuf = (U8*)globs->bitbuf;
2298 U16 BP = globs->bytepos;
2299 U16 OctNr = (globs->buflen+7) >> 3;
2300 U16 errPos = 0;
2301 U8 errTag = 0xFF;
2302 U8 errCode;
2303
2304 #ifdef DEBUG_CCD
2305 TRACE_CCD( globs, "SeekForGSMExtensions...");
2306 #endif
2307 while (BP < OctNr)
2308 {
2309 U8 T = MsgBuf[BP];
2310 BOOL tlv5 = FALSE;
2311
2312 /* Expecting a CCDTYPE_GSM5_TLV type we get an unknown tag with MSB set.
2313 * Expecting other types than CCDTYPE_GSM5_TLV we get an unknown tag with
2314 * comprehension required bits (5, 6, 7 and 8 of IEI according to GSM0407)
2315 * are set to zero.
2316 */
2317 tlv5 = (aim_sat == entity);
2318 if ( (tlv5 && ((T & 0x80) == 0x80))
2319 ||
2320 (!tlv5 && ((T & 0xf0) == 0)) )
2321 {
2322 errTag = T;
2323 errPos = BP*8;
2324 errCode = ERR_COMPREH_REQUIRED;
2325 /* Report error. Do not analyse the rest. */
2326 break;
2327 }
2328 else
2329 {
2330 errTag = T;
2331 errPos = BP*8;
2332 errCode = ERR_IE_NOT_EXPECTED;
2333 }
2334
2335 /* The type is TLV or ASN.1. */
2336 if ((T & 0x80) NEQ 0x80)
2337 {
2338 /* BP points to the first L byte */
2339 U16 L = MsgBuf[++BP];
2340 switch (L)
2341 {
2342 /* End Of Content (ASN.1 BER) */
2343 case 0x80:
2344 do
2345 {
2346 BP++;
2347 } while ((*(U16*)&MsgBuf[BP]) != 0 && BP < OctNr);
2348 BP++;
2349 L = 0;
2350 break;
2351
2352 /* Length encoding in two bytes */
2353 case 0x81:
2354 L = MsgBuf[++BP];
2355 break;
2356
2357 /* Length encoding in three bytes */
2358 case 0x82:
2359 L = (MsgBuf[++BP]) << 8;
2360 L |= MsgBuf[++BP];
2361 break;
2362
2363 /* Length encoding in one byte. */
2364 default:
2365 break;
2366 }
2367
2368 /* Skip over the bytes. */
2369 while (L > 0 && BP < OctNr)
2370 {
2371 --L;
2372 ++BP;
2373 }
2374
2375 } /* if TLV */
2376 /* else: The type is T or TV. Skip one byte (see next step). */
2377
2378 /*
2379 * BP points to the last byte of the skipped IE,
2380 * move to the next IE.
2381 */
2382 BP++;
2383 }/* while bytes left unread */
2384
2385 /* Report the summary of the found erros. */
2386 if (errTag != 0xFF)
2387 {
2388 ccd_setError (globs, errCode,
2389 (U8)((errCode == ERR_COMPREH_REQUIRED) ? BREAK : CONTINUE),
2390 errTag,
2391 errPos,
2392 (USHORT) -1);
2393 }
2394 }
2395 #endif /* !RUN_FLASH */
2396
2397 #ifndef RUN_FLASH
2398 /*
2399 +--------------------------------------------------------------------+
2400 | PROJECT : CCD (6144) MODULE : CCD |
2401 | STATE : code ROUTINE : ccd_decodeMsg |
2402 +--------------------------------------------------------------------+
2403
2404
2405 PARAMETERS: UBYTE entity
2406 - specifies the calling entity of CCD. The Constants
2407 for each valid entity is defined in MCONST.CDG
2408
2409 UBYTE direction
2410 - specifies wether the message goes UPLINK or DOWNLINK.
2411 This is nessesary because there are same PDU-Type
2412 codes for different messages.
2413
2414 T_MSGBUF * mBuf
2415 - specifies the bitstream buffer of the message. The
2416 struct contains the l_buf and the o_buf elements.
2417 These elements specifies the length and offset in bits
2418 of the bitstream in the T_MSGBUF component buf.
2419
2420 UBYTE * mStruct
2421 - reference to the C-Structure of the decoded message.
2422 The type may differ so the Pointer is always typed as
2423 UBYTE* and must be casted after decoding. If this parameter
2424 is NULL CCD uses his internal buffer wich must be
2425 protected via ccd_begin() in a multithread environment.
2426
2427 UBYTE mId
2428 - specifies the PDU-Type of the bitstream. If this
2429 parameter is not equal 0xff the CCD does not decode
2430 the pdu-type from the bitstream to decide wich decoding
2431 rules to select. Normaly this param is set to 0xff.
2432
2433 PURPOSE: decodes a bitstream, containing a valid TETRA-Message
2434 of the Air-Interface to a corresponding C-Structure.
2435
2436 */
2437
2438 BYTE CCDDATA_PREF(ccd_decodeMsg) (UBYTE entity,
2439 UBYTE direction,
2440 T_MSGBUF *mBuf,
2441 UBYTE *mStruct,
2442 UBYTE mId)
2443 {
2444 UBYTE theMsgId;
2445 USHORT mcompRef;
2446 int jmp_ret;
2447 T_CCD_Globs *globs;
2448 T_CCD_ERR_LIST_HEAD* eentry;
2449 T_CCD_STORE_LIST* stoentry;
2450
2451 globs = ccd_GetGlobVars (&eentry, &stoentry);
2452
2453 /*
2454 * setup the structure-buffer
2455 *
2456 * if the parameter of the decoded message buffer address is NULL
2457 * we use the internal one
2458 */
2459 globs->pstruct = (mStruct EQ NULL) ? ccd_decMsgBuffer : mStruct;
2460 globs->pstructOffs = 0;
2461
2462 ccd_common_decode_init(mBuf->l_buf, mBuf->o_buf, mBuf->buf, globs);
2463 ccd_err_reset (eentry);
2464 globs->errLabel = 0;
2465 globs->continue_array = TRUE;
2466
2467 #ifdef DEBUG_CCD
2468 ccd_dump_msg(mBuf->l_buf, mBuf->o_buf, mBuf->buf, globs);
2469 #endif
2470
2471 if (mId NEQ 0xff AND mId NEQ 0xfe)
2472 globs->pstruct[0] = theMsgId = mId;
2473 else
2474 {
2475 /* Read the message identifier */
2476 globs->pstruct[0] = bf_decodeByteNumber ((ULONG) mi_length[entity], globs);
2477 theMsgId = globs->pstruct[0];
2478 }
2479
2480 /* Get entry in mmtx table for this message */
2481 mcompRef = ccddata_get_mmtx(entity,theMsgId,direction);
2482
2483 /* Check the message identifier */
2484 if (theMsgId > max_message_id OR mcompRef EQ NO_REF)
2485 {
2486 #ifdef ERR_TRC_STK_CCD
2487 globs->ccd_recurs_level = 255;
2488 #endif /* ERR_TRC_STK_CCD */
2489 ccd_setError (globs, ERR_INVALID_MID, BREAK,
2490 (USHORT) theMsgId, (USHORT) -1);
2491 ccd_FreeGlobVars (globs);
2492 ccd_err_free (eentry);
2493 return (BYTE)globs->CCD_Error;
2494 }
2495 #ifdef ERR_TRC_STK_CCD
2496 /* save the value for tracing in error case */
2497 globs->error_stack[0] = mcompRef;
2498 #endif /* ERR_TRC_STK_CCD */
2499
2500 #ifdef DEBUG_CCD
2501 #ifdef CCD_SYMBOLS
2502 TRACE_CCD (globs, "CCD decode: Message = %s",
2503 mcomp[mcompRef].name);
2504 #else
2505 TRACE_CCD (globs, "CCD decode: MessageId = %x", theMsgId);
2506 #endif
2507 #endif
2508
2509 /*
2510 * Clean up the entite C-structure before decoding.
2511 * Do not overwrite the MsgId (1. Byte)
2512 */
2513 #ifdef DEBUG_CCD
2514 TRACE_CCD (globs, "CCD Cleaning struct %ld bytes",
2515 mcomp[mcompRef].cSize-1);
2516 #endif
2517 memset ((UBYTE *) &globs->pstruct[1], 0,
2518 (size_t)(mcomp[mcompRef].cSize - 1));
2519
2520 /*
2521 * clear the UPN stack
2522 */
2523 ST_CLEAR(globs);
2524 memset ((ULONG *) &(globs->KeepReg[0]), 0, MAX_KEEP_REG_SIZE);
2525
2526 /*
2527 * inform the GSM-CODEC about the begin of a new message
2528 */
2529 cdc_GSM_start (globs);
2530
2531 jmp_ret = setjmp (globs->jmp_mark);
2532
2533 if (jmp_ret EQ 0)
2534 {
2535 globs->jmp_mark_set = TRUE;
2536 ccd_decodeComposition ((ULONG) mcompRef, globs);
2537
2538 /*
2539 * The coding rules and the data tables must be able to lead CCD to
2540 * understand the bit buffer, element by element. If for some reason
2541 * the bit pointer points to a place after the message limit, the
2542 * encoding action is not trustworthy. Nevertheless CCD reports a
2543 * WARNING and not error.
2544 * In development phase it is helpful to detect such cases.
2545 * Otherwise the caller can supposedly still use the message.
2546 */
2547 if (globs->bitpos > globs->buflen)
2548 {
2549 ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, mcompRef, NULL);
2550 }
2551 /*
2552 * Seek for GSM extensions with types T, TV and TLV.
2553 * (GRR, RCM/RRC and RRLP assume other extension mechanisms.)
2554 * Check only at octet border.
2555 */
2556 else if ((globs->SeekTLVExt) && !globs->byteoffs)
2557 {
2558 SeekForGSMExtensions (entity, globs);
2559 }
2560 }
2561
2562
2563 #ifdef DEBUG_CCD
2564 TRACE_CCD (globs, "CCD-ERROR = %d", globs->CCD_Error);
2565 TRACE_CCD (globs, "-------------------------------------------------");
2566 #endif /* DEBUG_CCD */
2567
2568 ccd_FreeGlobVars (globs);
2569 ccd_err_free (eentry);
2570
2571 return (BYTE) globs->CCD_Error;
2572 } /* end ccd_decodeMsg () */
2573 #endif /* !RUN_FLASH */
2574
2575 #ifndef RUN_FLASH
2576 /*
2577 +--------------------------------------------------------------------+
2578 | PROJECT : CCD (6144) MODULE : CCD |
2579 | STATE : code ROUTINE : ccd_decodeMsgPtr |
2580 +--------------------------------------------------------------------+
2581
2582
2583 PARAMETERS: U8 entity
2584 - specifies the calling entity of CCD. The Constants
2585 for each valid entity is defined in MCONST.CDG
2586
2587 U8 direction
2588 - specifies wether the message goes UPLINK or DOWNLINK.
2589 This is nessesary because there are same PDU-Type
2590 codes for different messages.
2591
2592 U16 l_buf
2593 - Lenght of the bitstrem to be decoded.
2594
2595 U16 o_buf
2596 - specifies the bitstream buffer of the message. The
2597 struct contains the l_buf and the o_buf elements.
2598 These elements specifies the length and offset in bits
2599 of the bitstream in the T_MSGBUF component buf.
2600
2601 U8 *buf
2602 - specifies the bitstream buffer of the message.
2603
2604 U8 ** mStructPtr
2605 - points to the pointer on the C-structure of the
2606 decoded message. The buffer containing this message
2607 structure will be allocated by CCD. After decoding
2608 the first element in the message C-structure contains
2609 the message (PDU) type as a UBYTE.
2610
2611 U8 mId
2612 - specifies the PDU-Type of the bitstream. If this
2613 parameter is not equal 0xff the CCD does not decode
2614 the pdu-type from the bitstream to decide wich decoding
2615 rules to select. Normaly this param is set to 0xff.
2616
2617 PURPOSE: Like ccd_decodeMsg, this function decodes a bitstream
2618 containing a valid TETRA-Message from the Air-Interface
2619 to a corresponding C-Structure, only this function
2620 allows the use of pointer types in the C-structure.
2621
2622 */
2623 #if defined DYNAMIC_ARRAYS || defined _TOOLS_
2624 S8 CCDDATA_PREF(ccd_decodeMsgPtr) (U8 entity,
2625 U8 direction,
2626 U16 l_buf,
2627 U16 o_buf,
2628 U8* buf,
2629 U8** mStructPtr,
2630 U8 mId)
2631 {
2632 /*
2633 * Make a dummy for the DLLs, even if DYNAMIC_ARRAYS is not defined to
2634 * keep the ccd.def unique
2635 */
2636 #ifndef DYNAMIC_ARRAYS
2637 return -1;
2638 }
2639 #else /* DYNAMIC_ARRAYS */
2640 UBYTE theMsgId;
2641 int jmp_ret;
2642 U32 msgsize;
2643 USHORT mcompRef;
2644 T_CCD_Globs *globs;
2645 T_CCD_ERR_LIST_HEAD* eentry;
2646 T_CCD_STORE_LIST* stoentry;
2647
2648 globs = ccd_GetGlobVars (&eentry, &stoentry);
2649 ccd_common_decode_init(l_buf, o_buf, buf, globs);
2650 ccd_err_reset (eentry);
2651 globs->errLabel = 0;
2652 globs->continue_array = TRUE;
2653 globs->alloc_head = *mStructPtr = NULL;
2654
2655 #ifdef DEBUG_CCD
2656 TRACE_CCD( globs, "======================================================");
2657 TRACE_CCD( globs, "ccd_decodeMsgPtr: Decoding message with pointer types.");
2658 ccd_dump_msg(l_buf, o_buf, buf, globs);
2659 #endif
2660
2661 /* Read the message identifier. */
2662 if (mId NEQ 0xff AND mId NEQ 0xfe)
2663 theMsgId = mId;
2664 else
2665 theMsgId = bf_decodeByteNumber ((ULONG) mi_length[entity], globs);
2666
2667 /* Get the entry in mmtx table for this message */
2668 mcompRef = ccddata_get_mmtx (entity,theMsgId,direction);
2669
2670 /* Check the validity of the message identifier */
2671 if (theMsgId > max_message_id OR mcompRef EQ NO_REF)
2672 {
2673 #ifdef ERR_TRC_STK_CCD
2674 globs->ccd_recurs_level = 255;
2675 #endif /* ERR_TRC_STK_CCD */
2676 ccd_setError (globs, ERR_INVALID_MID, BREAK, (USHORT) theMsgId, (USHORT) -1);
2677 ccd_FreeGlobVars (globs);
2678 ccd_err_free (eentry);
2679 return (BYTE) globs->CCD_Error;
2680 }
2681
2682 #ifdef ERR_TRC_STK_CCD
2683 /* save the value for tracing in error case */
2684 globs->error_stack[0] = mcompRef;
2685 #endif /* ERR_TRC_STK_CCD */
2686
2687 #ifdef DEBUG_CCD
2688 #ifdef CCD_SYMBOLS
2689 TRACE_CCD (globs, "CCD decode: Message = %s",
2690 mcomp[mcompRef].name);
2691 #else
2692 TRACE_CCD (globs, "CCD decode: MessageId = %x", theMsgId);
2693 #endif
2694 #endif
2695
2696 /*
2697 * Setup the structure-buffer.
2698 * Make a first simple estimation of much memory to allocate.
2699 * It is twice as much as the air interface message, rounded up
2700 * to the nearest kilobyte boundary.
2701 */
2702 msgsize = mcomp[mcompRef].cSize;
2703
2704 #ifdef DEBUG_CCD
2705 TRACE_CCD( globs, "Allocating %ld bytes for msg.", msgsize);
2706 #endif
2707
2708 globs->alloc_head = (U8 *) DRP_ALLOC(msgsize, DP_NO_FRAME_GUESS);
2709
2710 if (globs->alloc_head == NULL)
2711 {
2712 ccd_setError (globs, ERR_NO_MEM, BREAK, (USHORT) theMsgId, (USHORT) -1);
2713 ccd_FreeGlobVars (globs);
2714 ccd_err_free (eentry);
2715 return (BYTE) globs->CCD_Error;
2716 }
2717 *mStructPtr = globs->alloc_head;
2718 globs->pstruct = globs->alloc_head;
2719 globs->pstructOffs = 0;
2720
2721 /*Write the MSG ID in the buffer*/
2722 globs->pstruct[0] = theMsgId;
2723
2724 /*
2725 * Clean up the entite C-structure before decoding.
2726 * Do not overwrite the MsgId (1. Byte)
2727 */
2728 #ifdef DEBUG_CCD
2729 TRACE_CCD (globs, "CCD Cleaning struct %ld bytes", mcomp[mcompRef].cSize);
2730 #endif
2731 memset ((U8 *)globs->pstruct, 0, (size_t)(msgsize));
2732
2733 /*
2734 * Write the message identifier into the C-structure.
2735 */
2736 globs->pstruct[0] = theMsgId;
2737
2738 /*
2739 * clear the UPN stack
2740 */
2741 ST_CLEAR(globs);
2742 memset ((ULONG *) &(globs->KeepReg[0]), 0, MAX_KEEP_REG_SIZE);
2743
2744 /*
2745 * inform the GSM-CODEC about the begin of a new message
2746 */
2747 cdc_GSM_start (globs);
2748
2749 jmp_ret = setjmp (globs->jmp_mark);
2750
2751 if (jmp_ret EQ 0)
2752 {
2753 globs->jmp_mark_set = TRUE;
2754 ccd_decodeComposition ((ULONG) mcompRef, globs);
2755 if (globs->byteoffs NEQ 0)
2756 {
2757 bf_incBitpos (8-globs->byteoffs, globs);
2758
2759 /* There are more bits to be decoded than ccddata expects.
2760 * The additional bits may belong to unknown non-critical extensions.
2761 */
2762 if (globs->bitpos > globs->buflen)
2763 {
2764 ccd_recordFault (globs, ERR_UNEXPECT_PAD, CONTINUE, mcompRef, NULL);
2765 }
2766 /*
2767 * Seek for GSM extensions with types T, TV and TLV.
2768 * (GRR, RCM/RRC and RRLP assume other extension mechanisms.)
2769 * Check only at octet border.
2770 */
2771 else if ((entity != aim_rrc_rcm)
2772 && (entity != aim_rrlp)
2773 && (globs->SeekTLVExt)
2774 && !globs->byteoffs)
2775 {
2776 SeekForGSMExtensions (entity, globs);
2777 }
2778 }
2779 else
2780 {
2781 if (globs->bitpos > globs->buflen)
2782 {
2783 ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, mcompRef, NULL);
2784 }
2785 /*
2786 * Seek for GSM extensions with types T, TV and TLV.
2787 * (GRR, RCM/RRC and RRLP assume other extension mechanisms.)
2788 * Check only at octet border.
2789 */
2790 else if ((entity != aim_rrc_rcm)
2791 && (entity != aim_rrlp)
2792 && (globs->SeekTLVExt)
2793 && !globs->byteoffs)
2794 {
2795 SeekForGSMExtensions (entity, globs);
2796 }
2797 }
2798 }
2799
2800 #ifdef DEBUG_CCD
2801 TRACE_CCD (globs, "CCD-ERROR = %d", globs->CCD_Error);
2802 TRACE_CCD (globs, "-----------------------------------------------------");
2803 #endif /* DEBUG_CCD */
2804
2805 ccd_FreeGlobVars (globs);
2806 ccd_err_free (eentry);
2807
2808 return (BYTE) globs->CCD_Error;
2809 } /* end ccd_decodeMsgPtr () */
2810 #endif /* !DYNAMIC_ARRAYS */
2811 #endif /* DYNAMIC_ARRAYS || _TOOLS_ */
2812 #endif /* !RUN_FLASH */
2813
2814 #ifndef RUN_FLASH
2815 /*
2816 +--------------------------------------------------------------------+
2817 | PROJECT : CCD (6144) MODULE : CCD |
2818 | STATE : code ROUTINE : ccd_codeMsgPtr |
2819 +--------------------------------------------------------------------+
2820
2821 PARAMETERS: UBYTE entity
2822 - specifies the calling entity of CCD. The Constants
2823 for each valid entity is defined in MCONST.CDG
2824
2825 UBYTE direction
2826 - specifies wether the message goes UPLINK or DOWNLINK.
2827 This is nessesary because there are same PDU-Type
2828 codes for different messages.
2829
2830 T_MSGBUF * mBuf
2831 - specifies the bitstream buffer of the message. The
2832 struct contains the l_buf and the o_buf elements.
2833 These elements specifies the length and offset in bits
2834 of the bitstream in the T_MSGBUF component buf.
2835 The o_buf component must be specified by the caller,
2836 the l_buf component is calculated by CCD.
2837
2838 UBYTE * mStruct
2839 - reference to the C-Structure containing the
2840 C-Representation of the decoded message.
2841 The type should be casted to UBYTE*. If this parameter
2842 is NULL CCD uses his internal buffer wich must be
2843 protected via ccd_begin() in a multithread environment.
2844
2845 UBYTE mId
2846 - specifies the PDU-Type of the bitstream. If this
2847 parameter is not equal 0xff the CCD does not read
2848 the pdu-type from the structure component pt
2849 to decide wich decoding rules to select.
2850 Normaly this param is set to 0xff.
2851
2852 PURPOSE: encodes a C-Structure containing the C-Representation of
2853 a valid Air-interface message to a bitstream.
2854
2855 */
2856
2857 S8 CCDDATA_PREF(ccd_codeMsgPtr)(U8 entity,
2858 U8 direction,
2859 U16* l_buf,
2860 U16 o_buf,
2861 U8 *buf,
2862 U8* mStruct,
2863 U8 mId)
2864 {
2865 UBYTE theMsgId;
2866 int jmp_ret;
2867 USHORT maxBytes, mcompRef;
2868 T_CCD_Globs *globs;
2869 T_CCD_ERR_LIST_HEAD* eentry;
2870 T_CCD_STORE_LIST* stoentry;
2871
2872 globs = ccd_GetGlobVars (&eentry, &stoentry);
2873 ccd_err_reset (eentry);
2874
2875 #if defined (DEBUG_CCD)
2876 {
2877 /* to avoid the vsprintf if the traces won't appear anyhow */
2878 ULONG mask;
2879 if (vsi_gettracemask (globs->me, globs->me, &mask) != VSI_ERROR)
2880 {
2881 globs->TraceIt = mask & TC_CCD;
2882 }
2883 }
2884 #endif
2885
2886 /*
2887 * Set a sign that no call to setjmp() is done. So ccd_setError
2888 * performs no longjmp in case of an error.
2889 */
2890 globs->jmp_mark_set = FALSE;
2891
2892 /* Setup the bitbuffer. */
2893 globs->bitbuf = buf;
2894 globs->bitpos = 0;
2895
2896 /* and the structure-buffer */
2897 globs->pstruct = (mStruct EQ NULL) ? ccd_decMsgBuffer : mStruct;
2898 globs->pstructOffs = 0;
2899
2900 /* Cleanup the read-caches. */
2901 globs->lastbytepos16 = globs->lastbytepos32 = 0xffff;
2902
2903 /* Setup the bitoffset. */
2904 globs->bitoffs = o_buf;
2905
2906
2907 bf_incBitpos (o_buf, globs);
2908
2909 globs->bitbuf[globs->bytepos] = 0;
2910
2911 globs->ccd_recurs_level = 0;
2912
2913 globs->CCD_Error = ccdOK;
2914
2915 globs->continue_array = TRUE;
2916
2917 if (mId NEQ 0xff AND mId NEQ 0xfe)
2918 theMsgId = mId;
2919 else
2920 {
2921 theMsgId = globs->pstruct[0];
2922 }
2923
2924 mcompRef = ccddata_get_mmtx(entity,theMsgId,direction);
2925 /* Check the validity of the given message identifier. */
2926 if (theMsgId > max_message_id OR mcompRef EQ NO_REF)
2927 {
2928 #ifdef ERR_TRC_STK_CCD
2929 globs->ccd_recurs_level = 255;
2930 #endif /* ERR_TRC_STK_CCD */
2931 ccd_setError (globs, ERR_INVALID_MID, BREAK, (USHORT) theMsgId, (USHORT) -1);
2932 ccd_FreeGlobVars (globs);
2933 ccd_err_free (eentry);
2934 return (BYTE) globs->CCD_Error;
2935 }
2936
2937 #ifdef ERR_TRC_STK_CCD
2938 /* save the value for tracing in error case */
2939 globs->error_stack[0] = mcompRef;
2940 #endif /* ERR_TRC_STK_CCD */
2941
2942 maxBytes = (*l_buf + 7)>>3;
2943 globs->msgLen = *l_buf;
2944
2945 #ifdef DEBUG_CCD
2946 TRACE_CCD (globs, "-------------------------------------------------");
2947 TRACE_CCD (globs, "CCD: Code Message");
2948 TRACE_CCD (globs, "Cleaning %d bits (%d bytes) of the bitstream",
2949 mcomp[mcompRef].bSize, maxBytes);
2950 #endif
2951
2952 /*
2953 * Clean up the bit buffer for the encoded message before encoding.
2954 */
2955 memset ((U8 *) &buf[(o_buf>>3)], 0, (size_t) maxBytes);
2956 /* Store the length of ereased buffer to support error handling. */
2957 globs->buflen = *l_buf;
2958
2959 if (mId EQ 0xff)
2960 {
2961 /* Write the message identifier. */
2962 bf_writeBits ((U32)mi_length[entity], globs);
2963 }
2964
2965 #ifdef DEBUG_CCD
2966 #ifdef CCD_SYMBOLS
2967 TRACE_CCD (globs, "CCD encode: Message = %s", mcomp[mcompRef].name);
2968 #else
2969 TRACE_CCD (globs, "CCD encode: MessageId = %x", theMsgId);
2970 #endif
2971 #endif
2972
2973 /*
2974 * Clear the UPN stack.
2975 */
2976 ST_CLEAR(globs);
2977 memset ((ULONG *) &(globs->KeepReg[0]), 0, MAX_KEEP_REG_SIZE);
2978
2979 /*
2980 * Inform the GSM-CODEC about the begin of a new message.
2981 */
2982 cdc_GSM_start (globs);
2983
2984 jmp_ret = setjmp (globs->jmp_mark);
2985
2986 if (jmp_ret EQ 0)
2987 {
2988 /*
2989 * no call to setjmp() done. So ccd_Error performs no longjmp in
2990 * case of an error
2991 */
2992 globs->jmp_mark_set = TRUE;
2993 ccd_encodeComposition ((ULONG) mcompRef, globs);
2994 if (globs->bitpos > o_buf + *l_buf)
2995 {
2996 ccd_setError (globs, ERR_BUFFER_OF, CONTINUE, (USHORT) -1);
2997 }
2998 bf_writePadBits (globs);
2999 }
3000
3001 *l_buf = (USHORT) globs->bitpos - (USHORT) o_buf;
3002
3003 #ifdef DEBUG_CCD
3004 {
3005 int i, j, buflen;
3006 char s[64], c[4];
3007
3008 buflen = (*l_buf + o_buf + 7) >> 3;
3009
3010 TRACE_CCD (globs, "-------------------------------------------------");
3011 TRACE_CCD (globs, " After ENCODING: lbuf= %d, obuf= %d", *l_buf, o_buf);
3012 TRACE_CCD (globs, " Hex dump of encoded message:");
3013
3014 s[0] = '\0';
3015 for (i = o_buf >> 3; i < buflen; i+=16)
3016 {
3017 for (j = 0; j < 16; j++)
3018 {
3019 if ((i+j) < buflen)
3020 {
3021 sprintf(c, " %02x", buf[i+j]);
3022 strcat (s, c);
3023 }
3024 }
3025 TRACE_CCD (globs, "%s", s);
3026 s[0] = '\0';
3027 }
3028 }
3029 #endif
3030
3031 #ifdef DEBUG_CCD
3032 TRACE_CCD (globs, "CCD-ERROR = %d", globs->CCD_Error);
3033 TRACE_CCD (globs, "-------------------------------------------------");
3034 #endif
3035
3036 ccd_FreeGlobVars (globs);
3037 ccd_err_free (eentry);
3038
3039 return (BYTE)globs->CCD_Error;
3040 }
3041 #endif /* !RUN_FLASH */
3042
3043 #ifndef RUN_FLASH
3044 /*
3045 +--------------------------------------------------------------------+
3046 | PROJECT : CCD (6144) MODULE : CCD |
3047 | STATE : code ROUTINE : ccd_codeMsg |
3048 +--------------------------------------------------------------------+
3049
3050 PARAMETERS: UBYTE entity
3051 - specifies the calling entity of CCD. The Constants
3052 for each valid entity is defined in MCONST.CDG
3053
3054 UBYTE direction
3055 - specifies wether the message goes UPLINK or DOWNLINK.
3056 This is nessesary because there are same PDU-Type
3057 codes for different messages.
3058
3059 T_MSGBUF * mBuf
3060 - specifies the bitstream buffer of the message. The
3061 struct contains the l_buf and the o_buf elements.
3062 These elements specifies the length and offset in bits
3063 of the bitstream in the T_MSGBUF component buf.
3064 The o_buf component must be specified by the caller,
3065 the l_buf component is calculated by CCD.
3066
3067 UBYTE * mStruct
3068 - reference to the C-Structure containing the
3069 C-Representation of the decoded message.
3070 The type should be casted to UBYTE*. If this parameter
3071 is NULL CCD uses his internal buffer wich must be
3072 protected via ccd_begin() in a multithread environment.
3073
3074 UBYTE mId
3075 - specifies the PDU-Type of the bitstream. If this
3076 parameter is not equal 0xff the CCD does not read
3077 the pdu-type from the structure component pt
3078 to decide wich decoding rules to select.
3079 Normaly this param is set to 0xff.
3080
3081 PURPOSE: encodes a C-Structure containing the C-Representation of
3082 a valid Air-interface message to a bitstream.
3083
3084 */
3085
3086 BYTE CCDDATA_PREF(ccd_codeMsg) (UBYTE entity,
3087 UBYTE direction,
3088 T_MSGBUF *mBuf,
3089 UBYTE *mStruct,
3090 UBYTE mId)
3091 {
3092 return CCDDATA_PREF(ccd_codeMsgPtr) (entity, direction, &mBuf->l_buf,
3093 mBuf->o_buf, mBuf->buf, mStruct, mId);
3094 }
3095 #endif /* !RUN_FLASH */
3096
3097 #ifndef RUN_FLASH
3098 /*
3099 +------------------------------------------------------------------------------
3100 | Function : ccd_init_ccddata
3101 +------------------------------------------------------------------------------
3102 | Description : Initialize local tables.
3103 |
3104 | Parameters : -
3105 |
3106 | Return : ccdOK, ccdWarning, or ccdError depending on the success.
3107 +------------------------------------------------------------------------------
3108 */
3109 ULONG CCDDATA_PREF(ccd_init_ccddata) (void)
3110 {
3111 const T_CCD_CompTabEntry *msg;
3112 USHORT mcompRef;
3113 UBYTE ret, entity, num_of_entities;
3114 USHORT messageId;
3115 #ifdef DEBUG_CCD
3116 T_CCD_Globs *globs = &globs_all;
3117 #endif
3118
3119 aim_rrc_rcm = (U8)ccddata_get_ccdent ("UMTS_AS_ASN1_MSG");
3120 aim_rrlp = (U8)ccddata_get_ccdent ("RRLP_ASN1_MSG");
3121 aim_sat = (U8)ccddata_get_ccdent ("SAT");
3122
3123 mcomp = ccddata_get_mcomp (0);
3124 mvar = ccddata_get_mvar (0);
3125 mval = ccddata_get_mval (0);
3126 melem = ccddata_get_melem (0);
3127 spare = ccddata_get_spare (0);
3128 calc = ccddata_get_calc (0);
3129 calcidx = ccddata_get_calcidx (0);
3130
3131 mi_length = ccddata_get_mi_length();
3132 ccd_decMsgBuffer = ALIGN_BUF(ccddata_get_decmsgbuffer());
3133 max_message_id = (USHORT) ccddata_get_max_message_id();
3134
3135 #ifdef CCD_SYMBOLS
3136 if (!ccddata_mccd_symbols())
3137 {
3138 #ifdef CCD_TEST
3139 printf ("CCD_SYMBOLS is not set in ccddata\n");
3140 #else /* CCD_TEST */
3141 vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
3142 "CCD_SYMBOLS is not set in ccddata" );
3143 #endif /* CCD_TEST */
3144 }
3145
3146 #else /* CCD_SYMBOLS */
3147 if (ccddata_mccd_symbols())
3148 {
3149 #ifdef CCD_TEST
3150 printf ("Undefine CCD_SYMBOLS in ccddata\n");
3151 #else /* CCD_TEST */
3152 vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
3153 "Undefine CCD_SYMBOLS in ccddata" );
3154 #endif /* CCD_TEST */
3155 }
3156 #endif /* CCD_SYMBOLS */
3157
3158 #ifdef DEBUG_CCD
3159 /* Only for TRACE_CCD call in ccd_init. */
3160 globs->me = 0;
3161 globs->TraceIt = 1;
3162 #endif /* DEBUG_CCD */
3163
3164 num_of_entities = (UBYTE) ccddata_get_num_of_entities();
3165 for (entity = 0; entity < num_of_entities; entity++)
3166 {
3167 /*
3168 * Point to the first defined Message, to get the length
3169 * of the message identifier
3170 */
3171 msg = NULL;
3172 messageId = 0;
3173 while (msg EQ NULL AND messageId <= max_message_id)
3174 {
3175 /*
3176 * If there is no UPLINK-decoding, try the DOWNLINK.
3177 */
3178 if ((mcompRef = ccddata_get_mmtx(entity, messageId, UPLINK)) NEQ NO_REF)
3179 msg = (T_CCD_CompTabEntry *) &mcomp[mcompRef];
3180 else
3181 if ((mcompRef = ccddata_get_mmtx(entity, messageId, DOWNLINK)) NEQ NO_REF)
3182 msg = (T_CCD_CompTabEntry *) &mcomp[mcompRef];
3183 else
3184 messageId++;
3185 }
3186 if (msg NEQ NULL
3187 AND melem[msg->componentRef].elemType EQ 'V'
3188 AND melem[msg->componentRef].elemRef NEQ NO_REF)
3189 {
3190 /*
3191 * if there is a message for this layer - get the length
3192 * of the first element (msg_type or pdu_type)
3193 */
3194 mi_length[entity] =(UBYTE) (mvar[melem[msg->componentRef].elemRef].bSize);
3195 }
3196 else
3197 mi_length[entity] = 0;
3198
3199 #ifdef DEBUG_CCD
3200 TRACE_CCD (globs, "MI-LEN [ENTITY %d] = %d", entity, mi_length[entity]);
3201 #endif
3202 }
3203
3204 /*
3205 * Register all needed coding/decoding functions in the jump table.
3206 */
3207 ret = cdc_init (codec);
3208
3209 if (ret EQ ccdError)
3210 return ccdError;
3211
3212 #ifdef DEBUG_CCD
3213 if (ret EQ ccdWarning)
3214 {
3215 TRACE_CCD (globs, "CCD: Mismatch between CCD and CCDDATA. Check the codec list.");//return ccdWarning;
3216 }
3217 #endif
3218
3219 return ccdOK;
3220 }
3221 #endif /* !RUN_FLASH */
3222
3223 #ifndef RUN_FLASH
3224 /*
3225 +------------------------------------------------------------------------------
3226 | Function : ccd_signup
3227 +------------------------------------------------------------------------------
3228 | Description : This function sets up the local CCD data for the calling
3229 | entity.
3230 |
3231 | Parameters : ccd_reg - set if called by ccd_register, not set if called
3232 | by ccd_init
3233 | decmsgbuf_size - further enhancement: size of the entity's
3234 | decoded msg buffer size
3235 |
3236 | Return : ccdErr or ccdOK depending on the success
3237 +------------------------------------------------------------------------------
3238 */
3239
3240 static int ccd_signup (int ccd_reg, int decmsgbuf_size)
3241 {
3242 #ifndef _TOOLS_
3243 UBYTE ret;
3244 #endif
3245 #ifdef SHARED_CCD
3246 T_HANDLE me;
3247 #else
3248 int me = 0;
3249 #endif
3250 T_CCD_TASK_TABLE* tentry;
3251
3252 #ifdef SHARED_CCD
3253 me = vsi_e_handle (0, NULL);
3254 if (me == VSI_ERROR)
3255 {
3256 me = 0;
3257 tentry = ccd_task_list[0] = &task_null;
3258 task_null.ccd_globs = &globs_all;
3259 #ifdef DEBUG_CCD
3260 TRACE_CCD (&globs_all, "Ccd initialization: task could not be identified. Try to continue with a non reentrant init");
3261 #endif
3262 }
3263 else
3264 {
3265 if (!ccd_task_list[me])
3266 {
3267 ccd_task_list[me] = D_ALLOC (sizeof (T_CCD_TASK_TABLE));
3268 if (!ccd_task_list[me])
3269 {
3270 vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
3271 "Could not allocate memory for ccd task table entry" );
3272 }
3273 else
3274 {
3275 ccd_task_list[me]->ccd_globs = NULL;
3276 ccd_task_list[me]->ccd_err_list = NULL;
3277 ccd_task_list[me]->ccd_store = NULL;
3278 }
3279 }
3280 tentry = ccd_task_list[me];
3281 tentry->decmsgbuf = NULL;
3282 if (ccd_reg)
3283 {
3284 if (!tentry->ccd_globs)
3285 {
3286 if (decmsgbuf_size != CCD_REENTRANT)
3287 {
3288 #ifdef DEBUG_CCD
3289 TRACE_CCD (tentry->ccd_globs, "Ccd_register (task %d): ignore %d for parameter decmsgbuf_size. Make non reentrant ccd_init instead.", me, decmsgbuf_size);
3290 #endif
3291 tentry->ccd_globs = &globs_all;
3292 }
3293 else
3294 {
3295 tentry->ccd_globs = D_ALLOC (sizeof(T_CCD_Globs));
3296 if (!tentry->ccd_globs)
3297 {
3298 vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
3299 "Could not allocate memory for ccd_globs" );
3300 }
3301 }
3302 }
3303 }
3304 else
3305 {
3306 tentry->ccd_globs = &globs_all;
3307 }
3308 }
3309 #else /* SHARED_CCD */
3310 tentry = ccd_task_list[0] = &task_null;
3311 task_null.ccd_globs = &globs_all;
3312 #endif
3313
3314 tentry->ccd_globs->me = me;
3315 if (ccd_err_init (&tentry->ccd_err_list))
3316 {
3317 #ifdef CCD_TEST
3318 printf ("Cannot initialize error list: out of memory\n");
3319 #else /* CCD_TEST */
3320 vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
3321 "Cannot initialize error list: out of memory" );
3322 #endif /* CCD_TEST */
3323 return ccdError;
3324 }
3325
3326 if (ccd_store_init (&tentry->ccd_store))
3327 {
3328 #ifdef CCD_TEST
3329 printf ("Cannot initialize store register: out of memory\n");
3330 #else /* CCD_TEST */
3331 vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
3332 "Cannot initialize store register: out of memory" );
3333 #endif /* CCD_TEST */
3334 return ccdError;
3335 }
3336
3337 if (!initialized)
3338 {
3339 #ifdef SHARED_CCD
3340 /*
3341 * if the CCD is used in a premptive multithreaded system
3342 * we must create a semaphore for the coding and decoding
3343 */
3344 semCCD_Codec = vsi_s_open (VSI_CALLER "CCD_COD",1);
3345 semCCD_Buffer = vsi_s_open (VSI_CALLER "CCD_BUF",1);
3346
3347 #endif /* SHARED_CCD */
3348
3349 #ifndef _TOOLS_
3350 ret = (UBYTE)ccd_init_ccddata ();
3351 if (ret != ccdOK)
3352 return ret;
3353
3354 #endif /* !_TOOLS_ */
3355 initialized = TRUE;
3356 /* save memory init pattern */
3357 mempat = (U8*) CCDDATA_PREF(ccd_get_numFaults ());
3358 }
3359 return ccdOK;
3360 }
3361
3362 BYTE CCDDATA_PREF(ccd_init) (void)
3363 {
3364 return (BYTE) ccd_signup (0, 0);
3365 }
3366
3367 /*
3368 +------------------------------------------------------------------------------
3369 | Function : ccd_register
3370 +------------------------------------------------------------------------------
3371 | Description : This function sets up the local CCD data for the calling
3372 | entity.
3373 | Entities calling this function with a parameter 0 will
3374 | get an own set of CCD local data, i.e., they don't have to
3375 | synchronize with other entities to use CCD.
3376 |
3377 | Parameters : decmsgbuf_size - further enhancement: size of the entity's
3378 | decoded msg buffer size
3379 |
3380 | Return : ccdErr or ccdOK depending on the success
3381 +------------------------------------------------------------------------------
3382 */
3383
3384 int ccd_register (int decmsgbuf_size)
3385 {
3386 return ccd_signup (1, decmsgbuf_size);
3387 }
3388 #endif /* !RUN_FLASH */
3389
3390 #ifndef RUN_FLASH
3391 /*
3392 +--------------------------------------------------------------------+
3393 | PROJECT : CCD (6144) MODULE : CCD |
3394 | STATE : code ROUTINE : ccd_exit |
3395 +--------------------------------------------------------------------+
3396
3397 PURPOSE: performs a shutdown of CCD.
3398
3399 */
3400
3401 int CCDDATA_PREF(ccd_exit) (void)
3402 {
3403 #ifdef SHARED_CCD
3404 T_CCD_TASK_TABLE* tentry;
3405 T_HANDLE me = vsi_e_handle (0, NULL);
3406 if (me == VSI_ERROR)
3407 return ccdError;
3408 tentry = ccd_task_list[me];
3409 if (tentry->ccd_globs && (tentry->ccd_globs != &globs_all))
3410 {
3411 D_FREE (tentry->ccd_globs);
3412 tentry->ccd_globs = 0;
3413 }
3414 ccd_store_exit();
3415 ccd_err_exit ();
3416 D_FREE (ccd_task_list[me]);
3417 ccd_task_list[me] = NULL;
3418 #else
3419 ccd_store_exit();
3420 ccd_err_exit ();
3421 #endif /* SHARED_CCD */
3422 return ccdOK;
3423 }
3424 #endif /* !RUN_FLASH */