view src/gpf/tst/drv/tif2.c @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*
+------------------------------------------------------------------------------
|  File:       tif.c
+------------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
|  Purpose :  This Modul contains the TIF driver
+-----------------------------------------------------------------------------
*/

#ifndef __TIF_C__
#define __TIF_C__
#endif

#include "typedefs.h"
#include "string.h"
#include "gdi.h"
#include "vsi.h"
#include "tools.h"
#include "glob_defs.h"
#include "ccdtable.h"
#include "ccddata.h"
#include "pcon.h"
#include "p_mem.h"
#include "drvconf.h"
#include "tstheader.h"

#ifdef _TOOLS_
  #include "frame_const.h"
  #include <stdio.h>
#endif /* _TOOLS_ */
#include "printtofile.h"

#ifndef _TOOLS_
#if !defined (_SOLARIS_) && !defined (_LINUX_)
#pragma pack(4)
#endif
#endif

/*lint -e545 */
/*==== TYPES ======================================================*/

typedef struct
{
  USHORT Handle;
  USHORT EnabledSignalType;
  T_DRV_CB_FUNC Callback;
  USHORT Config;
} T_TIF_DATA;

#ifdef _TOOLS_
typedef struct
{
  unsigned int use_id;
  char *name;
} T_RIV_USEID_TO_NAME;
#endif

/*==== CONSTANTS ==================================================*/

#define ALLOWED_TIF_SIGNALS   (DRV_SIGTYPE_READ|DRV_SIGTYPE_CONNECT|DRV_SIGTYPE_DISCONNECT)

#define NAME_LENGTH           4

#define TIF_RCV_CMD_SIZE    32
#define TIF_MAX_CMD         (TIF_RCV_CMD_SIZE-1)

#define STX                 0x02
#define LF                  0x0a

#define PCON_ENABLED   0x0001
#define SYNC_MODE      0x0002

#undef VSI_CALLER
#define VSI_CALLER TST_Handle,

#ifdef _TOOLS_
const T_RIV_USEID_TO_NAME riv_use_id_to_name[] =
{
  { 0x00010001, "RVM" },
  { 0x00010002, "RVT" },
  { 0x000A0001, "R2D" },
  { 0x000A0002, "RTC" },
  { 0x000A0004, "FFS" },
  { 0x000A0008, "KPD" },
  { 0x000A0010, "SPI" },
  { 0x000A0020, "PWR" },
  { 0x000A0040, "RGUI" },
  { 0x00140001, "HCI" },
  { 0x00140002, "L2CA" },
  { 0x00140004, "BTCT" },
  { 0x00140008, "RFC" },
  { 0x00140010, "SPP" },
  { 0x00140020, "HS" },
  { 0x00140040, "HSG" },
  { 0x00140080, "SDP" },
  { 0x00140100, "DUN" },
  { 0x00140200, "FAX" },
  { 0x00140400, "OBX" },
  { 0x00140800, "OPP" },
  { 0x00141000, "FTP" },
  { 0x00142000, "SYN" },
  { 0x001E0001, "EXPL" },
  { 0x001E0010, "AUDIO" },
  { 0x001E0020, "ETM" },
  { 0x001E0040, "DAR" },
  { 0x001E0080, "MKS" },
  { 0x001E0100, "MPM" },
  { 0x001E0200, "LLS" },
  { 0x001E0400, "ATP" },
  { 0x001E0800, "ATPUART" },
  { 0x001E2000, "MDC" },
  { 0x001E4000, "TTY" },
  { 0x001E8000, "DCM" },
  { 0x00280001, "TEST" },
  { 0x00280002, "TUT" },
  { 0x00320001, "KIL" },
  { 0x00320002, "KGC" },
  { 0x00320004, "KCL" },
  { 0x00320008, "KMM" },
  { 0x00320010, "KNM" },
  { 0x00320020, "UVM" },
  { 0x00320040, "KZP" },
  { 0x00320080, "KPG" },
  { 0x00320100, "JTM" },
  { 0x003C0001, "DEV1" },
  { 0x003C0002, "DEV2" },
  { 0x003C0003, "DEV3" },
  { 0x00460001, "RNET" },
  { 0x00460002, "RNET_WS" },
  { 0x00460004, "RNET_RT" },
  { 0x00460008, "RNET_BR" },
  { 0x00640001, "MSME" },
  { 0x00640002, "MSFE" },
  { 0x00640004, "STKE" },
  { 0x00640008, "BRSE" },
  { 0x00640010, "BRAE" },
  { 0x00640020, "PHSE" },
  { 0x00640040, "IBSE" },
  { 0x00640080, "MMSE" },
  { 0x00640100, "SLSE" },
  { 0x00640200, "SMAE" },
  { 0x00640400, "MEAE" },
  { 0x00640800, "SECE" },
  { 0x00641000, "SELE" },
  { 0x00642000, "PRSE" },
  { 0x00644000, "JAAE" },
  { 0x00648000, "JASE" },
  { 0x006E0001, "IT1E" },
  { 0x006E0002, "IT2E" },
  { 0x006E0004, "IT0E" },
  { 0x0,        NULL}
};
#endif

