FreeCalypso > hg > freecalypso-sw
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 */ |