comparison gpf/frame/route.c @ 0:75a11d740a02

initial import of gsm-fw from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 00:02:41 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:75a11d740a02
1 /*
2 +------------------------------------------------------------------------------
3 | File: route.c
4 +------------------------------------------------------------------------------
5 | Copyright 2004 Texas Instruments Deutschland, AG
6 | All rights reserved.
7 |
8 | This file is confidential and a trade secret of Texas
9 | Instruments Berlin, AG
10 | The receipt of or possession of this file does not convey
11 | any rights to reproduce or disclose its contents or to
12 | manufacture, use, or sell anything it may describe, in
13 | whole, or in part, without the specific written consent of
14 | Texas Instruments Deutschland, AG.
15 +-----------------------------------------------------------------------------
16 | Purpose : This Modul performs the filtering and routing of
17 | primitives for testing capabilities of the protocol stack.
18 +-----------------------------------------------------------------------------
19 */
20
21 #ifndef __ROUTE_C__
22 #define __ROUTE_C__
23 #endif
24
25 /*==== INCLUDES ===================================================*/
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "gpfconf.h"
31 #include "typedefs.h"
32 #include "os.h"
33 #include "vsi.h"
34 #include "frame.h"
35 #include "tools.h"
36 #include "frm_defs.h"
37 #include "frm_types.h"
38 #include "frm_glob.h"
39 #include "p_mem.h"
40 #include "route.h"
41 #include "frm_ext.h"
42
43 /*==== CONSTANTS ==================================================*/
44
45 /*==== TYPES ======================================================*/
46
47 /*==== CONSTANTS ====================================================*/
48
49 /*==== EXTERNALS =====================================================*/
50
51 /* -------------- S H A R E D - BEGIN ---------------- */
52 #ifdef _TOOLS_
53 #pragma data_seg("FRAME_SHARED")
54 #endif
55
56 extern OS_HANDLE ext_data_pool_handle;
57 extern T_HANDLE TestGroupHandle;
58 extern T_FRM_ROUTING_TABLE_ENTRY *Routing[];
59 extern char TaskName[];
60 #ifndef _TOOLS_
61 extern T_lemu_SendToQueue lemu_SendToQueue_func;
62 #endif
63 /*==== VARIABLES ==================================================*/
64
65 #ifndef RUN_INT_RAM
66 T_HANDLE rt_tst_handle = VSI_ERROR;
67 #else
68 extern int rt_tst_handle;
69 #endif
70
71 #ifdef _TOOLS_
72 #pragma data_seg()
73 #endif
74 /* -------------- S H A R E D - END ---------------- */
75
76 #ifndef _TOOLS_
77 extern const T_MEM_PROPERTIES *mem;
78 #endif
79
80 /*==== FUNCTIONS ==================================================*/
81
82 #ifndef RUN_INT_RAM
83 /*
84 +--------------------------------------------------------------------+
85 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
86 | STATE : code ROUTINE : rt_Init |
87 +--------------------------------------------------------------------+
88
89 PURPOSE : initialize the routing table.
90 */
91
92 GLOBAL SHORT rt_Init (void)
93 {
94 USHORT i;
95 /*
96 * Initialize the routingTable
97 */
98 for ( i = 0; i <= MaxEntities; i++ )
99 Routing[i] = NULL;
100
101 return OS_OK;
102 }
103 #endif
104
105
106 #ifndef RUN_INT_RAM
107 /*
108 +--------------------------------------------------------------------+
109 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
110 | STATE : code ROUTINE : rt_CvrtOpcMask |
111 +--------------------------------------------------------------------+
112
113 PURPOSE : convert "1010101" mask to opcMask and opcStatus
114 */
115
116 LOCAL SHORT rt_CvrtToOpcMask ( char *OpcString, ULONG *opcMask, ULONG *opcStatus )
117 {
118 unsigned int len;
119 unsigned int i;
120 char *p;
121
122 len = strlen ( OpcString );
123 p = OpcString + len;
124
125 for ( i = 0; i < len; i++ )
126 {
127 switch (*--p)
128 {
129 case '1':
130 *opcMask |= (1<<i);
131 *opcStatus |= (1<<i);
132 break;
133 case '0':
134 *opcMask |= (1<<i);
135 *opcStatus &= ~((unsigned int)1<<i);
136 break;
137 case '*': /* wildcard matches */
138 *opcMask &= ~((unsigned int)1<<i);
139 *opcStatus &= ~((unsigned int)1<<i);
140 break;
141 default:
142 break;
143 }
144 }
145 return OS_OK;
146 }
147 #endif
148
149 #ifndef RUN_INT_RAM
150 /*
151 +--------------------------------------------------------------------+
152 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
153 | STATE : code ROUTINE : rt_CvrtOpcMask |
154 +--------------------------------------------------------------------+
155
156 PURPOSE : convert opcMask and opcStatus to "1010101"
157 */
158 LOCAL SHORT rt_CvrtFromOpcMask ( char *OpcString, ULONG opcMask, ULONG opcStatus )
159 {
160 signed char i;
161 char len;
162
163 if ( opcMask >> 16 )
164 len = 32;
165 else
166 len = 16;
167 for ( i = len-1; i >= 0; i-- )
168 {
169 if ( opcMask & (1<<i) )
170 {
171 if ( opcStatus & (1<<i) )
172 *OpcString = '1';
173 else
174 *OpcString = '0';
175 }
176 else
177 *OpcString = '*';
178 OpcString++;
179 }
180 *(OpcString++) = ' ';
181 *(OpcString++) = 0;
182
183 return OS_OK;
184 }
185 #endif
186
187 #ifndef RUN_INT_RAM
188 /*
189 +--------------------------------------------------------------------+
190 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
191 | STATE : code ROUTINE : rt_ReadRouting |
192 +--------------------------------------------------------------------+
193
194 PURPOSE : reads all routings of the routing table of the task.
195 */
196
197 GLOBAL SHORT rt_RouteRead ( T_HANDLE Handle, char *Buffer )
198 {
199 T_HANDLE TstComHandle;
200 static T_FRM_ROUTING_TABLE_ENTRY *pEntry;
201 char OrgReceiver[ RESOURCE_NAMELEN ];
202 char NewReceiver[ RESOURCE_NAMELEN ];
203 char OpcString [18];
204 char const *pCmd;
205 static UBYTE FirstRead = 1;
206
207 if ( FirstRead )
208 {
209 FirstRead = 0;
210 pEntry = Routing[Handle];
211 }
212 if ( pEntry )
213 {
214 if ( pEntry->OldDestComHandle == ROUTE_ALL )
215 strcpy ( OrgReceiver, RT_ALL_TOKEN );
216 else
217 strcpy ( OrgReceiver, pf_TaskTable[pEntry->OldDestComHandle].Name );
218 TstComHandle = vsi_c_open ( Handle, FRM_TST_NAME );
219 if ( pEntry->NewDestComHandle == TstComHandle )
220 strcpy ( NewReceiver, pEntry->ExtDest );
221 else
222 {
223 if ( pEntry->NewDestComHandle != 0 )
224 strcpy ( NewReceiver, pf_TaskTable[pEntry->NewDestComHandle].Name );
225 }
226 if ( pEntry->opcMask )
227 rt_CvrtFromOpcMask ( OpcString, pEntry->opcMask, pEntry->opcStatus );
228 else
229 OpcString[0] = 0;
230
231 switch (pEntry->Command & RT_COMMAND_MASK)
232 {
233 case RT_DUPLICATE: pCmd = SYSPRIM_DUPLICATE_TOKEN;
234 break;
235 case RT_REDIRECT: pCmd = SYSPRIM_REDIRECT_TOKEN;
236 break;
237 case RT_DESTROY: pCmd = SYSPRIM_REDIRECT_TOKEN;
238 strcpy ( NewReceiver, SYSPRIM_NULL_TOKEN );
239 break;
240 default: pCmd = NULL;
241 break;
242 }
243 sprintf ( Buffer, "%s %s %s %s%s", pf_TaskTable[Handle].Name, pCmd, OrgReceiver, OpcString, NewReceiver );
244 pEntry = pEntry->pNextEntry;
245 return RT_OK;
246 }
247 else
248 {
249 FirstRead = 1;
250 pEntry = Routing[Handle];
251 return RT_ERROR;
252 }
253 }
254 #endif
255
256 #ifndef RUN_INT_RAM
257 /*
258 +--------------------------------------------------------------------+
259 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
260 | STATE : code ROUTINE : rt_RoutingEntry |
261 +--------------------------------------------------------------------+
262
263 PURPOSE : adds a new routing to the routing table of the task.
264 routings with duplicates are stored in the beginning
265 of the table because if the primitive is redirected and
266 send it can not be duplicated.
267 */
268
269 LOCAL SHORT rt_RoutingEntry ( T_HANDLE SndTaskHandle, T_FRM_ROUTING_TABLE_ENTRY *pNewEntry, RT_ENTRY Status )
270 {
271 T_FRM_ROUTING_TABLE_ENTRY *pEntry, *pNextEntry, *pPrevEntry;
272
273 /*
274 * delete all entries with same OldDestComHandle if a destroy command is stored
275 */
276 if ( pNewEntry->Command & RT_DESTROY )
277 {
278 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
279 {
280 do
281 {
282 if ( pEntry->OldDestComHandle == pNewEntry->OldDestComHandle )
283 {
284 if ( pEntry == Routing[SndTaskHandle] )
285 {
286 if ( pEntry->pNextEntry )
287 {
288 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
289 }
290 Routing[SndTaskHandle] = pEntry->pNextEntry;
291 }
292 else
293 {
294 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
295 if ( pEntry->pNextEntry )
296 {
297 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
298 }
299 }
300 pNextEntry = pEntry->pNextEntry;
301 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
302 }
303 else
304 pNextEntry = pEntry->pNextEntry;
305
306 pEntry = pNextEntry;
307 }
308 while ( pEntry );
309 }
310 }
311 else
312 {
313 /*
314 * delete destroy command for OldDestComHandle if a new command is stored
315 */
316 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
317 {
318 do
319 {
320 if ( pEntry->OldDestComHandle == pNewEntry->OldDestComHandle )
321 {
322 if ( pEntry->Command == RT_DESTROY )
323 {
324 if ( pEntry == Routing[SndTaskHandle] )
325 {
326 if ( pEntry->pNextEntry )
327 {
328 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
329 }
330 Routing[SndTaskHandle] = pEntry->pNextEntry;
331 }
332 else
333 {
334 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
335 if ( pEntry->pNextEntry )
336 {
337 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
338 }
339 }
340 pNextEntry = pEntry->pNextEntry;
341 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
342 }
343 break;
344 }
345 else
346 pNextEntry = pEntry->pNextEntry;
347
348 pEntry = pNextEntry;
349 }
350 while ( pEntry );
351 }
352 }
353
354
355 if ( (pEntry = Routing[SndTaskHandle]) != NULL )
356 {
357 do
358 {
359 if ( pEntry->SndTaskHandle == SndTaskHandle
360 && pEntry->NewDestComHandle == pNewEntry->NewDestComHandle
361 && pEntry->OldDestComHandle == pNewEntry->OldDestComHandle
362 && pEntry->MsgType == pNewEntry->MsgType )
363 {
364 if ( !strcmp (pEntry->ExtDest, pNewEntry->ExtDest) )
365 {
366 if ( Status == RT_DELETE )
367 {
368 if ( pEntry == Routing[SndTaskHandle] )
369 {
370 Routing[SndTaskHandle] = pEntry->pNextEntry;
371 if ( pEntry->pNextEntry )
372 {
373 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
374 }
375 }
376 else
377 {
378 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
379 if ( pEntry->pNextEntry )
380 {
381 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
382 }
383 }
384 pNextEntry = pEntry->pNextEntry;
385 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
386 return RT_OK;
387 }
388 #ifndef _TOOLS_
389 else
390 {
391 pEntry->Command = pNewEntry->Command; /* modify command for old routing entry */
392 pEntry->opcMask = pNewEntry->opcMask; /* set new opcMask in old routing entry */
393 pEntry->opcStatus = pNewEntry->opcStatus; /* set new opcStatus in old routing entry */
394 return RT_OK;
395 }
396 #else
397 pEntry = pEntry->pNextEntry;
398 #endif
399 }
400 else
401 {
402 #ifdef _TOOLS_
403 if ( ( pEntry->opcMask == pNewEntry->opcMask )
404 && ( pEntry->opcStatus == pNewEntry->opcStatus ) )
405 {
406 strcpy ( pEntry->ExtDest, pNewEntry->ExtDest );
407 return RT_OK;
408 }
409 else
410 #endif
411 pEntry = pEntry->pNextEntry;
412 }
413 }
414 else
415 pEntry = pEntry->pNextEntry;
416 } while ( pEntry );
417 }
418
419 pPrevEntry = NULL;
420 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
421 {
422 do
423 {
424 pPrevEntry = pEntry;
425 if ( pNewEntry->Command & RT_DUPLICATE )/* put Duplications at the end of Duplications */
426 {
427 if ( pEntry->Command & RT_DUPLICATE )
428 pEntry = pEntry->pNextEntry;
429 else
430 {
431 if ( pPrevEntry == Routing[SndTaskHandle] )
432 pPrevEntry = NULL;
433 else
434 pPrevEntry = pEntry->pPrevEntry;
435 break;
436 }
437 }
438 else
439 pEntry = pEntry->pNextEntry;
440 }
441 while ( pEntry );
442 }
443 if ( os_AllocateMemory ( SndTaskHandle, (T_VOID_STRUCT**)&pNextEntry, sizeof(T_FRM_ROUTING_TABLE_ENTRY), OS_NO_SUSPEND, ext_data_pool_handle ) == OS_TIMEOUT )
444 return RT_NO_MEM;
445 pNextEntry->SndTaskHandle = SndTaskHandle;
446 pNextEntry->OldDestComHandle = pNewEntry->OldDestComHandle;
447 pNextEntry->NewDestComHandle = pNewEntry->NewDestComHandle;
448 pNextEntry->OldDestTaskHandle = pNewEntry->OldDestTaskHandle;
449 pNextEntry->Command = pNewEntry->Command;
450 pNextEntry->MsgType = pNewEntry->MsgType;
451 pNextEntry->opcMask = pNewEntry->opcMask;
452 pNextEntry->opcStatus = pNewEntry->opcStatus;
453 strcpy ( pNextEntry->ExtDest, pNewEntry->ExtDest );
454
455 if ( pEntry )
456 {
457 pEntry->pPrevEntry = pNextEntry; /* store at the beginning/in the list */
458 }
459 else
460 pNextEntry->pNextEntry = NULL; /* append to the list */
461
462 if ( pPrevEntry )
463 {
464 pPrevEntry->pNextEntry = pNextEntry; /* store in the list */
465 pNextEntry->pPrevEntry = pPrevEntry;
466 pNextEntry->pNextEntry = pEntry;
467 }
468 else
469 {
470 Routing[SndTaskHandle] = pNextEntry; /* store at the beginning */
471 pNextEntry->pNextEntry = pEntry;
472 }
473 return RT_OK;
474 }
475 #endif
476
477 #if 0
478 /* not needed -> temporarily removed */
479 #ifndef RUN_INT_RAM
480 /*
481 +--------------------------------------------------------------------+
482 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
483 | STATE : code ROUTINE : rt_ModifyRouting |
484 +--------------------------------------------------------------------+
485
486 PURPOSE : handle the contents of the redirection or duplicate
487 system primitive
488
489 */
490 GLOBAL SHORT rt_isolate_entity ( T_HANDLE caller, char *entity )
491 {
492 T_FRM_ROUTING_TABLE_ENTRY entry;
493 T_HANDLE snd;
494 T_HANDLE rcv;
495 int read_entry = FIRST_ENTRY;
496
497 if ( (rcv = vsi_e_handle ( caller, entity )) == VSI_ERROR )
498 return RT_ERROR;
499 else
500 {
501 while ( vsi_c_get_entity_com_entry ( read_entry, rcv, &snd ) == VSI_OK )
502 {
503 read_entry = NEXT_ENTRY;
504 entry.SndTaskHandle = snd;
505 entry.OldDestComHandle = rcv;
506 entry.NewDestComHandle = 0;
507 entry.opcMask = 0;
508 entry.MsgType = RT_PRIMITIVE_TYPE;
509 entry.Command = RT_DESTROY;
510 rt_RoutingEntry ( snd, &entry, RT_STORE );
511 }
512
513 entry.SndTaskHandle = rcv;
514 entry.OldDestComHandle = ROUTE_ALL;
515 entry.NewDestComHandle = 0;
516 entry.opcMask = 0;
517 entry.MsgType = RT_PRIMITIVE_TYPE;
518 entry.Command = RT_DESTROY;
519 rt_RoutingEntry ( rcv, &entry, RT_STORE );
520
521 return RT_OK;
522 }
523 }
524 #endif
525 #endif
526
527 #ifndef RUN_INT_RAM
528 /*
529 +--------------------------------------------------------------------+
530 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
531 | STATE : code ROUTINE : rt_ModifyRouting |
532 +--------------------------------------------------------------------+
533
534 PURPOSE : handle the contents of the redirection or duplicate
535 system primitive
536
537 */
538 GLOBAL SHORT rt_RoutingModify ( T_HANDLE SndTaskHandle, char *Command, char *RoutingString)
539 {
540 char Token[81];
541 char *pChar = RoutingString;
542 T_FRM_ROUTING_TABLE_ENTRY Entry = { 0 };
543 unsigned int len;
544 T_FRM_ROUTING_TABLE_ENTRY *pEntry, *pNextEntry;
545
546 if ( !strcmp (Command, SYSPRIM_DUPLICATE_TOKEN) )
547 Entry.Command = RT_DUPLICATE;
548
549 if ( !strcmp (Command, SYSPRIM_REDIRECT_TOKEN) )
550 Entry.Command = RT_REDIRECT;
551
552 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
553 return RT_ERROR;
554 else
555 pChar += (len+1);
556
557 if ( !strcmp (Token, RT_CLEAR_TOKEN) )
558 Entry.Command |= RT_CLEAR_ENTRY;
559
560 if ( !strcmp (Token, RT_ALL_TOKEN) )
561 Entry.Command |= RT_ALL_DESTINATION;
562
563 if ( Entry.Command & RT_CLEAR_ENTRY )
564 {
565 if ( (pEntry = Routing[SndTaskHandle]) != NULL )
566 {
567 do
568 {
569 pNextEntry = (T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry;
570 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
571 pEntry = pNextEntry;
572 }
573 while ( pEntry );
574 Routing[SndTaskHandle] = NULL;
575 }
576 return RT_OK;
577 }
578
579 if ( Entry.Command & RT_ALL_DESTINATION )
580 {
581 Entry.OldDestComHandle = ROUTE_ALL;
582 Entry.OldDestTaskHandle = ROUTE_ALL;
583 }
584 else
585 {
586 if ( ( Entry.OldDestComHandle = vsi_c_open (SndTaskHandle, Token ) ) == VSI_ERROR )
587 return RT_ERROR;
588 Entry.OldDestTaskHandle = Entry.OldDestComHandle;
589 }
590
591 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
592 return RT_ERROR;
593 else
594 pChar += (len+1);
595
596 if ( !strcmp (Token, RT_TIMEOUT_TOKEN) )
597 {
598 Entry.MsgType = RT_TIMEOUT_TYPE;
599 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
600 return RT_ERROR;
601 else
602 pChar += (len+1);
603
604 }
605 else
606 {
607 if ( !strcmp (Token, RT_SIGNAL_TOKEN) )
608 {
609 Entry.MsgType = RT_SIGNAL_TYPE;
610 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
611 return RT_ERROR;
612 else
613 pChar += (len+1);
614 }
615 else
616 Entry.MsgType = RT_PRIMITIVE_TYPE;
617 }
618
619 if ( (Token[0] == '1') || (Token[0] == '0') || (Token[0] == '*') )
620 {
621 rt_CvrtToOpcMask(Token, &Entry.opcMask, &Entry.opcStatus);
622 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
623 return RT_ERROR;
624 else
625 pChar += (len+1);
626 }
627 /* else */
628 {
629 if (!strcmp (Token, SYSPRIM_NULL_TOKEN))
630 {
631 if ( Entry.Command & RT_REDIRECT )
632 {
633 Entry.Command |= RT_DESTROY; /* destroy the primitive */
634 Entry.Command &= ~RT_REDIRECT;
635 }
636 else
637 return RT_ERROR;
638 }
639 else
640 {
641 if ( ( Entry.NewDestComHandle = vsi_c_open (SndTaskHandle, Token ) ) == VSI_ERROR )
642 {
643 #ifdef _TOOLS_
644 if ( !strcmp ( FRM_PCO_NAME, Token ) )
645 return RT_ERROR;
646 #endif
647 if ( ( Entry.NewDestComHandle = vsi_c_open (SndTaskHandle, FRM_TST_NAME ) ) != VSI_ERROR )
648 {
649 rt_tst_handle = Entry.NewDestComHandle;
650 if ( len < RESOURCE_NAMELEN )
651 {
652 strncpy( Entry.ExtDest, Token, RESOURCE_NAMELEN );
653 Entry.ExtDest[RESOURCE_NAMELEN-1] = 0;
654 }
655 else
656 return RT_ERROR;
657 }
658 }
659 }
660
661 if ( Entry.Command & RT_ALL_DESTINATION )
662 {
663 if ( (pEntry = Routing[SndTaskHandle]) != NULL )
664 {
665 int all_cleared = 1;
666 do
667 {
668 pNextEntry = (T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry;
669 if ( (pEntry->NewDestComHandle == Entry.NewDestComHandle )
670 && !strcmp(pEntry->ExtDest, Entry.ExtDest) )
671 {
672 if ( pEntry == Routing[SndTaskHandle] )
673 {
674 Routing[SndTaskHandle] = pEntry->pNextEntry;
675 if ( pEntry->pNextEntry != NULL )
676 {
677 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
678 }
679 }
680 else
681 {
682 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
683 if ( pEntry->pNextEntry != NULL )
684 {
685 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
686 }
687 }
688 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
689 }
690 else
691 {
692 all_cleared = 0;
693 }
694 pEntry = pNextEntry;
695 }
696 while ( pEntry );
697 if ( all_cleared == 1 )
698 Routing[SndTaskHandle] = NULL;
699 }
700 }
701
702 if ( (pChar >= RoutingString+ strlen (RoutingString))
703 || ((len = GetNextToken (pChar, Token, " #")) == 0) )
704 return ( rt_RoutingEntry(SndTaskHandle, &Entry, RT_STORE) );
705 else
706 pChar += (len+1);
707
708 if ( Entry.Command & RT_CLEAR_ENTRY )
709 return ( rt_RoutingEntry(SndTaskHandle, &Entry, RT_DELETE) );
710 return RT_ERROR;
711 }
712
713 }
714 #endif
715
716 #ifndef RUN_FLASH
717 /*
718 +--------------------------------------------------------------------+
719 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
720 | STATE : code ROUTINE : rt_routePrim |
721 +--------------------------------------------------------------------+
722
723 PURPOSE : Looks if the task have some routing rules stored and
724 perform the redirection or duplication.
725
726 */
727
728 GLOBAL SHORT rt_Route ( T_HANDLE SndTaskHandle, T_HANDLE RcvComHandle, USHORT Prio, ULONG Suspend, OS_QDATA *Msg )
729 {
730 T_FRM_ROUTING_TABLE_ENTRY *pEntry;
731
732 T_PRIM_HEADER *prim;
733 ULONG opc;
734
735 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
736 {
737 if ( pEntry->MsgType == Msg->data16 )
738 {
739 prim = (T_PRIM_HEADER*)Msg->ptr;
740
741 #ifndef _TOOLS_
742 if (prim->opc & MEMHANDLE_OPC)
743 {
744 P_MEMHANDLE_SDU(prim)=0x00000000;
745 }
746 #endif
747
748 do
749 {
750 if ( SndTaskHandle == pEntry->SndTaskHandle
751 && ( (RcvComHandle == pEntry->OldDestComHandle) || (pEntry->OldDestComHandle == ROUTE_ALL) ) )
752 {
753 /*
754 * a route for the receiver is defined. Now
755 * check the filter conditions
756 */
757 opc = ((T_PRIM_HEADER*)Msg->ptr)->opc;
758 if ( (opc & pEntry->opcMask) == (pEntry->opcStatus & pEntry->opcMask) )
759 {
760 /*
761 * filter matched -> redirect, duplicate or destroy
762 * the primitive.
763 */
764 switch (pEntry->Command & RT_COMMAND_MASK)
765 {
766 case RT_DESTROY:
767 /* add VSI_PPM_FREE(Msg->ptr) just to avoid the PPM warning of freeing a primitive in a queue */
768 VSI_PPM_RCV(Msg->ptr);
769 VSI_PPM_FREE(Msg->ptr);
770 os_DeallocatePartition (SndTaskHandle, Msg->ptr-PPM_OFFSET );
771 return RT_OK;
772
773 case RT_REDIRECT:
774 #ifndef _TOOLS_
775 if (pEntry->NewDestComHandle != rt_tst_handle)
776 {
777 /* if not on tool side and not sending via TST -> send directly */
778 Msg->e_id = pEntry->NewDestComHandle;
779 return ( (SHORT)os_SendToQueue ( SndTaskHandle, pf_TaskTable[pEntry->NewDestComHandle].QueueHandle, OS_NORMAL, OS_SUSPEND, Msg ) );
780 }
781 #endif
782 /*lint -fallthrough */
783 case RT_DUPLICATE:
784 if (pEntry->NewDestComHandle != OS_ERROR)
785 {
786 OS_QDATA QData;
787 #ifdef _TOOLS_
788 QData.len = (USHORT)(PSIZE(P2D(Msg->ptr))-sizeof(T_PRIM_HEADER));
789 #else
790 /* QData.len = 4; not needed if per reference */
791 T_DP_HEADER *dp_hdr;
792 #if 0
793 P_ATTACH(P2D(prim)); /* recursivly increase use counters */
794 #else
795 prim->use_cnt++;
796 if ( prim->dph_offset != 0 )
797 {
798 dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
799 /* only increment use_cnt for dynamic primitives - not for DTI primitives */
800 if ( dp_hdr->magic_nr == GUARD_PATTERN )
801 {
802 do
803 {
804 dp_hdr->use_cnt++;
805 } while ( (dp_hdr = (T_DP_HEADER*)dp_hdr->next) != NULL );
806 }
807 }
808 #endif /* 0 */
809
810 #endif
811 QData.data16 = MSG_PRIMITIVE;
812 QData.ptr = Msg->ptr;
813
814 #ifndef _TOOLS_
815 if (pEntry->NewDestComHandle != rt_tst_handle)
816 {
817 Msg->e_id = pEntry->NewDestComHandle;
818 os_SendToQueue ( SndTaskHandle, pf_TaskTable[pEntry->NewDestComHandle].QueueHandle, OS_NORMAL, OS_SUSPEND, Msg );
819 }
820 else
821 #endif
822 {
823 /* if on tool side or sending via TST -> send with sys header a.s.o */
824 rt_ExtPrimitive ( SndTaskHandle, pEntry->NewDestComHandle, RcvComHandle, pEntry->ExtDest, &QData );
825 }
826 }
827 if ( pEntry->Command & RT_REDIRECT )
828 {
829 T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
830
831 #ifndef _TOOLS_
832 if ((prim->opc & MEMHANDLE_OPC) && (mem!=NULL))
833 {
834 if (P_MEMHANDLE(prim)!=0)
835 {
836 mem->dealloc(P_MEMHANDLE(prim));
837 }
838 }
839 #endif /* !_TOOLS_ */
840
841 vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
842 return RT_OK;
843 }
844 break;
845 default:
846 break;
847 }
848 }
849 }
850 pEntry = pEntry->pNextEntry;
851 } while ( pEntry );
852 }
853 }
854
855 /*
856 * send original
857 */
858
859 #ifdef _TOOLS_
860 return ( (SHORT)os_SendToQueue ( SndTaskHandle, RcvComHandle, Prio, Suspend, Msg ) );
861 #else
862 if((pf_TaskTable[RcvComHandle].Flags & USE_LEMU_QUEUE) AND
863 (lemu_SendToQueue_func.magic_nr == LEMU_SENDTOQUEUE_INITIALIZED))
864 {
865 if(lemu_SendToQueue_func.plemu_SendToQueue( SndTaskHandle, RcvComHandle,
866 pf_TaskTable[RcvComHandle].QueueHandle, Prio, Suspend, Msg )
867 != lemu_SendToQueue_func.ret_ok )
868 {
869 return OS_ERROR;
870 }
871 return OS_OK;
872 }
873 else
874 {
875 return ( (SHORT)os_SendToQueue ( SndTaskHandle, pf_TaskTable[RcvComHandle].QueueHandle, Prio, Suspend, Msg ) );
876 }
877 #endif
878 }
879 #endif
880
881 #ifndef RUN_INT_RAM
882 /*
883 +--------------------------------------------------------------------+
884 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
885 | STATE : code ROUTINE : rt_ExtPrimitive |
886 +--------------------------------------------------------------------+
887
888 PURPOSE : formats duplicated primitive to be sent to TST
889
890 */
891 void rt_ExtPrimitive ( T_HANDLE TaskHandle, T_HANDLE DestComHandle, T_HANDLE OrgDestTaskHandle, char *ExtDest, OS_QDATA *Msg )
892 {
893 T_PRIM_HEADER *prim;
894 #ifndef _TOOLS_
895 T_PRIM_HEADER *sdu_prim;
896 #endif /* not _TOOLS_ */
897 T_PRIM_HEADER *ptr;
898 T_S_HEADER *s_hdr;
899 OS_QDATA DMsg;
900 ULONG AllocSize;
901 LONG Status;
902 ULONG suspend;
903 #ifdef _TOOLS_
904 T_S_HEADER *prim_s_hdr;
905 unsigned int i;
906 #endif
907
908 prim = (T_PRIM_HEADER*)Msg->ptr;
909 #ifdef _TOOLS_
910 AllocSize = S_ALLOC_SIZE(Msg->len + 1); /* +1 To add LF in TIF */
911 #else
912 if ( prim->dph_offset != 0 )
913 {
914 T_DP_HEADER *dp_hdr;
915
916 dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
917 if ( dp_hdr->magic_nr != GUARD_PATTERN
918 #ifdef _TARGET_
919 && route_desclist[TaskHandle] == TRUE
920 #endif
921 )
922 {
923 rt_desclist_to_sdu ( TaskHandle, DestComHandle, prim, &sdu_prim );
924 prim = sdu_prim;
925 }
926 }
927
928 AllocSize = S_ALLOC_SIZE(4 + 1); /* only ptr to primitive */
929 #endif /* _TOOLS_ */
930 suspend = get_suspend_state(TaskHandle,CHECK_PRIM_SUSPEND);
931 Status = os_AllocatePartition ( TaskHandle, (T_VOID_STRUCT**)&ptr, AllocSize, suspend, TestGroupHandle );
932 if ( Status == OS_OK || Status == OS_WAITED || Status == OS_ALLOCATED_BIGGER )
933 {
934 DMsg.data16 = MSG_PRIMITIVE;
935 DMsg.data32 = Msg->data32;
936 #ifdef _TOOLS_
937 DMsg.len = AllocSize;
938 #endif
939 DMsg.ptr = (T_VOID_STRUCT*)ptr;
940
941 ptr->opc = prim->opc;
942 ptr->len = AllocSize;
943 ptr->sh_offset = S_HDR_OFFSET(AllocSize - sizeof(T_S_HEADER));
944 s_hdr = (T_S_HEADER*)((ULONG*)ptr + ptr->sh_offset);
945 #ifdef _TOOLS_
946 if ( prim->sh_offset == 0 )
947 {
948 /*
949 if the primitive is sent via the TAP REDIRECT TAP ... mechanism, then the prim->sh_offset
950 is zero and the org_rcv is filled corresponding to the original addressed entity name.
951 */
952 vsi_e_name ( TaskHandle, OrgDestTaskHandle, TaskName );
953 strcpy (s_hdr->org_rcv, TaskName);
954 strcpy (s_hdr->rcv, ExtDest);
955 }
956 else
957 {
958 /*
959 if the primitive is sent via the TAP TPORT mechanism then the original receiver is already
960 filled by the TAP and copied to the newly allocated primitive to be routed.
961 */
962 prim_s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset);
963
964 for (i = 0; prim_s_hdr->org_rcv[i] != 0 && i < sizeof (s_hdr->org_rcv)-1; i++)
965 s_hdr->org_rcv[i] = prim_s_hdr->org_rcv[i];
966 for (i = 0; prim_s_hdr->rcv[i] != 0 && i < sizeof (s_hdr->rcv)-1; i++)
967 s_hdr->rcv[i] = prim_s_hdr->rcv[i];
968 }
969 get_local_time (&s_hdr->time);
970 os_GetTaskName ( TaskHandle, TaskHandle, TaskName );
971 strcpy (s_hdr->snd, TaskName);
972 #else
973 vsi_e_name ( TaskHandle, OrgDestTaskHandle, TaskName );
974 strcpy (s_hdr->org_rcv, TaskName);
975 strcpy (s_hdr->rcv, ExtDest);
976 os_GetTime(TaskHandle,&s_hdr->time);
977 s_hdr->snd[0] = (char)(TaskHandle | HANDLE_BIT);
978 #endif
979 #ifdef _TOOLS_
980 memcpy ( (char*)P2D(ptr), P2D(Msg->ptr), Msg->len );
981 #else
982 ((T_PRIM_X*)(ptr))->prim_ptr = prim;
983 #endif
984 DMsg.e_id = DestComHandle;
985 #ifdef _TOOLS_
986 os_SendToQueue ( TaskHandle, DestComHandle, OS_NORMAL, OS_SUSPEND, &DMsg );
987 #else
988 if ((prim->opc & MEMHANDLE_OPC) && (mem!=NULL))
989 {
990 if (P_MEMHANDLE_SDU(prim)==0x00000000)
991 {
992 /* copy MEM-handle content into new sdu */
993 U8 *user_data;
994 U16 ptr_length;
995 user_data=mem->get_user_data(P_MEMHANDLE(prim), &ptr_length);
996
997 if (user_data)
998 {
999 T_sdu *sdu=(T_sdu *)M_ALLOC(ptr_length+2*sizeof(U16));
1000
1001 sdu->l_buf=ptr_length*8;
1002 sdu->o_buf=0;
1003 memcpy(sdu->buf,user_data,ptr_length);
1004
1005 P_MEMHANDLE_SDU(prim)=(U32)sdu;
1006 }
1007 }
1008 else
1009 {
1010 M_ATTACH((void*)P_MEMHANDLE_SDU(prim));
1011 }
1012 }
1013
1014 if ( PrimAborted[TaskHandle] > 0 )
1015 {
1016 if ( vsi_o_ttrace ( 0, TC_SYSTEM, "%d %s primitive routings aborted",PrimAborted[TaskHandle], pf_TaskTable[TaskHandle].Name ) == VSI_OK )
1017 PrimAborted[TaskHandle] = 0;
1018 }
1019 if ( os_SendToQueue ( TaskHandle, pf_TaskTable[DestComHandle].QueueHandle, OS_NORMAL, suspend, &DMsg ) == OS_TIMEOUT )
1020 {
1021 T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
1022 vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
1023 vsi_trc_free (0, (T_VOID_STRUCT**)&ptr);
1024 PrimAborted[TaskHandle]++;
1025 }
1026 #endif
1027 }
1028 else
1029 {
1030 T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
1031 vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
1032 PrimAborted[TaskHandle]++;
1033 }
1034 }
1035 #endif
1036
1037 #ifndef RUN_INT_RAM
1038 /*
1039 +--------------------------------------------------------------------+
1040 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
1041 | STATE : code ROUTINE : rt_desclist_to_sdu |
1042 +--------------------------------------------------------------------+
1043
1044 PURPOSE : formats duplicated primitive with descriptor list into a
1045 primitive with SDU
1046
1047 */
1048 int rt_desclist_to_sdu ( T_HANDLE caller, T_HANDLE dst, T_PRIM_HEADER *prim, T_PRIM_HEADER **sdu_prim )
1049 {
1050 T_PRIM_HEADER *ptr;
1051 T_DP_HEADER *dp_hdr;
1052 T_M_HEADER *m_hdr;
1053 T_desc3 *desc3;
1054 T_desc2 *desc2;
1055 T_desc *desc;
1056 int len = 0;
1057 int sdu_prim_size = 0;
1058 char *fill_ptr;
1059 USHORT *l_buf_ptr;
1060 USHORT *o_buf_ptr;
1061 char *sdu_data_ptr;
1062 T_sdu *sdu = NULL;
1063 unsigned int new_opc;
1064 int desc_type = 0;
1065
1066 dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
1067 /* primitive contains descriptor list */
1068
1069 /*
1070 START OF NON GENERIC CODE
1071 This code is for the phase 1 routing of primitives containing descriptor lists.
1072 It is non-generic and depends on the primitive ids defined in SAP docs.
1073 It should be removed as soon as the generic descriptor list routing is ready
1074 */
1075 switch ( prim->opc )
1076 {
1077 case 0x7754: /* DTI2_DATA_IND */
1078 new_opc = 0x7755; /* DTI2_DATA_TEST_IND */
1079 desc_type = VSI_DESC_TYPE2 >> 16;
1080 break;
1081 case 0x3754: /* DTI2_DATA_REQ */
1082 new_opc = 0x3755; /* DTI2_DATA_TEST_REQ */
1083 desc_type = VSI_DESC_TYPE2 >> 16;
1084 break;
1085 case 0x6800: /* SN_DATA_IND */
1086 new_opc = 0x6806; /* SN_DATA_TEST_IND */
1087 desc_type = VSI_DESC_TYPE2 >> 16;
1088 break;
1089 case 0x2800: /* SN_DATA_REQ */
1090 new_opc = 0x2806; /* SN_DATA_TEST_REQ */
1091 desc_type = VSI_DESC_TYPE2 >> 16;
1092 break;
1093 case 0x6801: /* SN_UNITDATA_IND */
1094 new_opc = 0x6807; /* SN_DATA_TEST_IND */
1095 desc_type = VSI_DESC_TYPE2 >> 16;
1096 break;
1097 case 0x2801: /* SN_UNITDATA_REQ */
1098 new_opc = 0x2807; /* SN_DATA_TEST_REQ */
1099 desc_type = VSI_DESC_TYPE2 >> 16;
1100 break;
1101 case 0x7701: /* DTI_DATA_IND */
1102 new_opc = 0x7702; /* DTI_DATA_TEST_IND */
1103 desc_type = VSI_DESC_TYPE1 >> 16;
1104 break;
1105 case 0x3701: /* DTI_DATA_REQ */
1106 new_opc = 0x3702; /* DTI_DATA_TEST_REQ */
1107 desc_type = VSI_DESC_TYPE1 >> 16;
1108 break;
1109 case 0x80004097: /* GRLC_DATA_IND */
1110 new_opc = 0x80014097; /* GRLC_DATA_IND_TEST */
1111 desc_type = VSI_DESC_TYPE1 >> 16;
1112 break;
1113 case 0x80024097: /* GRLC_UNITDATA_IND */
1114 new_opc = 0x80034097; /* GRLC_UNITDATA_IND_TEST */
1115 desc_type = VSI_DESC_TYPE1 >> 16;
1116 break;
1117 default:
1118 new_opc = prim->opc;
1119 break;
1120 }
1121 /* END OF NON GENERIC CODE */
1122
1123 /*
1124 it has to be distinguished between T_desc, T_desc2 and T_desc3 because to length information
1125 is located at different places inside the structure
1126 */
1127 m_hdr = (T_M_HEADER*)(((T_desc_list*)dp_hdr)->first) - 1;
1128 if ( m_hdr->desc_type != 0 )
1129 {
1130 desc_type = m_hdr->desc_type;
1131 }
1132 if ( desc_type == (VSI_DESC_TYPE2 >> 16) )
1133 {
1134 desc2 = (T_desc2*)(((T_desc_list2*)dp_hdr)->first);
1135 while (desc2 != NULL)
1136 {
1137 len = len + desc2->len;
1138 desc2 = (T_desc2 *)desc2->next;
1139 }
1140 /* the size to be allocated for the primitive containing the sdu needs to be
1141 root prim length + data length + sdu size minus data buffer - desc list2 size */
1142 sdu_prim_size = prim->len + len + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list2);
1143 }
1144 else if ( desc_type == (VSI_DESC_TYPE1 >> 16) )
1145 {
1146 desc = (T_desc*)(((T_desc_list*)dp_hdr)->first);
1147 while (desc != NULL)
1148 {
1149 len = len + desc->len;
1150 desc = (T_desc *)desc->next;
1151 }
1152 /* the size to be allocated for the primitive containing the sdu needs to be
1153 root prim length + data length + sdu size minus data buffer - desc list size */
1154 sdu_prim_size = prim->len + len + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list);
1155 }
1156 else if ( desc_type == (VSI_DESC_TYPE3 >> 16) )
1157 {
1158 /* it is assumed that type 3 is valid if not 1 or 2 */
1159 desc3 = (T_desc3*)(((T_desc_list3*)dp_hdr)->first);
1160 while (desc3 != NULL)
1161 {
1162 len = len + desc3->len;
1163 desc3 = (T_desc3 *)desc3->next;
1164 }
1165 /* the size to be allocated for the primitive containing the sdu needs to be
1166 root prim length + data length + sdu size minus data buffer - desc list3 size */
1167 sdu_prim_size = prim->len + len + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list3);
1168 }
1169 else
1170 {
1171 vsi_o_ttrace ( 0, TC_SYSTEM, "unknown desc type in 0x%x, routing aborted", prim->opc );
1172 vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
1173 return RT_ERROR;
1174 }
1175
1176 if ( sdu_prim_size < (int)MaxPrimPartSize )
1177 {
1178 ptr = (T_PRIM_HEADER*)vsi_c_new ( caller, sdu_prim_size, new_opc FILE_LINE_MACRO );
1179 }
1180 else
1181 {
1182 vsi_o_ttrace ( 0, TC_SYSTEM, "desclist in 0x%x too long, routing aborted", prim->opc );
1183 vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
1184 return RT_ERROR;
1185 }
1186 #ifdef MEMORY_SUPERVISION
1187 vsi_ppm_send ( caller, dst, (T_PRIM_HEADER*)ptr FILE_LINE_MACRO );
1188 #endif /* MEMORY_SUPERVISION */
1189
1190 fill_ptr = (char*)ptr;
1191 l_buf_ptr = &((T_sdu*)((int*)fill_ptr + prim->dph_offset))->l_buf;
1192 o_buf_ptr = &((T_sdu*)((int*)fill_ptr + prim->dph_offset))->o_buf;
1193 sdu_data_ptr = (char*)&((T_sdu*)((int*)fill_ptr + prim->dph_offset))->buf;
1194
1195 memcpy ( (char*)P2D(fill_ptr), (char*)P2D(prim), prim->len-sizeof(T_PRIM_HEADER) );
1196
1197 *l_buf_ptr = 0;
1198 *o_buf_ptr = 0;
1199
1200 fill_ptr = sdu_data_ptr;
1201
1202 if ( desc_type == (VSI_DESC_TYPE2 >> 16) )
1203 {
1204 desc2 = (T_desc2*)(((T_desc_list2*)dp_hdr)->first);
1205 while (desc2 != NULL)
1206 {
1207 *l_buf_ptr += (desc2->len*8);
1208 memcpy ( fill_ptr, (char*)(&desc2->buffer)+desc2->offset, desc2->len );
1209 fill_ptr += desc2->len;
1210 desc2 = (T_desc2 *)desc2->next;
1211 }
1212 }
1213 else if ( desc_type == (VSI_DESC_TYPE1 >> 16) )
1214 {
1215 desc = (T_desc*)(((T_desc_list*)dp_hdr)->first);
1216 while (desc != NULL)
1217 {
1218 *l_buf_ptr += (desc->len*8);
1219 memcpy ( fill_ptr, (char*)(&desc->buffer), desc->len );
1220 fill_ptr += desc->len;
1221 desc = (T_desc *)desc->next;
1222 }
1223 }
1224 else if ( desc_type == (VSI_DESC_TYPE3 >>16) )
1225 {
1226 desc3 = (T_desc3*)(((T_desc_list3*)dp_hdr)->first);
1227 while (desc3 != NULL)
1228 {
1229 *l_buf_ptr += (desc3->len*8);
1230 memcpy ( fill_ptr, (char*)(desc3->buffer)+desc3->offset, desc3->len );
1231 fill_ptr += desc3->len;
1232 desc3 = (T_desc3 *)desc3->next;
1233 }
1234 }
1235 vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
1236 *sdu_prim = ptr;
1237 return RT_OK;
1238 }
1239 #endif
1240
1241