/*==== EXTERNALS ==================================================*/

extern T_HANDLE TST_Handle;

#ifndef _TOOLS_
extern const T_PCON_PROPERTIES *pcon;
extern ULONG MaxPrimPartSize;
extern const T_MEM_PROPERTIES *mem;
#endif

#ifdef CTB
  extern BOOL ctb_sent_to_tap;
  extern BOOL ctb_tick_enabled;
#endif

/*==== VARIABLES ==================================================*/

#ifndef RUN_INT_RAM
char corruptWarning[] = "corrupt prim received: ";
char wrongTSTWarning[] = "wrong (old) TST header used on toolside! ";
T_TIF_DATA TIF_Data;
static ULONG TIF_WrInd = 0;
BOOL socket_flush = TRUE;
#else
extern T_TIF_DATA TIF_Data;
extern BOOL socket_flush;
#endif /* RUN_INT_RAM */

#ifdef _TOOLS_
char buffer[80];

const T_PCON_PROPERTIES pcon_export =
{
  pcon_init_prim_coding,
  pcon_decodePrim,
  pcon_codePrim,
  pcon_make_filter,
  PCON_STACK_OFFSET
};

T_PCON_PROPERTIES const *pcon = &pcon_export;
#endif

/*==== FUNCTIONS ==================================================*/

#ifndef RUN_INT_RAM
USHORT TIF_Write ( void *Buffer, ULONG *BytesToWrite );
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : TIF                 |
| STATE   : code                       ROUTINE : TIF_Exit            |
+--------------------------------------------------------------------+

  PURPOSE : exit a driver

*/
LOCAL void TIF_Exit ( void )
{
#ifdef _TOOLS_
  ccddata_exit();
#endif /* _TOOLS_ */
}
#endif

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : TIF                 |
| STATE   : code                       ROUTINE : TIF_Write           |
+--------------------------------------------------------------------+

  PURPOSE : write data to driver

*/
/* Lint is not able to analyze the program flow through if...else constructions
   and therefor bring a bunch of warnings.*/
/*lint -e645 suppress warning -- Symbol '...' may not have been initialized */
/*lint -e644 suppress warning -- Symbol '...' may not have been initialized */
/*lint -e613 suppress warning -- possibly use of NULL pointer '...' */
USHORT TIF_Write ( void *Buffer, ULONG *BytesToWrite )
{
T_PRIM_HEADER *prim = (T_PRIM_HEADER*)Buffer;
T_PRIM_HEADER *prim_ptr = NULL;
TST_SMALL_HEADER *tst_header_ptr;
T_S_HEADER *s_hdr;
unsigned int bytes_to_write;
unsigned int size;
unsigned int name_len;
unsigned int length;
unsigned int org_rcv_len = 0; 
unsigned int opc_len = 0;
unsigned int bytes_written = 0;
unsigned int write_flag = 0;
char *write_ptr;
char *tst_data_ptr;
char trace_opc=0;
char Sender[RESOURCE_NAMELEN] = {0};
void *coded_prim;
void *decoded_prim;
int pcon_called = 0;
int is_primitive = TRUE;
int ret = DRV_OK;
int sts;
#ifdef _TOOLS_
int is_generated_primitive = FALSE;
#endif /* _TOOLS_ */


  s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset);
  if ( prim->opc & SYS_MASK )
  {
    size = prim->len - sizeof(T_PRIM_HEADER);
    tst_data_ptr = (char*)P2D(prim);
    tst_header_ptr = (TST_SMALL_HEADER*) tst_data_ptr - 1;
    tst_header_ptr->combined[INFO_BYTE] = (~HDR_IDENT_MASK | IDENT_SYS_PRIM);
    InsertString(s_hdr->rcv, (char*)&tst_header_ptr->receiver, 4);
    is_primitive = FALSE;
#ifdef _TOOLS_
    if ( (length = GetNextToken (tst_data_ptr, buffer, " #")) > 0)
    {
      if ( !strcmp (buffer, FILTER) )
      {
        void *filter_prim;
        if ( (pcon != NULL) && pcon->make_filter(tst_data_ptr+length+1, &filter_prim) == PCON_OK )
        {
          prim = D2P(filter_prim);
          s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset);
          is_primitive = TRUE;
          is_generated_primitive = TRUE;
        }
      }
    }
