FreeCalypso > hg > fc-magnetite
view src/g23m-gsm/dl/dl_trace.c @ 354:cb3bc4fe730a
cfg-headers/voice-only: created
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 25 Dec 2017 00:32:10 +0000 |
parents | 27a4235405c6 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : +----------------------------------------------------------------------------- | 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 defines the offline trace functions | for the component DL of the mobile station. +----------------------------------------------------------------------------- */ #ifndef DL_TRACE_C #define DL_TRACE_C #define ENTITY_DL /*==== INCLUDES ===================================================*/ #include "typedefs.h" #include <string.h> #include "vsi.h" #include "pconst.cdg" #include "custom.h" #include "gsm.h" #include "mon_dl.h" #include "prim.h" #include "pei.h" #include "tok.h" #include "ccdapi.h" #include "dl.h" /*==== EXPORT =====================================================*/ /*==== PRIVAT =====================================================*/ #if defined(DL_TRACE_ENABLED) #ifdef OPTION_MULTITHREAD #define TRACE_TYPE _ENTITY_PREFIXED(TRACE_TYPE) #define CHANNEL _ENTITY_PREFIXED(CHANNEL) #define STATES _ENTITY_PREFIXED(STATES) #endif /* OPTION_MULTITHREAD */ LOCAL const char* const STATES[] = { "INVALID", "DISABLED", "IDLE_DL", "SUSPENDED", "AWAITING_ESTABLISHMENT", "MULTI_FRAME_ESTABLISHED", "TIMER_RECOVERY", "AWAITING_RELEASE" }; LOCAL const char* const TRACE_TYPE[] = { "UL", "DL", "Ev", "St", "PL", "RR" }; LOCAL const char* const CH_TYPE[] = { " ", "SA", "SD", "FH", "FF", "CC", "BC", "PC", "PE", "CB", "BE" }; LOCAL const char SAPI_TYPE[] = { '0', '1', '2', '3', ' '}; LOCAL void array2hex (UBYTE *inarray, char *outarray, int size); #if !defined(DL_IMMEDIATE_TRACE) /*==== TEST TRACE ===================================================*/ #define TEST_ENTITY_DL /*==== VARIABLES ==================================================*/ /*==== FUNCTIONS ==================================================*/ /* * The Data Link Layer Trace is a cyclic buffer for * debugging layer 2 problems. * * The buffer will be initialized at startup and will * be filled by the function dl_trace() until it is full. * The size of the buffer is IDLE_TRACE_SIZE. * * The content is * * trace_type (uplink, downlink, event state, alr_event, rr_event) * Channel Type (SACCH, SDDCH, FACCH) * real system clock * State (DL states) * pending disc request * data (layer frame, eevnt strings, state) * * During IDLE mode (triggered by RX_PERIODIC_IND in ALR/TIL_main.c) * an output is written to as SYST trace. * (IDLE_TRACE_MAX_READED traces each trigger) */ #define IDLE_TRACE_SIZE 512 #define IDLE_TRACE_MAX_READED 16 #if (((IDLE_TRACE_SIZE-1) & (~IDLE_TRACE_SIZE)) == (IDLE_TRACE_SIZE-1)) #define POWER_OF_2 #pragma message("IDLE_TRACE_SIZE is power of 2") #else #pragma message("IDLE_TRACE_SIZE is NOT power of 2") #endif typedef struct { UBYTE trace_type; UBYTE ch_type; UBYTE sapi; T_TIME sysClock; UBYTE disc_request; UBYTE state; UBYTE data [MAX_L2_FRAME_SIZE]; } T_IDLE_TRACE_DATA; #ifdef OPTION_MULTITHREAD #define IDLE_Trace_buffer _ENTITY_PREFIXED(IDLE_Trace_buffer) #define IDLE_Trace_write_index _ENTITY_PREFIXED(IDLE_Trace_write_index) #define IDLE_Trace_read_index _ENTITY_PREFIXED(IDLE_Trace_read_index) #endif /* OPTION_MULTITHREAD */ GLOBAL T_IDLE_TRACE_DATA IDLE_Trace_buffer [IDLE_TRACE_SIZE]; GLOBAL USHORT IDLE_Trace_write_index = 0; GLOBAL USHORT IDLE_Trace_read_index = 0; LOCAL T_HANDLE sem_DL_TRC; GLOBAL void dl_trace_init (void) { sem_DL_TRC = vsi_s_open (VSI_CALLER "DL_IDLE_TRACE",1); if (sem_DL_TRC NEQ VSI_ERROR) dl_trace_clear (0); else SYST_TRACE ("DL:canīt open semaphore \"DL_IDLE_TRACE\""); } GLOBAL void dl_trace_exit (void) { if (sem_DL_TRC NEQ VSI_ERROR) vsi_s_close (VSI_CALLER sem_DL_TRC); } GLOBAL void dl_trace_clear () { dl_trace_read_all (0); /* first, get all remaining traces (if exists) */ ENTER_CRITICAL_SECTION (sem_DL_TRC); IDLE_Trace_write_index = IDLE_Trace_read_index = 0; LEAVE_CRITICAL_SECTION (sem_DL_TRC); TRACE_EVENT ("offline trace reset"); DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, 0, "offline trace reset"); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : DL_COM | | STATE : code ROUTINE : dl_trace | +--------------------------------------------------------------------+ PURPOSE : Fill in a trace. */ GLOBAL void dl_trace (UCHAR trace_type, UCHAR channel, UCHAR ch_type, UCHAR* data) { T_IDLE_TRACE_DATA* trace_data; USHORT write_index1, write_index2;/* trace_size must not be greater than 2 */ UBYTE trace_size; if (data) { #if defined (DISABLE_MEASREPORT_TRACE) if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[2] EQ 0x01) AND (data[3] EQ 0x03) AND (data[4] EQ 0x49)) return; #endif /* DISABLE_MEASREPORT_TRACE */ #if defined (DISABLE_EMPTY_UI) if ((trace_type EQ TRACE_DOWNLINK) OR (trace_type EQ TRACE_UPLINK)) { if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[3] EQ 0x03) AND (data[4] EQ 0x01)) return; else if ( (data[1] EQ 0x03) AND (data[2] EQ 0x01)) return; } #endif /* DISABLE_EMPTY_UI */ } TEST_SEMAPHORE (sem_DL_TRC); ENTER_CRITICAL_SECTION(sem_DL_TRC); trace_size = 1; if ((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT)) { if (data AND strlen ((char *)data) >= 23) trace_size = 2; } #if defined(POWER_OF_2) write_index1 = (IDLE_Trace_write_index + 1) & (IDLE_TRACE_SIZE - 1); /* if IDLE_TRACE_SIZE power of 2 */ write_index2 = (IDLE_Trace_write_index + trace_size) & (IDLE_TRACE_SIZE - 1); /* if IDLE_TRACE_SIZE power of 2 */ #else write_index1 = (IDLE_Trace_write_index + 1) % IDLE_TRACE_SIZE; /* if IDLE_TRACE_SIZE not power of 2 */ write_index2 = (IDLE_Trace_write_index + trace_size) % IDLE_TRACE_SIZE; /* if IDLE_TRACE_SIZE not power of 2 */ #endif /* POWER_OF_2 */ if ((write_index1 NEQ IDLE_Trace_read_index) AND (write_index2 NEQ IDLE_Trace_read_index)) { /* buffer is not full */ trace_data = &IDLE_Trace_buffer[IDLE_Trace_write_index]; trace_data->trace_type = trace_type; if ((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT)) { trace_data->state = trace_size; } else { GET_INSTANCE_DATA; trace_data->ch_type = ch_type; switch (channel) { case C_SACCH0: case C_DCCH0: trace_data->disc_request = dl_data->dcch0_disc_request; trace_data->state = dl_data->state [C_DCCH0]; trace_data->sapi = PS_SAPI_0; break; case C_DCCH3: trace_data->disc_request = dl_data->dcch3_disc_request; trace_data->state = dl_data->state [C_DCCH3]; trace_data->sapi = PS_SAPI_3; break; default: trace_data->disc_request = 0; trace_data->state = 0; trace_data->sapi = NOT_PRESENT_8BIT; break; } } vsi_t_time (VSI_CALLER &trace_data->sysClock); if (data) { memcpy (trace_data->data, data, MAX_L2_FRAME_SIZE); if ((trace_type NEQ TRACE_UPLINK) AND (trace_type NEQ TRACE_DOWNLINK)) { trace_data->data[MAX_L2_FRAME_SIZE-1] = 0; } if (trace_size EQ 2) { if (IDLE_Trace_write_index EQ (IDLE_TRACE_SIZE - 1))/* the last buffer index ? */ trace_data = &IDLE_Trace_buffer[0];/* -> overflow to the first buffer index */ else trace_data++; memcpy (trace_data->data, data+MAX_L2_FRAME_SIZE-1, MAX_L2_FRAME_SIZE-1); trace_data->data[MAX_L2_FRAME_SIZE-1] = 0; } } IDLE_Trace_write_index = write_index2; }/* endif buffer is not full */ LEAVE_CRITICAL_SECTION (sem_DL_TRC); #if defined(_SIMULATION_) dl_trace_read (0); #endif /* _SIMULATION_ */ } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : DL_COM | | STATE : code ROUTINE : dl_trace_read | +--------------------------------------------------------------------+ PURPOSE : Fill in a trace. */ GLOBAL void dl_trace_read_all () { USHORT write_index, read_index; do { dl_trace_read (); ENTER_CRITICAL_SECTION (sem_DL_TRC); write_index = IDLE_Trace_write_index; read_index = IDLE_Trace_read_index; LEAVE_CRITICAL_SECTION (sem_DL_TRC); } while (read_index NEQ write_index); } GLOBAL void dl_trace_read () { T_IDLE_TRACE_DATA* trace_data; USHORT write_index, read_index, left; UBYTE trace_size; static char buffer[80]; UBYTE j, o, readed = 0; TEST_SEMAPHORE (sem_DL_TRC); ENTER_CRITICAL_SECTION (sem_DL_TRC); write_index = IDLE_Trace_write_index; read_index = IDLE_Trace_read_index; LEAVE_CRITICAL_SECTION (sem_DL_TRC); if (read_index EQ write_index) { #if defined (_TARGET_) AND !defined( GPRS ) AND defined(FF_GTI) sleep_mode (); #endif /* _TARGET_ AND !GPRS AND !FF_GTI */ return; } while (read_index NEQ write_index) { ENTER_CRITICAL_SECTION (sem_DL_TRC); trace_data = &IDLE_Trace_buffer[read_index]; LEAVE_CRITICAL_SECTION (sem_DL_TRC); #if defined(POWER_OF_2) left = (write_index - read_index - 1) & (IDLE_TRACE_SIZE-1); #else left = (IDLE_TRACE_SIZE + write_index - read_index - 1) % IDLE_TRACE_SIZE; #endif /* POWER_OF_2 */ if (trace_data->ch_type > ELEMENTS(CH_TYPE)) trace_data->ch_type = 0; if (trace_data->sapi >= ELEMENTS (SAPI_TYPE)) trace_data->sapi = ELEMENTS (SAPI_TYPE) - 1; trace_size = 1;/* default */ switch (trace_data->trace_type) { case TRACE_UPLINK: case TRACE_DOWNLINK: sprintf (buffer, "[%03d]:%07lu %c%d %s %s ", left, trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, TRACE_TYPE[trace_data->trace_type], CH_TYPE[trace_data->ch_type]); o = strlen (buffer); array2hex (trace_data->data, buffer+o, 23); break; case TRACE_DL_EVENT: sprintf (buffer, "[%03d]:%07lu %c%d Ev %s%c %s", left, trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[trace_data->ch_type], SAPI_TYPE[trace_data->sapi], trace_data->data); break; case TRACE_PL_EVENT: case TRACE_RR_EVENT: trace_size = trace_data->state; if (trace_size EQ 2) { T_IDLE_TRACE_DATA *trace_data2; if (read_index EQ (IDLE_TRACE_SIZE - 1))/* the last buffer index ? */ trace_data2 = &IDLE_Trace_buffer[0];/* -> overflow to the first buffer index */ else trace_data2 = trace_data+1; sprintf (buffer, "[%03d]:%07lu %d Ev %s %s%s", left, trace_data->sysClock, trace_data->state, TRACE_TYPE[trace_data->trace_type], trace_data->data, trace_data2->data); } else { sprintf (buffer, "[%03d]:%07lu %d Ev %s %s", left, trace_data->sysClock, trace_data->state, TRACE_TYPE[trace_data->trace_type], trace_data->data); } break; case TRACE_CHSTATE: sprintf (buffer, "[%03d]:%07lu %c%d ST %s%c state=%s", left, trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[trace_data->ch_type], SAPI_TYPE[trace_data->sapi], STATES[trace_data->state]); break; default: buffer[0] = 0; break; } if (buffer[0]) { SYST_TRACE (buffer); } else { SYST_TRACE ("dl_trace_read() failed"); } ENTER_CRITICAL_SECTION (sem_DL_TRC); trace_data->sysClock = 0; /* readed */ IDLE_Trace_read_index += trace_size; #if defined(POWER_OF_2) IDLE_Trace_read_index &= (IDLE_TRACE_SIZE-1);/* if power of 2 */ #else IDLE_Trace_read_index %= IDLE_TRACE_SIZE; /* if not power of 2 */ #endif /* POWER_OF_2 */ read_index = IDLE_Trace_read_index; write_index = IDLE_Trace_write_index; LEAVE_CRITICAL_SECTION (sem_DL_TRC); if (readed++ >= IDLE_TRACE_MAX_READED) break; }/* endwhile */ } #else /* DL_IMMEDIATE_TRACE */ #define IMM_TRACE_SIZE 2 typedef struct { UBYTE sapi; T_TIME sysClock; UBYTE disc_request; UBYTE state; UBYTE data [IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE]; } T_TRACE_DATA; #ifdef OPTION_MULTITHREAD #define print_buffer _ENTITY_PREFIXED(print_buffer) #define trace_buffer _ENTITY_PREFIXED(trace_buffer) #endif /* OPTION_MULTITHREAD */ LOCAL char print_buffer[25+IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE]; LOCAL T_TRACE_DATA trace_buffer; /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : DL_COM | | STATE : code ROUTINE : dl_trace | +--------------------------------------------------------------------+ PURPOSE : Fill in a trace. */ GLOBAL void dl_fast_trace (UBYTE trace_type, UBYTE channel, UBYTE ch_type, T_TIME trace_time, ULONG trace_mask, UBYTE* data) { T_TRACE_DATA* trace_data; UBYTE o; /* While TC_USER2 is set, measurements and empty frames will be traced always */ if (data AND ((trace_mask & TC_USER2) EQ 0)) { if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[2] EQ 0x01) AND (data[3] EQ 0x03) AND (data[4] EQ 0x49)) return; if ((trace_type EQ TRACE_DOWNLINK) OR (trace_type EQ TRACE_UPLINK)) { if ((ch_type EQ L2_CHANNEL_SACCH) AND (data[3] EQ 0x03) AND (data[4] EQ 0x01)) return; else if ( (data[1] EQ 0x03) AND (data[2] EQ 0x01)) return; } } trace_data = &trace_buffer; trace_data->sysClock = trace_time; if (!((trace_type EQ TRACE_PL_EVENT) OR (trace_type EQ TRACE_RR_EVENT))) { GET_INSTANCE_DATA; switch (channel) { case C_SACCH0: case C_DCCH0: trace_data->disc_request = dl_data->dcch0_disc_request; trace_data->state = dl_data->state [C_DCCH0]; trace_data->sapi = PS_SAPI_0; break; case C_DCCH3: trace_data->disc_request = dl_data->dcch3_disc_request; trace_data->state = dl_data->state [C_DCCH3]; trace_data->sapi = PS_SAPI_3; break; default: trace_data->disc_request = 0; trace_data->state = 0; trace_data->sapi = NOT_PRESENT_8BIT; break; } } if (data) { if ((trace_type EQ TRACE_UPLINK) OR (trace_type EQ TRACE_DOWNLINK)) { memcpy (trace_data->data, data, MAX_L2_FRAME_SIZE); } else { strncpy ((char *)trace_data->data, (char *)data, IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE-1); trace_data->data[IMM_TRACE_SIZE*MAX_L2_FRAME_SIZE-1] = 0; } } else { trace_data->data[0] = 0; } if (ch_type > ELEMENTS(CH_TYPE)) ch_type = 0; if (trace_data->sapi >= ELEMENTS (SAPI_TYPE)) trace_data->sapi = ELEMENTS (SAPI_TYPE) - 1; switch (trace_type) { case TRACE_UPLINK: case TRACE_DOWNLINK: sprintf (print_buffer, "DLTRC:%07lu %c%d %s %s%c ", trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, TRACE_TYPE[trace_type], CH_TYPE[ch_type], SAPI_TYPE[trace_data->sapi]); o = strlen (print_buffer); array2hex (trace_data->data, print_buffer+o, 23); break; case TRACE_DL_EVENT: sprintf (print_buffer, "DLTRC:%07lu %c%d Ev %s%c %s", trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[ch_type], SAPI_TYPE[trace_data->sapi], trace_data->data); break; case TRACE_PL_EVENT: case TRACE_RR_EVENT: sprintf (print_buffer, "DLTRC:%07lu %d Ev %s %s", trace_data->sysClock, trace_data->state, TRACE_TYPE[trace_type], trace_data->data); break; case TRACE_CHSTATE: sprintf (print_buffer, "DLTRC:%07lu %c%d ST %s%c state=%s", trace_data->sysClock, trace_data->disc_request?'D':' ', trace_data->state, CH_TYPE[ch_type], SAPI_TYPE[trace_data->sapi], STATES[trace_data->state]); break; default: print_buffer[0] = 0; break; } TRACE_USER_CLASS (TC_USER1, print_buffer); #if 0 if (print_buffer[0]) { #if defined(_SIMULATION_) TRACE_EVENT_WIN (print_buffer); #else /* _SIMULATION_ */ SYST_TRACE_P ((DLTRC,print_buffer)); #endif /* _SIMULATION_ */ } #endif /* 0 */ } #endif /* DL_IMMEDIATE_TRACE */ LOCAL void array2hex (UBYTE *inarray, char *outarray, int size) { int col=0, n=0; UBYTE b, nh, nl; while (n < size) { b = inarray[n++]; nh = b>>4; nl = b&0x0f; outarray[col++] = nh > 9 ? nh + 'A' - 10 : nh + '0'; outarray[col++] = nl > 9 ? nl + 'A' - 10 : nl + '0'; } outarray[col] = 0; } #endif /* DL_TRACE_ENABLED */ #if defined (DL_TRACE_PFREE) GLOBAL void* my_pfree(void *pointer, int line, char *file) { char buffer[23]; sprintf (buffer, "%s#%u:%p", file+2, line, pointer); dl_trace (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, buffer); if (pointer) { PFREE (pointer); } else { SYST_TRACE_P((SYST, "%s#%u: PFREE(NULL)", file, line)); } return NULL; } #endif /* DL_TRACE_PFREE */ #endif /* DL_TRACE_C */