#endif
  }
  else if ( (SAP_NR(prim->opc)==TRACE_SAP) || (prim->opc==TRACE_OPC) )
  {
    is_primitive = FALSE;
    size = prim->len - sizeof(T_PRIM_HEADER);
    tst_data_ptr = (char*)P2D(prim);
    if (prim->opc!=TRACE_OPC)
    {
      /* we have a traceclass id */
      trace_opc=(char)PRIM_NR(prim->opc);
    }
    tst_header_ptr = (TST_SMALL_HEADER*) tst_data_ptr - 1;
    tst_header_ptr->combined[INFO_BYTE] = (~HDR_IDENT_MASK | IDENT_TRACE);
    InsertString(FRM_PCO_NAME, (char*)&tst_header_ptr->receiver, 4);
  }
  if ( is_primitive == TRUE )
  {
    TST_BIG_HEADER tst_big_header;
    TST_BIG_HEADER *tst_big_header_ptr;
#ifdef _TOOLS_
    /* on the tool side the primitive to be duplicated is copied when sent to TST */
    prim_ptr = prim;
#else
    /* in the target a pointer to the primitive to be duplicated is transported in a carrier of type T_PRIM_X */
    prim_ptr = (T_PRIM_HEADER*)((T_PRIM_X*)(prim))->prim_ptr;
#endif

    size = prim_ptr->len - sizeof(T_PRIM_HEADER);
    tst_data_ptr = (char*)P2D(prim_ptr);
    tst_big_header_ptr = &tst_big_header;
    opc_len = 4;
    org_rcv_len = 4;
    if ( (pcon != NULL) && (TIF_Data.Config & PCON_ENABLED) && !(prim_ptr->opc & VIRTUAL_OPC) )
    {
      decoded_prim = P2D(prim_ptr);
      if ( (sts = (int)(pcon->code_prim( prim_ptr->opc, decoded_prim, &coded_prim, (ULONG*)&size, 0, s_hdr->rcv ))) != PCON_OK )
      {
        vsi_o_ttrace (NO_TASK, TC_SYSTEM,"PCON Code Error %d, TIF_Write() aborted", sts );
        return DRV_INTERNAL_ERROR;
      }
      else
      {
        prim_ptr = D2P(coded_prim);
        tst_data_ptr = coded_prim;
        pcon_called = 1;
      }
    }

    EXCHANGE_4BYTES_ENDIANESS(&prim_ptr->opc);

    tst_big_header_ptr->opc = prim_ptr->opc;
    tst_big_header_ptr->combined[INFO_BYTE] = (~HDR_IDENT_MASK | IDENT_PS_PRIM);
    InsertString(s_hdr->rcv, (char*) &tst_big_header_ptr->receiver, 4);
    InsertString(s_hdr->org_rcv, (char*) &tst_big_header_ptr->orgreceiver, 4);
    socket_flush = TRUE;
    tst_header_ptr = (TST_SMALL_HEADER*) tst_big_header_ptr;
  }

  tst_header_ptr->combined[INFO_BYTE] = ((tst_header_ptr->combined[INFO_BYTE] & (~HDR_VERSION_MASK)) | HDR_VALID_VERSION_1);
  tst_header_ptr->combined[INFO_BYTE] = ((tst_header_ptr->combined[INFO_BYTE] & (~HDR_TIME_MASK)) | HDR_TIME_MS);
  tst_header_ptr->time = s_hdr->time;
  EXCHANGE_4BYTES_ENDIANESS(&tst_header_ptr->time);
  tst_header_ptr->sender[0] = 0;

  if ( s_hdr->snd[0] == 0 )
  {
    if ( *tst_data_ptr == '~')
    {
      name_len = GetNextToken ((char*)(tst_data_ptr), Sender, "~");
      InsertString(Sender, (char*) &tst_header_ptr->sender, 4);
      size -= 2+name_len;
      /* rub out a leading ~NAM~ in data field: */
      memcpy ( tst_data_ptr, tst_data_ptr + 2 + name_len, size );
    }
    else
    {
      InsertString(FRM_SYST_NAME, (char*)&tst_header_ptr->sender, 4);
    }
  }
  else
  {
    T_HANDLE TaskHandle;
    if ( s_hdr->snd[0] & ~HANDLE_MASK )
    {
      TaskHandle = (T_HANDLE)(s_hdr->snd[0]&HANDLE_MASK);
      vsi_e_name ( TST_Handle, TaskHandle, Sender );
      InsertString(Sender, (char*)&tst_header_ptr->sender, 4);
    }
    else
    {
      InsertString(s_hdr->snd, (char*)&tst_header_ptr->sender, 4);
    }
  }

  length = size + TST_HEADER_TRAILING_FIELDS + org_rcv_len + opc_len + (trace_opc ? 1 : 0);
  tst_header_ptr->combined[FIRST_BYTE] = (UBYTE) (LOW_MASK & length);
  tst_header_ptr->combined[SECOND_BYTE] = (UBYTE) (LOW_MASK & (length >> 8));
  bytes_to_write = length + TST_HEADER_LEADING_FIELDS;
  write_ptr = (char*)&tst_header_ptr->combined[INFO_BYTE];
  if (trace_opc)
  {
    /* move small header 1 byte to the left and insert trace class id */
    char *trace_opc_ptr=tst_data_ptr-1;
    write_ptr = (char*)tst_header_ptr;
    memcpy(write_ptr,(char*)tst_header_ptr+1,sizeof(TST_SMALL_HEADER)-1);
    *trace_opc_ptr=trace_opc;
    length++;
  }
  else if ( prim_ptr != NULL )
  {
    bytes_written = TST_BIG_HEADER_SIZE;
    if ( vsi_d_write ( TIF_Data.Handle, 0, write_ptr, bytes_written | PRIM_HEADER_FLAG ) != VSI_OK )
    {
      ret = DRV_INTERNAL_ERROR;
      *BytesToWrite = 0;
    }
    write_ptr = tst_data_ptr;
    write_flag = PRIM_DATA_FLAG;
  }

  if (ret==DRV_OK)
  {
#if defined (_TOOLS_) || defined (_LINUX_) || defined (_SOLARIS_)
    socket_flush = TRUE;  /* flush socket always on tool side */
#endif

    if ( vsi_d_write ( TIF_Data.Handle, 0, write_ptr, (bytes_to_write - bytes_written) | write_flag ) != VSI_OK )
    {
      ret = DRV_INTERNAL_ERROR;
      *BytesToWrite = 0;
    }
  }
  if ( pcon_called )
  {
    PFREE(P2D((T_VOID_STRUCT*)prim_ptr));
  }
#ifdef _TOOLS_
  if ( is_generated_primitive == TRUE )
  {
    vsi_c_free ( TST_Handle, (T_VOID_STRUCT**)&prim );
  }
#else /* _TOOLS_ */
  if (prim->opc & MEMHANDLE_OPC)
  {
    M_FREE(P_MEMHANDLE_SDU(((T_PRIM_X*)(prim))->prim_ptr));
  }
#endif /* _TOOLS_ */
#if defined _NUCLEUS_ && !defined _TARGET_
#ifdef CTB
  if(ctb_tick_enabled && !ctb_sent_to_tap && !strncmp(tst_header_ptr->receiver,"TAP",3)) 
  {
    ctb_sent_to_tap = TRUE;
  }
#endif
#endif

  return ( (USHORT)ret );
}
/*lint +e645 */
/*lint +e613 */
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : TIF                 |
| STATE   : code                       ROUTINE : TIF_SetSignal       |
+--------------------------------------------------------------------+

  PURPOSE : enable signal for the driver

*/
LOCAL USHORT TIF_SetSignal ( USHORT SignalType )
{
  if ( !(SignalType & ALLOWED_TIF_SIGNALS) )
    return DRV_INVALID_PARAMS;
  else
    TIF_Data.EnabledSignalType |= SignalType;

  return DRV_OK;
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : TIF                 |
| STATE   : code                       ROUTINE : TIF_ResetSignal     |
+--------------------------------------------------------------------+

  PURPOSE : disable signal for the driver

*/
LOCAL USHORT TIF_ResetSignal ( USHORT SignalType )
{
  if ( !(SignalType & ALLOWED_TIF_SIGNALS) )
    return DRV_INVALID_PARAMS;
  else
    TIF_Data.EnabledSignalType &= ~SignalType;

  return DRV_OK;
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : TIF                 |
| STATE   : code                       ROUTINE : TIF_SetConfig       |
+--------------------------------------------------------------------+

  PURPOSE : set configuration for the driver

*/
/*lint -esym(715,Buffer), suppress Info -- Symbol 'Buffer' not referenced) */
LOCAL USHORT TIF_SetConfig ( char *Buffer )
{
  if ( !strcmp ( TIF_PCON_ENABLE, Buffer ) )
  {
    if ( TIF_Data.Config & PCON_ENABLED)
    {
      /* already in PCON mode */
      return DRV_OK;
    }

#ifdef _TOOLS_
    switch (ccddata_init(NULL,0,NULL,NULL))
    {
      case CCDDATA_DLL_OK:
      case CCDDATA_DLL_ALREADY:
        break;
      default:
        return DRV_INTERNAL_ERROR;
    }
#endif
    TIF_Data.Config |= PCON_ENABLED;

#ifdef _TOOLS_
    printf("TIF: PCON mode selected\n");
#endif
    return DRV_OK;
  }
  else if ( !strcmp ( DRV_DEFAULT, Buffer ) )
  {
    if ( !(TIF_Data.Config & PCON_ENABLED))
    {
      /* already in default mode */
      return DRV_OK;
    }

#ifdef _TOOLS_
    ccddata_exit();
#endif
    TIF_Data.Config &= ~PCON_ENABLED;

#ifdef _TOOLS_
    printf("TIF: default mode selected\n");
#endif
    return DRV_OK;
  }
#ifdef _TOOLS_
  else if ( !strcmp ( ENABLE_SYNC_MODE, Buffer ) )
  {
    TIF_Data.Config |= SYNC_MODE;
    PrintToFile("TIF: sync mode enabled\n");
    return DRV_OK;
  }
  else if ( !strcmp ( DISABLE_SYNC_MODE, Buffer ) )
  {
    TIF_Data.Config &= ~SYNC_MODE;
    PrintToFile("TIF: sync mode disabled\n");
    return DRV_OK;
  }
  return DRV_INVALID_PARAMS;
#else
  return DRV_OK;
#endif
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : TIF                 |
| STATE   : code                       ROUTINE : Callback            |
+--------------------------------------------------------------------+

  PURPOSE : callback function of the driver

*/
/* Lint is not able to analyze the program flow through if...else constructions
   and therefor bring a bunch of warnings.*/
/*lint -esym(645,opc_str) suppress warning -- Symbol 'opc_str' may not have been initialized */
LOCAL void TIF_Callback ( T_DRV_SIGNAL *Signal )
{
T_PRIM_HEADER *prim;
T_S_HEADER *s_hdr;
T_PRIM_X *sys_prim;
T_DRV_SIGNAL TIF_Signal;
TST_BIG_HEADER tst_header;
unsigned int CorruptByteOffset = 0;
unsigned int length;
unsigned int BytesToRead = 0;
unsigned int BytesRead;
unsigned int Bytes = 0;
unsigned int i;
unsigned int opc_len = 0;
unsigned int org_rcv_len = 0;
unsigned int alloc_size;
int sts;
int WrongTSTHeader = FALSE;
char *target;
void *decoded_prim;
char opc_str[4];
#ifdef _TOOLS_
int l1_sigtype = 0;
#endif

  switch ( Signal->SignalType )
  {
#ifdef _TOOLS_
    case DRV_SIGTYPE_READ_L1:
      l1_sigtype = 1;
      /*lint -fallthrough*/
    case DRV_SIGTYPE_READ_RIV:

      if ( vsi_d_read ( TIF_Data.Handle, 0, NULL, &BytesToRead ) != DRV_OK )
        return;

      alloc_size = S_ALLOC_SIZE(BytesToRead + 1);
      if ( ( prim = (T_PRIM_HEADER*)vsi_c_new ( TST_Handle, alloc_size, 0 FILE_LINE_MACRO )) != NULL )
      {
        TIF_WrInd = 0;
        Bytes = 0;
        BytesRead = BytesToRead;
        do
        {
          vsi_d_read ( TIF_Data.Handle, 0, (void*)((char*)P2D(prim)+TIF_WrInd), &BytesRead );
          Bytes += BytesRead;
          if ( Bytes < BytesToRead )
          {
            TIF_WrInd += BytesRead;
            BytesRead = BytesToRead - BytesRead;
          }
        } while ( Bytes < BytesToRead );
        prim->sh_offset = S_HDR_OFFSET(alloc_size - sizeof(T_S_HEADER));
        s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset);
        s_hdr->time = 0;
        s_hdr->org_rcv[0] = 0;
        if ( l1_sigtype == 1 )
        {
          strcpy ( s_hdr->snd, "L1" );
        }
        else
        {
          int i = 0;
          unsigned int use_id = 0;
          unsigned char *p = (unsigned char*)P2D(prim);
          use_id = use_id | *p++ << 24;
          use_id = use_id | *p++ << 16;
          use_id = use_id | *p++ << 8;
          use_id = use_id | *p;
          do
          {
            if ( riv_use_id_to_name[i].use_id == use_id )
            {
              strcpy ( s_hdr->snd, riv_use_id_to_name[i].name );
              break;
            }
            if ( riv_use_id_to_name[i+1].use_id == 0 )
              strcpy ( s_hdr->snd, "RIV" );
          } while ( riv_use_id_to_name[++i].use_id != 0 );
          memcpy ( (char*)P2D(prim), (char*)P2D(prim)+5, BytesToRead);
        }
        strcpy ( s_hdr->rcv, FRM_PCO_NAME );

        sys_prim = (T_PRIM_X*) vsi_c_new ( TST_Handle, alloc_size, 0 FILE_LINE_MACRO );
        sys_prim->prim_ptr = prim;
        prim->opc = 0;
        prim->len = BytesToRead  + sizeof(T_PRIM_HEADER);

        if ( TIF_Data.EnabledSignalType & DRV_SIGTYPE_READ )
        {
          VSI_PPM_SEND ( (T_PRIM_HEADER*)sys_prim, TST_Handle );
          VSI_PPM_SEND ( (T_PRIM_HEADER*)sys_prim->prim_ptr, TST_Handle );
          TIF_Signal.SignalType = DRV_SIGTYPE_READ;
          TIF_Signal.DrvHandle = TIF_Data.Handle;
          TIF_Signal.UserData = (T_VOID_STRUCT*)sys_prim;
          (TIF_Data.Callback)( &TIF_Signal );
        }
      }
      break;
#endif
    case DRV_SIGTYPE_READ:
      /*
       * Get the size of the needed buffer to store the data
       */

      if ( vsi_d_read ( TIF_Data.Handle, 0, NULL, (ULONG*)&BytesToRead ) != DRV_OK )
        return;

      if ( BytesToRead )
      {
        if ( BytesToRead >= TST_SMALL_HEADER_SIZE )
          BytesToRead -= TST_SMALL_HEADER_SIZE;
        Bytes = 0;
        TIF_WrInd = 0;
        BytesRead = TST_SMALL_HEADER_SIZE;
        do
        {
          vsi_d_read ( TIF_Data.Handle, 0, (void*)((char*)&tst_header.combined[INFO_BYTE]+TIF_WrInd), (ULONG*)&BytesRead );
          Bytes += BytesRead;
          if ( Bytes < TST_SMALL_HEADER_SIZE )
          {
            TIF_WrInd += BytesRead;
            BytesRead = TST_SMALL_HEADER_SIZE - BytesRead;
          }
        } while ( Bytes < TST_SMALL_HEADER_SIZE );

        alloc_size = ALIGN(sizeof(T_PRIM_X));
        sys_prim = (T_PRIM_X*) vsi_c_new ( TST_Handle, alloc_size, 0 FILE_LINE_MACRO );

        switch (tst_header.combined[INFO_BYTE] &  HDR_IDENT_MASK)
        {
          case IDENT_ABORT:
            tst_header.combined[INFO_BYTE] = ((tst_header.combined[INFO_BYTE] & ~HDR_IDENT_MASK) | IDENT_TRACE);
#ifdef _TOOLS_
            /* TR did loose byte(s)! Primitive is corrupt, no header val can be
            guaranteed to be valid.
            Create a HUGE trace prim with zero time, sender tst, receiver pco,
            org_receiver tst
            TRACE DATA will contain: a "corrupt prim received: " string,
            the already received part of the prim and all the rest */
            CorruptByteOffset = TST_SMALL_HEADER_SIZE + strlen(corruptWarning) + 1;
#else
            /* TR did receive a prim from tool side old TST header format and swiched to new.
            Now we have to TRACE the wrong tool side format, because the prim is lost. */
            WrongTSTHeader = TRUE;
            BytesToRead = 0;
            CorruptByteOffset = strlen(wrongTSTWarning) + 1;
#endif
            break;
          case IDENT_PS_PRIM:
            opc_len = 4;
            org_rcv_len = 4;
            break;
          default:
            break;
        }

        if ( (BytesRead = org_rcv_len) > 0 )
        {
          if ( BytesToRead >= org_rcv_len )
            BytesToRead -= org_rcv_len;
          Bytes = 0;
          TIF_WrInd = 0;
          do
          {
            vsi_d_read ( TIF_Data.Handle, 0, (void*)((char*)&tst_header.orgreceiver+TIF_WrInd), (ULONG*)&BytesRead );
            Bytes += BytesRead;
            if ( Bytes < org_rcv_len )
            {
              TIF_WrInd += BytesRead;
              BytesRead = org_rcv_len - BytesRead;
            }
          } while ( Bytes < org_rcv_len );
        }

        if ( (BytesRead = opc_len) > 0 )
        {
          if ( BytesToRead >= opc_len )
            BytesToRead -= opc_len;
          Bytes = 0;
          TIF_WrInd = 0;
          do
          {
            vsi_d_read ( TIF_Data.Handle, 0, (void*)(opc_str+TIF_WrInd), (ULONG*)&BytesRead );
            Bytes += BytesRead;
            if ( Bytes < opc_len )
            {
              TIF_WrInd += BytesRead;
              BytesRead = opc_len - BytesRead;
            }
          } while ( Bytes < opc_len );
        }

        alloc_size = S_ALLOC_SIZE(CorruptByteOffset + BytesToRead + 1);
#ifdef _TOOLS_
        if ( alloc_size > MAX_PRIM_PARTITION_SIZE - sizeof(T_PRIM_HEADER) - sizeof(T_S_HEADER))
          alloc_size = MAX_PRIM_PARTITION_SIZE - sizeof(T_PRIM_HEADER) - sizeof(T_S_HEADER);
#else
        if ( alloc_size > MaxPrimPartSize - sizeof(T_PRIM_HEADER) - sizeof(T_S_HEADER) )
          alloc_size = MaxPrimPartSize - sizeof(T_PRIM_HEADER) - sizeof(T_S_HEADER);
#endif
        if ( ( prim = (T_PRIM_HEADER*)vsi_c_new ( TST_Handle, alloc_size, 0 FILE_LINE_MACRO )) != NULL )
        {
          TIF_WrInd = 0;
          Bytes = 0;
          if ((BytesToRead + CorruptByteOffset) > alloc_size)
          {
#ifdef _TOOLS_
            PrintToFile("TIF: Reduced a new Prim's size\n");
#endif
            BytesToRead = alloc_size - CorruptByteOffset;
          }
          BytesRead = BytesToRead;

          target = (char*) P2D(prim);

          if (WrongTSTHeader)
          {
            memcpy(target, wrongTSTWarning, strlen(wrongTSTWarning));
            target += strlen(wrongTSTWarning);
          }
          else if (CorruptByteOffset)
          {
#ifdef _TOOLS_
            PrintToFile("TIF: Byte(s) lost\n");
#endif
            memcpy(target, corruptWarning, strlen(corruptWarning));
            target += strlen(corruptWarning);
            /*lint -e420, suppress Warning -- Apparent access beyond array for function 'memcpy(...*/
            memcpy(target,&tst_header.combined[INFO_BYTE], TST_SMALL_HEADER_SIZE-1);
            /*lint +e420 */
            target += TST_SMALL_HEADER_SIZE - 1;
          }


          if (WrongTSTHeader == FALSE && BytesToRead)
          {
            if ( (tst_header.combined[INFO_BYTE] &  HDR_IDENT_MASK)==IDENT_TRACE )
            {
              /* we read the first bytes in advance in case the trace class is carried */
              ULONG bread=1;
              vsi_d_read ( TIF_Data.Handle, 0, (void*)((char*)target+TIF_WrInd), &bread );

              if (bread==1 && *((char*)target)<0x20) /* no character -> assume traceclass id */
              {
                opc_str[0]=*((char*)target);
                opc_len=1;

                BytesToRead -= bread;
              }
              else
              {
                /* ok, we have no traceclass info :-( */
                TIF_WrInd += bread;
                Bytes += bread;
              }
              BytesRead = BytesToRead - Bytes;
            }

            do
            {
              vsi_d_read ( TIF_Data.Handle, 0, (void*)((char*)target+TIF_WrInd), (ULONG*)&BytesRead );
              Bytes += BytesRead;
              if ( Bytes < BytesToRead )
              {
                TIF_WrInd += BytesRead;
                BytesRead = BytesToRead - Bytes;
              }
            } while ( Bytes < BytesToRead );
          }

          *((char*)target + Bytes) = 0;
          prim->sh_offset = S_HDR_OFFSET(alloc_size - sizeof(T_S_HEADER));
          s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset);
          switch (tst_header.combined[INFO_BYTE] &  HDR_IDENT_MASK)
          {
            case IDENT_PS_PRIM:

              EXCHANGE_4BYTES_ENDIANESS(opc_str);

              memcpy((char*)&prim->opc, opc_str, 4);
              if ( (pcon != NULL) && (TIF_Data.Config & PCON_ENABLED) )
              {
                if ( (sts = (int)pcon->decode_prim ( prim->opc, &decoded_prim, (void*)((char*)prim+sizeof(T_PRIM_HEADER)), (ULONG*)&length, 0 )) != PCON_OK )
                {
                  if ( sts != PCON_CONFIG_PRIM )
                  {
                    vsi_o_ttrace (NO_TASK, TC_SYSTEM,"PCON Deode Error %d, TIF_Callback() aborted", sts );
                  }
                  PFREE(P2D(sys_prim));
                  PFREE(P2D(prim));
                  return;
                }
                PFREE(P2D((T_VOID_STRUCT*)prim));
                sys_prim->prim_ptr = D2P(decoded_prim);
              }
              else
              {
                sys_prim->prim_ptr = prim;
                length = BytesToRead;
              }
              sys_prim->prim_ptr->sh_offset = S_HDR_OFFSET(length+sizeof(T_PRIM_HEADER));
              sys_prim->prim_ptr->len = length + sizeof(T_PRIM_HEADER);
              s_hdr = (T_S_HEADER*)((ULONG*)sys_prim->prim_ptr + sys_prim->prim_ptr->sh_offset);
#ifndef _TOOLS_
              /* evtl. convert aux sdu to mem handle */
              if (sys_prim->prim_ptr->opc & MEMHANDLE_OPC && mem!=NULL)
              {
                if (P_MEMHANDLE_SDU(sys_prim->prim_ptr))
                {
                  U32 mem_handle;
                  U8 buffer_handle;
                  U8 user_handle;
                  U8 *user_data;
                  T_sdu *sdu;
                  U16 len;

                  sdu=(T_sdu *)P_MEMHANDLE_SDU(sys_prim->prim_ptr);
                  len=(sdu->l_buf + 7)/8;

                  buffer_handle=mem->create_buffer(MEM_UNORDERED_BUFFER, len);
                  user_handle = mem->create_user(buffer_handle, 23, "TST");

                  user_data=mem->alloc(user_handle,len,&mem_handle);
                  memcpy(user_data,sdu->buf+(sdu->o_buf+7)/8,len);
                  P_MEMHANDLE(sys_prim->prim_ptr)=mem_handle;

                  mem->delete_user(user_handle);
                  mem->delete_buffer(buffer_handle);
                }
              }
#endif
            break;

            case IDENT_SYS_PRIM:
              sys_prim->prim_ptr = prim;
              prim->opc = SYS_MASK;
              prim->len = BytesToRead  + sizeof(T_PRIM_HEADER);
            break;

            case IDENT_TRACE:
              sys_prim->prim_ptr = prim;
              if (opc_len)
              {
                /* nice, we found a traceclass info */
                prim->opc = opc_str[0];
                prim->opc = prim->opc << 16;
                prim->opc |= EXTENDED_OPC | VIRTUAL_OPC | TRACE_SAP;
              }
              else
              {
                prim->opc = TRACE_OPC;
              }
              prim->len = CorruptByteOffset + BytesToRead  + sizeof(T_PRIM_HEADER);
              break;

            default:
            break;
          }

          /*
           * Extract Sender and Receiverfrom header
           */
          if (CorruptByteOffset)
          {
            s_hdr->time = NULL;
#ifndef _TOOLS_
            memcpy ( s_hdr->snd, "~TST", 4 );
            memcpy ( s_hdr->rcv, FRM_TST_NAME, 4 );
#else
            memcpy ( s_hdr->snd, FRM_TST_NAME, 4 );
            memcpy ( s_hdr->rcv, FRM_PCO_NAME, 4 );
#endif
            memcpy ( s_hdr->org_rcv, "TST", 4 );
          }
          else
          {
            s_hdr->time = tst_header.time;

            i = 0;
            do
            {
              s_hdr->snd[i] = tst_header.sender[i];
              i++;
            } while ( tst_header.sender[i] != 0x20 && i < 4 );
            s_hdr->snd[i] = 0;

            i = 0;
            do
            {
              s_hdr->rcv[i] = tst_header.receiver[i];
              i++;
            } while ( tst_header.receiver[i] != 0x20 && i < 4 );
            s_hdr->rcv[i] = 0;

            if (org_rcv_len)
            {
              i = 0;
              do
              {
                s_hdr->org_rcv[i] = tst_header.orgreceiver[i];
                i++;
              } while ( tst_header.orgreceiver[i] != 0x20 && i < 4 );
              s_hdr->org_rcv[i] = 0;
            }
          }

          if ( TIF_Data.EnabledSignalType & DRV_SIGTYPE_READ )
          {
            VSI_PPM_SEND ( (T_PRIM_HEADER*)sys_prim, TST_Handle );
            VSI_PPM_SEND ( (T_PRIM_HEADER*)sys_prim->prim_ptr, TST_Handle );
            TIF_Signal.SignalType = DRV_SIGTYPE_READ;
            TIF_Signal.DrvHandle = TIF_Data.Handle;
            TIF_Signal.UserData = (T_VOID_STRUCT*)sys_prim;
            (TIF_Data.Callback)( &TIF_Signal );
          }
        }
      } /* if ( BytesToRead ) */
    break;
    case DRV_SIGTYPE_CONNECT:
    case DRV_SIGTYPE_DISCONNECT:
      if ( TIF_Data.EnabledSignalType & Signal->SignalType )
      {
        TIF_Signal.SignalType = Signal->SignalType;
        TIF_Signal.DrvHandle = TIF_Data.Handle;
        TIF_Signal.UserData = NULL;
        (TIF_Data.Callback)( &TIF_Signal );
      }
    break;
    default:
    break;
  }
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : TIF                 |
| STATE   : code                       ROUTINE : TIF_Init            |
+--------------------------------------------------------------------+

  PURPOSE : initialize driver

*/
GLOBAL USHORT TIF_Init ( USHORT DrvHandle, T_DRV_CB_FUNC CallbackFunc, T_DRV_EXPORT const **DrvInfo )
{
static const T_DRV_EXPORT TIF_Info =
{
  TIF_NAME,
  0,
  {
#ifdef _TOOLS_
    TIF_Init,
#endif
    TIF_Exit,
    NULL,
    TIF_Write,
    NULL,
    NULL,
    NULL,
    TIF_SetSignal,
    TIF_ResetSignal,
    TIF_SetConfig,
    NULL,
    TIF_Callback,
  }
};

#ifndef _TOOLS_
union
{
  USHORT s;
  UBYTE b[2];
} test;
#endif /* !_TOOLS_ */

  TIF_Data.Handle = DrvHandle;
  TIF_Data.EnabledSignalType = 0;
  TIF_Data.Config = 0;
  TIF_Data.Callback = CallbackFunc;

#ifdef _TOOLS_
  switch (ccddata_init(NULL,0,NULL,NULL))
  {
    case CCDDATA_DLL_OK:
    case CCDDATA_DLL_ALREADY:
      break;
    default:
      return DRV_INITFAILURE;
  }
#else /* _TOOLS_ */
  test.s = 1;
  if ( pcon != NULL )
  {
    ULONG sts = pcon->init_prim_coding ( TST_Handle,(UBYTE)((test.b[0]==1) ? PCON_LITTLE : PCON_BIG));
#ifndef _TARGET_ 
    vsi_pcheck_register (pcon->pcheck, PCON_OK);
#endif /* !_TARGET_ */
  }
#endif /* !_TOOLS_ */

  *DrvInfo = &TIF_Info;

  return DRV_OK;
}
#endif