diff src/g23m-aci/uart/uart_kers.c @ 1:d393cd9bb723

src/g23m-*: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:40:46 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-aci/uart/uart_kers.c	Sun Jul 15 04:40:46 2018 +0000
@@ -0,0 +1,2473 @@
+/*
++-----------------------------------------------------------------------------
+|  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 is part of the entity UART and implements all
+|             functions to handles the incoming process internal signals as
+|             described in the SDL-documentation (KER-statemachine)
++-----------------------------------------------------------------------------
+*/
+
+#ifndef UART_KERS_C
+#define UART_KERS_C
+#endif /* !UART_KERS_C */
+
+#define ENTITY_UART
+
+/*
+ * Turn off spurious LINT warnings
+ */
+ /*lint -e415 access of out-of-bounds pointer */
+
+/*==== INCLUDES =============================================================*/
+
+#ifdef WIN32
+#include "nucleus.h"
+#endif /* WIN32 */
+#include "typedefs.h"   /* to get Condat data types */
+#include "vsi.h"        /* to get a lot of macros */
+#include "macdef.h"     /* to get a lot of macros */
+#include "custom.h"
+#include "gsm.h"        /* to get a lot of macros */
+#include "cnf_uart.h"   /* to get cnf-definitions */
+#include "mon_uart.h"   /* to get mon-definitions */
+#include "prim.h"       /* to get the definitions of used SAP and directions */
+#include "dti.h"        /* to get dti lib */
+#include "pei.h"        /* to get PEI interface */
+#ifdef FF_MULTI_PORT
+#include "gsi.h"        /* to get definitions of serial driver */
+#else /* FF_MULTI_PORT */
+#ifdef _TARGET_
+#include "uart/serialswitch.h"
+#include "uart/traceswitch.h"
+#else /* _TARGET_ */
+#include "serial_dat.h" /* to get definitions of serial driver */
+#endif /* _TARGET_ */
+#endif /* FF_MULTI_PORT */
+#include "uart.h"       /* to get the global entity definitions */
+
+#ifdef FF_MULTI_PORT
+#include "uart_ptxs.h"  /* to get signal definitions for service TX */
+#include "uart_prxs.h"  /* to get rx signals */
+#else /* FF_MULTI_PORT */
+#include "uart_txs.h"   /* to get signal definitions of service TX */
+#include "uart_rxs.h"   /* to get signal definitions of service RX */
+#endif /* FF_MULTI_PORT */
+#include "uart_dtxs.h"  /* to get signal definitions of service DTX */
+#include "uart_drxs.h"  /* to get signal definitions of service DRX */
+#include "uart_kerf.h"  /* to get function definitions of service KER */
+#include "uart_rts.h"   /* to get signal definitions of service RT */
+
+#ifndef _TARGET_
+#include <stdio.h>      /* to get sprintf */
+#endif /* !_TARGET_ */
+#include <string.h>      /* JK, delete warnings: to get memcpy */
+
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_drx_ker_line_states_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_DRX_KER_LINE_STATES_IND
+|
+| Parameters  : dlc_instance - dlc instance wich belongs to calling DRX
+|               st_flow      - flow control state (X bit)
+|               st_line_sa   - line state SA
+|               st_line_sa   - line state SB
+|               st_break_len - break state
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_drx_ker_line_states_ind(UBYTE  dlc_instance,
+                                        UBYTE  st_flow,
+                                        UBYTE  st_line_sa,
+                                        UBYTE  st_line_sb,
+                                        USHORT st_break_len)
+{
+  T_DLC*  dlc;
+  ULONG   old_lines;
+  ULONG   new_lines;
+
+  TRACE_ISIG( "sig_drx_ker_line_states_ind" );
+
+  /*
+   * set DLC
+   */
+  dlc = &uart_data->dlc_table[dlc_instance];
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_READY:
+      /*
+       * check for changed line states
+       */
+      old_lines = dlc->lines & (UART_SA_TX_MASK |
+                                UART_SB_TX_MASK |
+                                UART_X_TX_MASK  |
+                                UART_BRK_TX_MASK);
+      new_lines = ((ULONG)st_line_sa << UART_SA_TX_POS) |
+                   ((ULONG)st_line_sb << UART_SB_TX_POS) |
+                   ((ULONG)st_flow    << UART_X_TX_POS);
+      if(st_break_len NEQ DTI_BREAK_OFF)
+      {
+        TRACE_EVENT("send Break");
+        new_lines|= UART_BRK_TX_MASK;
+      }
+
+      if(old_lines NEQ new_lines)
+      {
+        /*
+         * trace changes
+         */
+        if(new_lines & UART_X_TX_MASK)
+        {
+          if(!(old_lines & UART_X_TX_MASK))
+          {
+            TRACE_EVENT("TX Flow Control: stop");
+          }
+        }
+        else if(old_lines & UART_X_TX_MASK)
+        {
+          TRACE_EVENT("TX Flow Control: start");
+        }
+
+        if(new_lines & UART_SA_TX_MASK)
+        {
+          if(!(old_lines & UART_SA_TX_MASK))
+          {
+            TRACE_EVENT("DSR: off");
+          }
+        }
+        else if(old_lines & UART_SA_TX_MASK)
+        {
+          TRACE_EVENT("DSR: on");
+        }
+
+        if(new_lines & UART_SB_TX_MASK)
+        {
+          if(!(old_lines & UART_SB_TX_MASK))
+          {
+            TRACE_EVENT("DCD: off");
+          }
+        }
+        else if(old_lines & UART_SB_TX_MASK)
+        {
+          TRACE_EVENT("DCD: on");
+        }
+
+        /*
+         * send new line states
+         * but flush UART before
+         */
+        dlc->lines&= ~(UART_SA_TX_MASK  |
+                       UART_SB_TX_MASK  |
+                       UART_X_TX_MASK   |
+                       UART_BRK_TX_MASK |
+                       UART_BRKLEN_TX_MASK);
+
+        if(st_break_len NEQ DTI_BREAK_OFF)
+          new_lines|= ((ULONG)st_break_len << UART_BRKLEN_TX_POS);
+
+        dlc->lines|= new_lines;
+
+        dlc->received_prim|= UART_DTI_DATA_REQ_MASK;
+
+        if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
+        {
+          uart_data->ker.flush_state = UART_KER_TX_FLUSH;
+          sig_ker_tx_flush_req();
+        }
+      }
+      break;
+
+    case KER_MUX:
+      /*
+       * check for changed line states
+       */
+      old_lines = dlc->lines & (UART_CTS_MASK |
+                                UART_DSR_MASK |
+                                UART_DCD_MASK |
+                                UART_BRK_TX_MASK);
+      new_lines = ((ULONG)st_flow << UART_CTS_POS)    |
+                  ((ULONG)st_line_sa << UART_DSR_POS) |
+                  ((ULONG)st_line_sb << UART_DCD_POS);
+
+      if(st_break_len NEQ DTI_BREAK_OFF)
+      {
+        TRACE_EVENT_P1("send Break - DLCI=%d", dlc->dlci);
+        new_lines|= UART_BRK_TX_MASK;
+      }
+
+      if(old_lines NEQ new_lines)
+      {
+        /*
+         * trace changes
+         */
+        if(new_lines & UART_CTS_MASK)
+        {
+          if(!(old_lines & UART_CTS_MASK))
+          {
+            TRACE_EVENT_P1("TX Flow Control: stop - DLCI=%d", dlc->dlci);
+          }
+        }
+        else if(old_lines & UART_CTS_MASK)
+        {
+          TRACE_EVENT_P1("TX Flow Control: start - DLCI=%d", dlc->dlci);
+        }
+
+        if(new_lines & UART_DSR_MASK)
+        {
+          if(!(old_lines & UART_DSR_MASK))
+          {
+            TRACE_EVENT_P1("DSR: off - DLCI=%d", dlc->dlci);
+          }
+        }
+        else if(old_lines & UART_DSR_MASK)
+        {
+          TRACE_EVENT_P1("DSR: on - DLCI=%d", dlc->dlci);
+        }
+
+        if(new_lines & UART_DCD_MASK)
+        {
+          if(!(old_lines & UART_DCD_MASK))
+          {
+            TRACE_EVENT_P1("DCD: off - DLCI=%d", dlc->dlci);
+          }
+        }
+        else if(old_lines & UART_DCD_MASK)
+        {
+          TRACE_EVENT_P1("DCD: on - DLCI=%d", dlc->dlci);
+        }
+        /*
+         * build and send MSC command
+         */
+        dlc->lines&= ~(UART_CTS_MASK    |
+                       UART_DSR_MASK    |
+                       UART_DCD_MASK    |
+                       UART_BRK_TX_MASK |
+                       UART_BRKLEN_TX_MASK);
+
+        if(st_break_len NEQ DTI_BREAK_OFF)
+          new_lines|= ((ULONG)st_break_len << UART_BRKLEN_TX_POS);
+
+        dlc->lines|= new_lines;
+        ker_mux_send_line_states(dlc_instance);
+      }
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_DRX_KER_LINE_STATES_IND unexpected" );
+      break;
+  }
+} /* sig_drx_ker_line_states_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_dtx_ker_enable_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_DTX_KER_ENABLE_IND
+|
+| Parameters  : dlc_instance - dlc instance wich belongs to calling DTX
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_dtx_ker_enable_ind (UBYTE dlc_instance)
+{
+  TRACE_ISIG( "sig_dtx_ker_enable_ind" );
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_MUX:
+      /*
+       * build and send MSC command
+       * enable flow control in line states
+       */
+      uart_data->dlc_table[dlc_instance].lines&= ~UART_FC_TX_MASK;
+      /*
+       * send new line states
+       */
+      ker_mux_send_line_states(dlc_instance);
+      break;
+
+    case KER_READY:
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_DTX_KER_ENABLE_IND unexpected" );
+      break;
+  }
+} /* sig_dtx_ker_enable_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_dtx_ker_disable_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_DTX_KER_DISABLE_IND
+|
+| Parameters  : dlc_instance - dlc instance wich belongs to calling DTX
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_dtx_ker_disable_ind (UBYTE dlc_instance)
+{
+  TRACE_ISIG( "sig_dtx_ker_disable_ind" );
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_MUX:
+      /*
+       * build and send MSC command
+       * disable flow control in line states
+       */
+      uart_data->dlc_table[dlc_instance].lines|= UART_FC_TX_MASK;
+      /*
+       * send new line states
+       */
+      ker_mux_send_line_states(dlc_instance);
+      break;
+
+    case KER_READY:
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_DTX_KER_DISABLE_IND unexpected" );
+      break;
+  }
+} /* sig_dtx_ker_disable_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_dtx_ker_escape_detected_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_DTX_KER_ESCAPE_DETECTED_IND
+|
+| Parameters  : dlc_instance - dlc instance wich belongs to calling DTX
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_dtx_ker_escape_detected_ind (U8 dlc_instance)
+{
+  T_DLC *dlc;
+
+  TRACE_FUNCTION( "sig_dtx_ker_escape_detected_ind" );
+
+  /*
+   * set DLC
+   */
+  dlc = &uart_data->dlc_table[dlc_instance];
+  {
+    PALLOC (uart_detected_ind, UART_DETECTED_IND);
+    uart_detected_ind->device = uart_data->device;
+    uart_detected_ind->dlci   = dlc->dlci;
+    uart_detected_ind->cause  = UART_DETECT_ESC;
+    PSEND (hCommMMI, uart_detected_ind);
+  }
+} /* sig_dtx_ker_escape_detected_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_any_ker_flushed_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_ANY_KER_FLUSHED_IND
+|
+| Parameters  : dlc_instance - dlc instance wich belongs to this signal
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_any_ker_flushed_ind (UBYTE dlc_instance)
+{
+  T_DLC*  dlc;
+  UBYTE   i;
+
+  TRACE_ISIG( "sig_any_ker_flushed_ind" );
+
+  /*
+   * reset flush indicator
+   */
+  dlc          = &uart_data->dlc_table[dlc_instance];
+  dlc->flushed = TRUE;
+  /*
+   * if the primitive which has triggered the flush belongs to the whole port
+   * we will check each DLC for flush, if it only belongs to this DLC we start
+   * TX flushing immediately
+   */
+  if(uart_data->ker.received_prim)
+  {
+    /*
+     * check each DLC
+     */
+    for(i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+    {
+      dlc = &uart_data->dlc_table[i];
+      if(dlc->flushed NEQ TRUE)
+        return;
+    }
+  }
+  /*
+   * start TX flushing
+   */
+  uart_data->ker.flush_state = UART_KER_TX_FLUSH;
+  sig_ker_tx_flush_req();
+} /* sig_any_ker_flushed_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tx_ker_flushed_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TX_KER_FLUSHED_IND
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tx_ker_flushed_ind ()
+{
+  T_DLC*  dlc;
+  UBYTE   i;
+#ifndef  _SIMULATION_
+  USHORT  error_code;
+#endif
+  TRACE_ISIG( "sig_tx_ker_flushed_ind" );
+
+  if(uart_data->ker.flush_state EQ UART_KER_TX_FLUSH)
+  {
+    /*
+     * primitives of the port
+     */
+    /*
+     * UART_PARAMETERS_REQ
+     */
+    if(uart_data->ker.received_prim & UART_PARAMETERS_REQ_MASK)
+    {
+      /*
+       * disable UART while set new communication parameters
+       */
+#ifdef _SIMULATION_
+      {
+        /*
+         * send DTI_GETDATA_REQ
+         */
+        PALLOC (dti_getdata_req, DTI2_GETDATA_REQ);
+        dti_getdata_req->link_id = LINK_DISABLE_PORT_1; /* for disable */
+        PSEND (hCommMMI, dti_getdata_req);
+      }
+#else /* _SIMULATION_ */
+#ifndef FF_MULTI_PORT
+      if((error_code = UF_Enable (uart_data->device, FALSE)) NEQ UF_OK)
+      {
+          TRACE_ERROR_P2("UF Driver: Can't disable UART, [%d], uart_kerp.c(%d)",
+                                                           error_code,__LINE__);
+      }
+#endif /* !FF_MULTI_PORT */
+#endif /* _SIMULATION */
+      /*
+       * set new parameters
+       */
+      ker_setupUart();
+#ifdef _SIMULATION_
+      {
+        /*
+         * send DTI_GETDATA_REQ
+         */
+        PALLOC (dti_getdata_req, DTI2_GETDATA_REQ);
+        dti_getdata_req->link_id = LINK_ENABLE_PORT_1; /* for enable */
+        PSEND (hCommMMI, dti_getdata_req);
+      }
+#else /* _SIMULATION_ */
+#ifndef FF_MULTI_PORT
+      if((error_code = UF_Enable (uart_data->device, TRUE)) NEQ UF_OK)
+      {
+          TRACE_ERROR_P2("UF Driver: Can't enable UART, [%d], uart_kerp.c(%d)",
+                                                          error_code,__LINE__);
+      }
+#endif /* !FF_MULTI_PORT */
+#endif /* _SIMULATION */
+      /*
+       * restart suspended read and write procedures
+       */
+      sig_ker_tx_restart_write_req();
+      sig_ker_rx_restart_read_req();
+      /*
+       * send confirm primitive
+       */
+      {
+        PALLOC (uart_parameters_cnf, UART_PARAMETERS_CNF);
+        uart_parameters_cnf->device = uart_data->device;
+        PSEND (hCommMMI, uart_parameters_cnf);
+      }
+    }
+
+    /*
+     * UART_DISABLE_REQ
+     */
+    if(uart_data->ker.received_prim & UART_DISABLE_REQ_MASK)
+    {
+      switch( GET_STATE( UART_SERVICE_KER ) )
+      {
+        case KER_MUX:
+        case KER_MUX_ESTABLISH:
+        case KER_MUX_DLC_CLOSING:
+        case KER_MUX_CLOSING:
+        case KER_MUX_CLOSED:
+          /*
+           * stop timers and
+           * remove all DLC instances
+           */
+          ker_mux_close_down();
+          break;
+
+        case KER_READY:
+          /*
+           * close dlc channel
+           */
+          ker_mux_dlc_release(UART_CONTROL_INSTANCE);
+          break;
+
+        case KER_DEAD:
+          break;
+
+        default:
+          TRACE_ERROR( "SIG_TX_KER_FLUSHED_IND unexpected" );
+          break;
+      }
+
+      SET_STATE( UART_SERVICE_KER, KER_DEAD );
+
+      /*
+       * disable UART
+       */
+#ifdef _SIMULATION_
+      {
+        /*
+         * send DTI_GETDATA_REQ
+         */
+        PALLOC (dti_getdata_req, DTI2_GETDATA_REQ);
+        dti_getdata_req->link_id = LINK_DISABLE_PORT_1; /* for disable */
+        PSEND (hCommMMI, dti_getdata_req);
+      }
+#else /* _SIMULATION_ */
+#ifndef FF_MULTI_PORT
+      if((error_code = UF_Enable (uart_data->device, FALSE)) NEQ UF_OK)
+      {
+          TRACE_ERROR_P2("UF Driver: Can't disable UART, [%d], uart_kerp.c(%d)",
+                                                           error_code,__LINE__);
+      }
+#endif /* !FF_MULTI_PORT */
+#endif /* _SIMULATION */
+      sig_ker_rx_dead_mode_req();
+      sig_ker_tx_dead_mode_req();
+      /*
+       * send confirm primitive
+       */
+      {
+        PALLOC (uart_disable_cnf, UART_DISABLE_CNF);
+        uart_disable_cnf->device = uart_data->device;
+        PSEND (hCommMMI, uart_disable_cnf);
+      }
+    }
+
+    /*
+     * UART_MUX_START_REQ
+     */
+    if(uart_data->ker.received_prim & UART_MUX_START_REQ_MASK)
+    {
+      switch( GET_STATE( UART_SERVICE_KER ) )
+      {
+        case KER_READY:
+          /*
+           * close dlc channel
+           */
+          ker_mux_dlc_release(UART_CONTROL_INSTANCE);
+          break;
+
+        default:
+          TRACE_ERROR( "SIG_TX_KER_FLUSHED_IND unexpected" );
+          break;
+      }
+
+      SET_STATE( UART_SERVICE_KER, KER_MUX_ESTABLISH );
+
+      /*
+       * set RX and TX service in mux mode
+       */
+      sig_ker_rx_mux_mode_req();
+      sig_ker_tx_mux_mode_req();
+      /*
+       * start reception
+       */
+      MALLOC(uart_data->ker.rx_data_desc, (USHORT)(sizeof(T_desc2) -
+                                           1 +
+                                           uart_data->n1 +
+                                           2));
+      uart_data->ker.rx_data_desc->next = (ULONG)NULL;
+      uart_data->ker.rx_data_desc->len  = 0;
+      sig_ker_rx_ready_to_receive_req(uart_data->ker.rx_data_desc,
+                                      0,
+                                      (USHORT)(uart_data->n1 + 2));
+      /*
+       * start timer
+       */
+      sig_ker_rt_start_t3_req();
+
+      /*
+       * send confirm primitive
+       */
+      {
+        PALLOC (uart_mux_start_cnf, UART_MUX_START_CNF);
+        uart_mux_start_cnf->device = uart_data->device;
+        PSEND (hCommMMI, uart_mux_start_cnf);
+      }
+    }
+
+    /*
+     * UART_MUX_CLOSE_REQ
+     */
+    if(uart_data->ker.received_prim & UART_MUX_CLOSE_REQ_MASK)
+    {
+      switch( GET_STATE( UART_SERVICE_KER ) )
+      {
+        case KER_MUX_CLOSED:
+          if(uart_data->ker.receiving_state NEQ UART_KER_RECEIVING)
+          {
+            PALLOC(uart_mux_close_ind, UART_MUX_CLOSE_IND);
+            SET_STATE( UART_SERVICE_KER, KER_READY );
+            /*
+             * stop receiving
+             */
+            sig_ker_rx_not_ready_to_receive_req();
+            MFREE_DESC2(uart_data->ker.rx_data_desc);
+            uart_data->ker.rx_data_desc = NULL;
+            /*
+             * set dlc values
+             */
+            dlc           = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
+            dlc->drx      = &uart_data->drx_base[0];
+            dlc->dtx      = &uart_data->dtx_base[0];
+            dlc->dlci     = 0;
+            dlc->priority = 0;
+            /*
+             * set RX and TX in ready mode
+             */
+            sig_ker_rx_ready_mode_req();
+            sig_ker_tx_ready_mode_req();
+            /*
+             * set frame size for ready mode
+             */
+            uart_data->n1 = UART_N1_READY_MODE;
+            /*
+             * set DRX and DTX in ready mode
+             */
+            uart_data->dtx = dlc->dtx;
+            uart_data->drx = dlc->drx;
+            sig_ker_drx_ready_mode_req(UART_CONTROL_INSTANCE);
+            sig_ker_dtx_ready_mode_req(UART_CONTROL_INSTANCE);
+            /*
+             * inform ACI about entering ready mode
+             */
+            uart_mux_close_ind->device = uart_data->device;
+            PSEND(hCommMMI, uart_mux_close_ind);
+          }
+          break;
+
+        default:
+          TRACE_ERROR( "SIG_TX_KER_FLUSHED_IND unexpected" );
+          break;
+      }
+    }
+
+    /*
+     * no more UART port related primitives
+     * so clear all flags
+     */
+    uart_data->ker.received_prim = 0;
+
+    /*
+     * primitives of the DLC
+     */
+    for(i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+    {
+      dlc = &uart_data->dlc_table[i];
+      if(dlc->received_prim)
+      {
+        /*
+         * UART_RING_REQ
+         * UART_DCD_REQ
+         * DTI_DATA_REQ (line states)
+         */
+        if((dlc->received_prim & UART_RING_REQ_MASK)  ||
+           (dlc->received_prim & UART_DCD_REQ_MASK)   ||
+           (dlc->received_prim & UART_DTI_DATA_REQ_MASK))
+        {
+          /*
+           * send new line states
+           */
+          switch( GET_STATE( UART_SERVICE_KER ) )
+          {
+            case KER_READY:
+              sig_ker_tx_line_states_req(UART_CONTROL_INSTANCE);
+              break;
+
+            case KER_MUX:
+              /*
+               * send MSC frame to peer
+               */
+              ker_mux_send_line_states (uart_data->dlc_instance[dlc->dlci]);
+              break;
+
+            default:
+              if(dlc->received_prim & UART_RING_REQ_MASK)
+              {
+                TRACE_ERROR( "UART_RING_REQ unexpected" );
+              }
+              if(dlc->received_prim & UART_DCD_REQ_MASK)
+              {
+                TRACE_ERROR( "UART_DCD_REQ unexpected" );
+              }
+              break;
+          }
+          /*
+           * send confirm primitives
+           */
+          if(dlc->received_prim & UART_RING_REQ_MASK)
+          {
+            PALLOC (uart_ring_cnf, UART_RING_CNF);
+            uart_ring_cnf->device = uart_data->device;
+            uart_ring_cnf->dlci   = dlc->dlci;
+            PSEND (hCommMMI, uart_ring_cnf);
+          }
+          if(dlc->received_prim & UART_DCD_REQ_MASK)
+          {
+            PALLOC (uart_dcd_cnf, UART_DCD_CNF);
+            uart_dcd_cnf->device = uart_data->device;
+            uart_dcd_cnf->dlci   = dlc->dlci;
+            PSEND (hCommMMI, uart_dcd_cnf);
+          }
+        }
+        /*
+         * no more DLC related primitives
+         * so clear all flags
+         */
+        dlc->received_prim = 0;
+      }
+    }
+    uart_data->ker.flush_state = UART_KER_NOT_FLUSHING;
+  }
+} /* sig_tx_ker_flushed_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tx_ker_sending_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TX_KER_SENDING_IND
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tx_ker_sending_ind ()
+{
+  TRACE_ISIG( "sig_tx_ker_sending_ind" );
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_MUX_ESTABLISH:
+    case KER_MUX:
+    case KER_MUX_DLC_CLOSING:
+    case KER_MUX_CLOSING:
+    case KER_MUX_CLOSED:
+      uart_data->ker.sending_state = UART_KER_SENDING;
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_TX_KER_SENDING_IND unexpected" );
+      break;
+  }
+} /* sig_tx_ker_sending_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tx_ker_data_sent_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TX_KER_DATA_SENT_IND
+|
+| Parameters  : rest_data - not yet sent data
+|               write_pos - position where the not yet sent data starts
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tx_ker_data_sent_ind (T_desc2* rest_data, USHORT read_pos)
+{
+  TRACE_ISIG( "sig_tx_ker_data_sent_ind" );
+
+  /*
+   * free sent data descriptor
+   */
+  MFREE_DESC2(uart_data->ker.tx_data_desc);
+  uart_data->ker.tx_data_desc  = NULL;
+  uart_data->ker.sending_state = UART_KER_NOT_SENDING;
+  if(uart_data->ker.tx_data_waiting)
+  {
+    /*
+     * send next descriptor in waiting queue
+     */
+    uart_data->ker.tx_data_desc    = uart_data->ker.tx_data_waiting;
+    uart_data->ker.tx_data_waiting =
+      (T_desc2*)uart_data->ker.tx_data_waiting->next;
+    /*
+     * only one descriptor is sent at a time
+     */
+    uart_data->ker.tx_data_desc->next = (ULONG)NULL;
+    sig_ker_tx_data_available_req( uart_data->ker.tx_data_desc, 0);
+  }
+  else
+  {
+    switch( GET_STATE( UART_SERVICE_KER ) )
+    {
+      case KER_MUX_ESTABLISH:
+      case KER_MUX:
+      case KER_MUX_DLC_CLOSING:
+      case KER_MUX_CLOSING:
+        break;
+
+      case KER_MUX_CLOSED:
+        /*
+         * flush UART before enter ready mode
+         */
+        uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;
+
+        if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
+        {
+          uart_data->ker.flush_state = UART_KER_TX_FLUSH;
+          sig_ker_tx_flush_req();
+        }
+        break;
+
+      default:
+        TRACE_ERROR( "SIG_TX_KER_DATA_SENT_IND unexpected" );
+        break;
+    }
+  }
+} /* sig_tx_ker_data_sent_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rx_ker_receiving_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RX_KER_RECEIVING_IND
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rx_ker_receiving_ind ()
+{
+  TRACE_ISIG( "sig_rx_ker_receiving_ind" );
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_MUX_ESTABLISH:
+    case KER_MUX:
+    case KER_MUX_DLC_CLOSING:
+    case KER_MUX_CLOSING:
+    case KER_MUX_CLOSED:
+      uart_data->ker.receiving_state = UART_KER_RECEIVING;
+      break;
+    default:
+      TRACE_ERROR( "SIG_RX_KER_RECEIVING_IND unexpected" );
+      break;
+  }
+} /* sig_rx_ker_receiving_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rx_ker_data_received_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RX_KER_DATA_RECEIVED_IND
+|               which is used to process a received frame.
+|
+|               Precondition is that the frame has a length >2 without flags.
+|
+| Parameters  : received_data - received data
+|               write_pos     - write position for the next reception
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rx_ker_data_received_ind (T_desc2* received_data,
+                                          USHORT write_pos)
+{
+  UBYTE   i;
+  UBYTE   dlci;
+  T_DLC*  dlc;
+  ULONG   forward;
+  BOOL    continuous;
+
+  TRACE_ISIG( "sig_rx_ker_data_received_ind" );
+
+#ifndef _TARGET_
+  if(received_data->len)
+  {
+    USHORT  pos;
+    char    buf[90];
+    /*
+     * trace output
+     */
+    TRACE_EVENT("======= IN");
+    i   = 0;
+    pos = 0;
+    while(pos < received_data->len)
+    {
+      i+= sprintf(&buf[i], "0x%02x, ", received_data->buffer[pos]);
+      pos++;
+      if(i > 80)
+      {
+        TRACE_EVENT( buf );
+        i = 0;
+      }
+      else if(pos >= received_data->len)
+      {
+        TRACE_EVENT( buf );
+      }
+    }
+  }
+#endif /* !_TARGET_ */
+
+  uart_data->ker.receiving_state = UART_KER_NOT_RECEIVING;
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_MUX_ESTABLISH:
+      if(received_data->len EQ 0)
+      {
+        /*
+         * prepare next reception
+         */
+        sig_ker_rx_ready_to_receive_req(received_data,
+                                        write_pos,
+                                        (USHORT)(uart_data->n1 + 2));
+        break;
+      }
+      dlci = received_data->buffer[UART_OFFSET_ADDRESS] >> UART_DLCI_POS;
+      if((dlci EQ UART_DLCI_CONTROL) &&
+         (received_data->buffer[UART_OFFSET_CONTROL] EQ UART_SABM_FRAME))
+      {
+        /*
+         * analyze SABM frame
+         */
+        forward = 0;
+        ker_receive_sabm_frame(&forward, received_data);
+        /*
+         * set dlc value
+         */
+        dlc = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
+        if((forward & UART_FORWARD_SABM) &&
+           (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD) &&
+           (uart_data->dlc_instance[dlci] NEQ UART_CONTROL_INSTANCE))
+        {
+          SET_STATE( UART_SERVICE_KER, KER_MUX );
+          /*
+           * stop timer
+           */
+          sig_ker_rt_stop_t3_req();
+          /*
+           * setup dlc parameter
+           */
+          uart_data->dlc_instance[dlci] = UART_CONTROL_INSTANCE;
+          dlc->connection_state         = UART_CONNECTION_OPEN;
+          /*
+           * set priority
+           */
+          dlc->priority = 0;
+          /*
+           * send response frame
+           */
+          if(forward & UART_FORWARD_RESPONSE)
+          {
+            ker_mux_send_frame(received_data);
+            /*
+             * prepare next reception
+             */
+            MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
+                                                          + uart_data->n1
+                                                          + 2));
+            received_data->next = (ULONG)NULL;
+          }
+        }
+      }
+      /*
+       * prepare next reception
+       */
+      received_data->len = 0;
+      uart_data->ker.rx_data_desc = received_data;
+      sig_ker_rx_ready_to_receive_req(received_data,
+                                      0,
+                                      (USHORT)(uart_data->n1 + 2));
+      break;
+
+    case KER_MUX:
+      if(received_data->len EQ 0)
+      {
+        /*
+         * prepare next reception
+         */
+        sig_ker_rx_ready_to_receive_req(received_data,
+                                        write_pos,
+                                        (USHORT)(uart_data->n1 + 2));
+        break;
+      }
+      /*
+       * analyze frame and messages
+       */
+      forward = 0;
+      switch(received_data->buffer[UART_OFFSET_CONTROL])
+      {
+        case UART_SABM_FRAME:
+          ker_receive_sabm_frame(&forward, received_data);
+          break;
+
+        case UART_UA_FRAME:
+          ker_receive_ua_frame(&forward, received_data);
+          break;
+
+        case UART_DM_CONTROL_FRAME:
+        case UART_DM_DATA_FRAME:
+          ker_receive_dm_frame(&forward, received_data);
+          break;
+
+        case UART_DISC_FRAME:
+          ker_receive_disc_frame(&forward, received_data);
+          break;
+
+        case UART_UIH_CONTROL_FRAME:
+          ker_receive_uih_control_frame(&forward, received_data);
+          break;
+
+        case UART_UIH_DATA_FRAME:
+          ker_receive_uih_data_frame(&forward, received_data);
+          break;
+
+        default:
+        {
+          TRACE_EVENT_P2("Warning: Unexpected HDLC value: %d, uart_kers.c(%d)",
+                         received_data->buffer[UART_OFFSET_CONTROL], __LINE__);
+          break;
+        }
+      }
+      /*
+       * remove resonded frames and send next frames in command queue
+       */
+      for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+      {
+        dlc = &uart_data->dlc_table[i];
+        switch(dlc->connection_state)
+        {
+          case UART_CONNECTION_OPEN:
+          case UART_CONNECTION_DISC_SENT:
+            if((dlc->last_command NEQ NULL) &&
+               (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
+                UART_UIH_CONTROL_FRAME) &&
+               (dlc->last_command->len EQ UART_OFFSET_INFO))
+            {
+              /*
+               * remove responded UIH frame
+               */
+              MFREE_DESC2(dlc->last_command);
+              dlc->last_command = NULL;
+              uart_data->ker.nr_t2--;
+              if( uart_data->ker.nr_t2 EQ 0 )
+                sig_ker_rt_stop_t2_req();
+            }
+            if((dlc->last_command  EQ NULL) &&
+               (dlc->next_command NEQ NULL))
+            {
+              T_desc2* temp_desc;
+              /*
+               * transmit next command frame
+               */
+              dlc->last_command       = dlc->next_command;
+              dlc->next_command       = (T_desc2*)dlc->next_command->next;
+              dlc->last_command->next = (ULONG)NULL;
+
+              MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
+                                dlc->last_command->len));
+              temp_desc->next = (ULONG)NULL;
+              temp_desc->len  = dlc->last_command->len;
+              memcpy(temp_desc->buffer,
+                     dlc->last_command->buffer,
+                     dlc->last_command->len);
+
+              dlc->retransmissions = 0;
+              ker_mux_send_frame(temp_desc);
+
+              if(dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
+                 UART_UIH_CONTROL_FRAME)
+              {
+                uart_data->ker.nr_t2++;
+                sig_ker_rt_start_t2_req();
+              }
+              else
+              {
+                uart_data->ker.nr_t1++;
+                sig_ker_rt_start_t1_req();
+              }
+            }
+            break;
+
+          case UART_CONNECTION_DEAD:
+            break;
+
+          default:
+          {
+            TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
+                                                 dlc->connection_state, __LINE__);
+            break;
+          }
+        }
+      }
+      /*
+       * process results of analysis
+       */
+      if(forward)
+      {
+        for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+        {
+          if(i NEQ UART_CONTROL_INSTANCE)
+          {
+            /*
+             * set dlc values
+             */
+            dlc  = &uart_data->dlc_table[i];
+            dlci = dlc->dlci;
+            /*
+             * channel to open
+             */
+            if((forward & UART_FORWARD_SABM) &&
+               (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD) &&
+               (uart_data->dlc_instance[dlci] NEQ i))
+            {
+              PALLOC(uart_mux_dlc_establish_ind, UART_MUX_DLC_ESTABLISH_IND);
+              /*
+               * setup dlc parameter
+               */
+              uart_data->dlc_instance[dlci] = i;
+              dlc->drx = &uart_data->drx_base[i];
+              dlc->dtx = &uart_data->dtx_base[i];
+              /*
+               * set priority
+               */
+              if(dlci < 8)
+                dlc->priority = 7;
+              else if(dlci < 16)
+                dlc->priority = 15;
+              else if(dlci < 24)
+                dlc->priority = 23;
+              else if(dlci < 32)
+                dlc->priority = 31;
+              else if(dlci < 40)
+                dlc->priority = 39;
+              else if(dlci < 48)
+                dlc->priority = 47;
+              else if(dlci < 56)
+                dlc->priority = 55;
+              else
+                dlc->priority = 61;
+              /*
+               * store response frame and
+               * clear appropriate bit in forward mask
+               */
+              dlc->next_command = received_data;
+              forward          &= ~UART_FORWARD_RESPONSE;
+              /*
+               * create new reception frame
+               */
+              MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
+                                                            + uart_data->n1
+                                                            + 2));
+              received_data->next = (ULONG)NULL;
+              /*
+               * inform ACI about new DLC
+               */
+              uart_mux_dlc_establish_ind->device = uart_data->device;
+              uart_mux_dlc_establish_ind->dlci   = dlci;
+              uart_mux_dlc_establish_ind->
+                                     convergence = UART_MUX_CONVERGENCE_UOS;
+              uart_mux_dlc_establish_ind->n1     = uart_data->n1;
+              uart_mux_dlc_establish_ind->
+                                         service = UART_MUX_SERVICE_AT;
+              PSEND (hCommMMI, uart_mux_dlc_establish_ind);
+            }
+            /*
+             * channel to close
+             */
+            if((forward & UART_FORWARD_DLC_RELEASE) &&
+               (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
+               (dlci NEQ UART_DLCI_INVALID))
+            {
+              PALLOC(uart_mux_dlc_release_ind, UART_MUX_DLC_RELEASE_IND);
+              /*
+               * release channel
+               */
+              ker_mux_dlc_release(i);
+              /*
+               * inform ACI about DLC release
+               */
+              uart_mux_dlc_release_ind->device = uart_data->device;
+              uart_mux_dlc_release_ind->dlci   = dlci;
+              PSEND(hCommMMI, uart_mux_dlc_release_ind);
+            }
+            /*
+             * set Flow Control ON
+             */
+            if((forward & UART_FORWARD_FCON) &&
+               (dlc->connection_state EQ UART_CONNECTION_OPEN) &&
+               (!(dlc->lines & UART_FC_RX_MASK)))
+            {
+              uart_data->drx = dlc->drx;
+              sig_ker_drx_enable_req();
+            }
+            /*
+             * set Flow Control OFF
+             */
+            if((forward & UART_FORWARD_FCOFF) &&
+               (dlc->connection_state EQ UART_CONNECTION_OPEN) &&
+               (!(dlc->lines & UART_FC_RX_MASK)))
+            {
+              uart_data->drx = dlc->drx;
+              sig_ker_drx_disable_req();
+            }
+            /*
+             * send status lines
+             */
+            if((forward & UART_FORWARD_MSC) &&
+               (dlc->connection_state EQ UART_CONNECTION_OPEN))
+            {
+              UBYTE st_flow;
+              UBYTE st_line_sa;
+              UBYTE st_break_len;
+              /*
+               * send primitive if DTR drop is detected
+               */
+              if(dlc->lines & UART_DTR_MASK)
+              {
+                PALLOC (uart_detected_ind, UART_DETECTED_IND);
+                uart_detected_ind->device = uart_data->device;
+                uart_detected_ind->dlci   = dlc->dlci;
+                uart_detected_ind->cause  = UART_DETECT_DTR;
+                PSEND (hCommMMI, uart_detected_ind);
+              }
+              /*
+               * set line states
+               */
+              if(dlc->lines & UART_RTS_MASK)
+                st_flow = DTI_FLOW_OFF;
+              else
+                st_flow = DTI_FLOW_ON;
+              if(dlc->lines & UART_DTR_MASK)
+                st_line_sa = DTI_SA_OFF;
+              else
+                st_line_sa = DTI_SA_ON;
+              /*
+               * set break
+               */
+              if(dlc->lines & UART_BRK_RX_MASK)
+                st_break_len = (UBYTE)((dlc->lines & UART_BRKLEN_RX_MASK) >>
+                                                     UART_BRKLEN_RX_POS);
+              else
+                st_break_len = DTI_BREAK_OFF;
+              /*
+               * send flow control signals
+               */
+              if(uart_data->ker.data_flow_tx EQ UART_FLOW_ENABLED)
+              {
+                uart_data->drx = dlc->drx;
+                if(dlc->lines & UART_FC_RX_MASK)
+                  sig_ker_drx_disable_req();
+                else
+                  sig_ker_drx_enable_req();
+              }
+              /*
+               * send line states
+               */
+              uart_data->dtx = dlc->dtx;
+              sig_ker_dtx_line_states_req(st_flow,
+                                          st_line_sa,
+                                          DTI_SB_ON,
+                                          st_break_len);
+            }
+          }
+        }
+        /*
+         * send response frame
+         */
+        if(forward & UART_FORWARD_RESPONSE)
+        {
+          ker_mux_send_frame(received_data);
+          uart_data->ker.rx_data_desc = NULL;
+        }
+        /*
+         * Close-Down multiplexer
+         */
+        if(forward & UART_FORWARD_CLD)
+        {
+          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
+          /*
+           * stop timers and
+           * remove all DLC instances
+           */
+          ker_mux_close_down();
+          /*
+           * flush UART before change the state
+           */
+          if(uart_data->ker.tx_data_desc EQ NULL)
+          {
+            uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;
+
+            if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
+            {
+              uart_data->ker.flush_state = UART_KER_TX_FLUSH;
+              sig_ker_tx_flush_req();
+            }
+          }
+        }
+      }
+      /*
+       * prepare next reception
+       */
+      if(forward & UART_FORWARD_RESPONSE)
+      {
+        MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
+                                                      + uart_data->n1
+                                                      + 2));
+        received_data->next = (ULONG)NULL;
+      }
+      received_data->len = 0;
+      uart_data->ker.rx_data_desc = received_data;
+      sig_ker_rx_ready_to_receive_req(received_data,
+                                      0,
+                                      (USHORT)(uart_data->n1 + 2));
+      break;
+
+    case KER_MUX_DLC_CLOSING:
+      if(received_data->len EQ 0)
+      {
+        /*
+         * prepare next reception
+         */
+        sig_ker_rx_ready_to_receive_req(received_data,
+                                        write_pos,
+                                        (USHORT)(uart_data->n1 + 2));
+        break;
+      }
+      /*
+       * analyze frame and messages
+       */
+      forward = 0;
+      switch(received_data->buffer[UART_OFFSET_CONTROL])
+      {
+        case UART_SABM_FRAME:
+          ker_receive_sabm_frame(&forward, received_data);
+          break;
+
+        case UART_UA_FRAME:
+          ker_receive_ua_frame(&forward, received_data);
+          break;
+
+        case UART_DM_CONTROL_FRAME:
+        case UART_DM_DATA_FRAME:
+          ker_receive_dm_frame(&forward, received_data);
+          break;
+
+        case UART_DISC_FRAME:
+          ker_receive_disc_frame(&forward, received_data);
+          break;
+
+        case UART_UIH_CONTROL_FRAME:
+          ker_receive_uih_control_frame(&forward, received_data);
+          break;
+
+        case UART_UIH_DATA_FRAME:
+          ker_receive_uih_data_frame(&forward, received_data);
+          break;
+
+        default:
+        {
+          TRACE_EVENT_P2("Warning: Unexpected HDLC value: %d, uart_kers.c(%d)",
+                         received_data->buffer[UART_OFFSET_CONTROL], __LINE__);
+          break;
+        }
+      }
+      /*
+       * remove resonded frames and send next frames in command queue
+       */
+      for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+      {
+        dlc = &uart_data->dlc_table[i];
+        switch(dlc->connection_state)
+        {
+          case UART_CONNECTION_OPEN:
+          case UART_CONNECTION_DISC_SENT:
+            if((dlc->last_command NEQ NULL) &&
+               (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
+                UART_UIH_CONTROL_FRAME) &&
+               (dlc->last_command->len EQ UART_OFFSET_INFO))
+            {
+              /*
+               * remove responded UIH frame
+               */
+              MFREE_DESC2(dlc->last_command);
+              dlc->last_command = NULL;
+              uart_data->ker.nr_t2--;
+              if( uart_data->ker.nr_t2 EQ 0 )
+                sig_ker_rt_stop_t2_req();
+            }
+            if((dlc->last_command  EQ NULL) &&
+               (dlc->next_command NEQ NULL))
+            {
+              T_desc2* temp_desc;
+              /*
+               * transmit next command frame
+               */
+              dlc->last_command       = dlc->next_command;
+              dlc->next_command       = (T_desc2*)dlc->next_command->next;
+              dlc->last_command->next = (ULONG)NULL;
+
+              MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
+                                dlc->last_command->len));
+              temp_desc->next = (ULONG)NULL;
+              temp_desc->len  = dlc->last_command->len;
+              memcpy(temp_desc->buffer,
+                     dlc->last_command->buffer,
+                     dlc->last_command->len);
+
+              dlc->retransmissions = 0;
+              ker_mux_send_frame(temp_desc);
+
+              if(dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
+                 UART_UIH_CONTROL_FRAME)
+              {
+                uart_data->ker.nr_t2++;
+                sig_ker_rt_start_t2_req();
+              }
+              else
+              {
+                uart_data->ker.nr_t1++;
+                sig_ker_rt_start_t1_req();
+              }
+            }
+            break;
+
+          case UART_CONNECTION_DEAD:
+            break;
+
+          default:
+          {
+            TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
+                                                 dlc->connection_state, __LINE__);
+            break;
+          }
+        }
+      }
+      /*
+       * process results of analysis
+       */
+      if(forward)
+      {
+        continuous = FALSE;
+        for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+        {
+          if(i NEQ UART_CONTROL_INSTANCE)
+          {
+            /*
+             * set dlc values
+             */
+            dlc  = &uart_data->dlc_table[i];
+            dlci = dlc->dlci;
+            /*
+             * channel to open
+             */
+            if((forward & UART_FORWARD_SABM) &&
+               (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD))
+            {
+              /*
+               * reject all attempts to open a channel
+               */
+              received_data->buffer[UART_OFFSET_CONTROL] =
+                UART_DM_CONTROL_FRAME;
+              /*
+               * release channel
+               */
+              ker_mux_dlc_release(i);
+            }
+            /*
+             * channel to close
+             */
+            if((forward & UART_FORWARD_DLC_RELEASE) &&
+               (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
+               (dlci NEQ UART_DLCI_INVALID))
+            {
+              /*
+               * release channel
+               */
+              ker_mux_dlc_release(i);
+            }
+            if(dlc->connection_state NEQ UART_CONNECTION_DEAD)
+              continuous = TRUE;
+          }
+        }
+        /*
+         * send response frame
+         */
+        if(forward & UART_FORWARD_RESPONSE)
+        {
+          ker_mux_send_frame(received_data);
+          uart_data->ker.rx_data_desc = NULL;
+        }
+        /*
+         * Close-Down multiplexer
+         */
+        if(forward & UART_FORWARD_CLD)
+        {
+          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
+          /*
+           * stop timers and
+           * remove all DLC instances
+           */
+          ker_mux_close_down();
+          /*
+           * flush UART before change the state
+           */
+          if(uart_data->ker.tx_data_desc EQ NULL)
+          {
+            uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;
+
+            if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
+            {
+              uart_data->ker.flush_state = UART_KER_TX_FLUSH;
+              sig_ker_tx_flush_req();
+            }
+          }
+        }
+        /*
+         * change state if all channels are closed
+         */
+        else if(continuous EQ FALSE)
+        {
+          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSING );
+          /*
+           * build and send CLD command frame:
+           */
+          ker_mux_send_close_down();
+          /*
+           * start timer
+           */
+          sig_ker_rt_start_t3_req();
+        }
+      }
+      /*
+       * prepare next reception
+       */
+      if(forward & UART_FORWARD_RESPONSE)
+      {
+        MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
+                                                      + uart_data->n1
+                                                      + 2));
+        received_data->next = (ULONG)NULL;
+      }
+      received_data->len = 0;
+      uart_data->ker.rx_data_desc = received_data;
+      sig_ker_rx_ready_to_receive_req(received_data,
+                                      0,
+                                      (USHORT)(uart_data->n1 + 2));
+      break;
+
+    case KER_MUX_CLOSING:
+      if(received_data->len EQ 0)
+      {
+        /*
+         * prepare next reception
+         */
+        sig_ker_rx_ready_to_receive_req(received_data,
+                                        write_pos,
+                                        (USHORT)(uart_data->n1 + 2));
+        break;
+      }
+      /*
+       * analyze frame and messages
+       */
+      forward = 0;
+      switch(received_data->buffer[UART_OFFSET_CONTROL])
+      {
+        case UART_SABM_FRAME:
+          ker_receive_sabm_frame(&forward, received_data);
+          break;
+
+        case UART_UA_FRAME:
+          ker_receive_ua_frame(&forward, received_data);
+          break;
+
+        case UART_DM_CONTROL_FRAME:
+        case UART_DM_DATA_FRAME:
+          ker_receive_dm_frame(&forward, received_data);
+          break;
+
+        case UART_DISC_FRAME:
+          ker_receive_disc_frame(&forward, received_data);
+          break;
+
+        case UART_UIH_CONTROL_FRAME:
+          ker_receive_uih_control_frame(&forward, received_data);
+          break;
+
+        case UART_UIH_DATA_FRAME:
+          ker_receive_uih_data_frame(&forward, received_data);
+          break;
+
+        default:
+        {
+          TRACE_EVENT_P2("Warning: Unexpected HDLC value: %d, uart_kers.c(%d)",
+                         received_data->buffer[UART_OFFSET_CONTROL], __LINE__);
+          break;
+        }
+      }
+      /*
+       * remove resonded frames and send next frames in command queue
+       */
+      for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+      {
+        dlc = &uart_data->dlc_table[i];
+        switch(dlc->connection_state)
+        {
+          case UART_CONNECTION_OPEN:
+          case UART_CONNECTION_DISC_SENT:
+            if((dlc->last_command NEQ NULL) &&
+               (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
+                UART_UIH_CONTROL_FRAME) &&
+               (dlc->last_command->len EQ UART_OFFSET_INFO))
+            {
+              /*
+               * remove responded UIH frame
+               */
+              MFREE_DESC2(dlc->last_command);
+              dlc->last_command = NULL;
+              uart_data->ker.nr_t2--;
+              if( uart_data->ker.nr_t2 EQ 0 )
+                sig_ker_rt_stop_t2_req();
+            }
+            if((dlc->last_command  EQ NULL) &&
+               (dlc->next_command NEQ NULL))
+            {
+              T_desc2* temp_desc;
+              /*
+               * transmit next command frame
+               */
+              dlc->last_command       = dlc->next_command;
+              dlc->next_command       = (T_desc2*)dlc->next_command->next;
+              dlc->last_command->next = (ULONG)NULL;
+
+              MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
+                                dlc->last_command->len));
+              temp_desc->next = (ULONG)NULL;
+              temp_desc->len  = dlc->last_command->len;
+              memcpy(temp_desc->buffer,
+                     dlc->last_command->buffer,
+                     dlc->last_command->len);
+
+              dlc->retransmissions = 0;
+              ker_mux_send_frame(temp_desc);
+
+              if(dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
+                 UART_UIH_CONTROL_FRAME)
+              {
+                uart_data->ker.nr_t2++;
+                sig_ker_rt_start_t2_req();
+              }
+              else
+              {
+                uart_data->ker.nr_t1++;
+                sig_ker_rt_start_t1_req();
+              }
+            }
+            break;
+
+          case UART_CONNECTION_DEAD:
+            break;
+
+          default:
+          {
+            TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
+                                                  dlc->connection_state,__LINE__);
+            break;
+          }
+        }
+      }
+      /*
+       * process results of analysis
+       */
+      if(forward)
+      {
+        for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
+        {
+          if(i NEQ UART_CONTROL_INSTANCE)
+          {
+            /*
+             * set dlc values
+             */
+            dlc  = &uart_data->dlc_table[i];
+            dlci = dlc->dlci;
+            /*
+             * channel to open
+             */
+            if((forward & UART_FORWARD_SABM) &&
+               (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD))
+            {
+              /*
+               * reject all attempts to open a channel
+               */
+              received_data->buffer[UART_OFFSET_CONTROL] =
+                UART_DM_CONTROL_FRAME;
+              /*
+               * release channel
+               */
+              ker_mux_dlc_release(i);
+            }
+            /*
+             * channel to close
+             */
+            if((forward & UART_FORWARD_DLC_RELEASE) &&
+               (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
+               (dlci NEQ UART_DLCI_INVALID))
+            {
+              /*
+               * release channel
+               */
+              ker_mux_dlc_release(i);
+            }
+          }
+        }
+        /*
+         * send response frame
+         */
+        if(forward & UART_FORWARD_RESPONSE)
+        {
+          ker_mux_send_frame(received_data);
+          uart_data->ker.rx_data_desc = NULL;
+        }
+        /*
+         * Close-Down multiplexer
+         */
+        if(forward & UART_FORWARD_CLD)
+        {
+          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
+          /*
+           * stop timers and
+           * remove all DLC instances
+           */
+          ker_mux_close_down();
+          /*
+           * flush UART before change the state
+           */
+          if(uart_data->ker.tx_data_desc EQ NULL)
+          {
+            uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;
+
+            if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
+            {
+              uart_data->ker.flush_state = UART_KER_TX_FLUSH;
+              sig_ker_tx_flush_req();
+            }
+          }
+        }
+      }
+      /*
+       * prepare next reception
+       */
+      if(forward & UART_FORWARD_RESPONSE)
+      {
+        MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
+                                                      + uart_data->n1
+                                                      + 2));
+        received_data->next = (ULONG)NULL;
+      }
+      received_data->len = 0;
+      uart_data->ker.rx_data_desc = received_data;
+      sig_ker_rx_ready_to_receive_req(received_data,
+                                      0,
+                                      (USHORT)(uart_data->n1 + 2));
+      break;
+
+    case KER_MUX_CLOSED:
+      if((uart_data->ker.tx_data_desc EQ NULL) &&
+         (uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING))
+      {
+        PALLOC(uart_mux_close_ind, UART_MUX_CLOSE_IND);
+        SET_STATE( UART_SERVICE_KER, KER_READY );
+        /*
+         * free receiving buffer
+         */
+        MFREE_DESC2(uart_data->ker.rx_data_desc);
+        uart_data->ker.rx_data_desc = NULL;
+        /*
+         * set dlc values
+         */
+        dlc            = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
+        dlc->drx       = &uart_data->drx_base[0];
+        dlc->dtx       = &uart_data->dtx_base[0];
+        dlc->dlci      = 0;
+        dlc->priority  = 0;
+        /*
+         * set RX and TX in ready mode
+         */
+        sig_ker_rx_ready_mode_req();
+        sig_ker_tx_ready_mode_req();
+        /*
+         * set frame size for ready mode
+         */
+        uart_data->n1 = UART_N1_READY_MODE;
+        /*
+         * set DRX and DTX in ready mode
+         */
+        uart_data->dtx = dlc->dtx;
+        uart_data->drx = dlc->drx;
+        sig_ker_drx_ready_mode_req(UART_CONTROL_INSTANCE);
+        sig_ker_dtx_ready_mode_req(UART_CONTROL_INSTANCE);
+        /*
+         * inform ACI about entering ready mode
+         */
+        uart_mux_close_ind->device = uart_data->device;
+        PSEND(hCommMMI, uart_mux_close_ind);
+      }
+      else if(received_data->len EQ 0)
+      {
+        /*
+         * prepare next reception
+         */
+        sig_ker_rx_ready_to_receive_req(received_data,
+                                        write_pos,
+                                        (USHORT)(uart_data->n1 + 2));
+      }
+      else
+      {
+        /*
+         * prepare next reception
+         */
+        received_data->len = 0;
+        sig_ker_rx_ready_to_receive_req(received_data,
+                                        0,
+                                        (USHORT)(uart_data->n1 + 2));
+      }
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_RX_KER_DATA_RECEIVED_IND unexpected" );
+      break;
+  }
+} /* sig_rx_ker_data_received_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rx_ker_line_states_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RX_KER_LINE_STATES_IND
+|
+| Parameters  : line_states - new line states
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rx_ker_line_states_ind (ULONG line_states)
+{
+  T_DLC*  dlc;
+  UBYTE   st_flow;
+  UBYTE   st_line_sa;
+  UBYTE   st_line_sb;
+  UBYTE   st_break_len;
+
+  TRACE_ISIG( "sig_rx_ker_line_states_ind" );
+
+  /*
+   * set DLC
+   */
+  dlc = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
+  /*
+   * send primitive if escape sequence or DTR drop is detected
+   */
+  if(line_states & UART_ESC_RX_MASK)
+  {
+    PALLOC (uart_detected_ind, UART_DETECTED_IND);
+    uart_detected_ind->device = uart_data->device;
+    uart_detected_ind->dlci   = dlc->dlci;
+    uart_detected_ind->cause  = UART_DETECT_ESC;
+    PSEND (hCommMMI, uart_detected_ind);
+  }
+  if((line_states & UART_DTR_MASK) AND
+     (!(dlc->lines & UART_DTR_MASK)))
+  {
+    PALLOC (uart_detected_ind, UART_DETECTED_IND);
+    uart_detected_ind->device = uart_data->device;
+    uart_detected_ind->dlci   = dlc->dlci;
+    uart_detected_ind->cause  = UART_DETECT_DTR;
+    PSEND (hCommMMI, uart_detected_ind);
+  }
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_READY:
+      /*
+       * set line states
+       */
+      if(line_states & UART_X_RX_MASK)
+        st_flow = DTI_FLOW_OFF;
+      else
+        st_flow = DTI_FLOW_ON;
+
+      if(line_states & UART_SA_RX_MASK)
+        st_line_sa = DTI_SA_OFF;
+      else
+        st_line_sa = DTI_SA_ON;
+
+      if(line_states & UART_SB_RX_MASK)
+        st_line_sb = DTI_SB_OFF;
+      else
+        st_line_sb = DTI_SB_ON;
+
+      if(line_states & UART_BRK_RX_MASK)
+        st_break_len = (UBYTE)((line_states & UART_BRKLEN_RX_MASK)
+                               >> UART_BRKLEN_RX_POS);
+      else
+        st_break_len = DTI_BREAK_OFF;
+
+      uart_data->dtx = dlc->dtx;
+      sig_ker_dtx_line_states_req(st_flow,
+                                  st_line_sa,
+                                  st_line_sb,
+                                  st_break_len);
+      break;
+
+    case KER_MUX_ESTABLISH:
+    case KER_MUX:
+    case KER_MUX_DLC_CLOSING:
+    case KER_MUX_CLOSING:
+    case KER_MUX_CLOSED:
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_RX_KER_LINE_STATES_IND unexpected" );
+      break;
+  }
+  /*
+   * store new line states
+   */
+  dlc->lines &= ~(UART_X_RX_MASK   |
+                  UART_SA_RX_MASK  |
+                  UART_SB_RX_MASK  |
+                  UART_ESC_RX_MASK |
+                  UART_BRK_RX_MASK |
+                  UART_BRKLEN_RX_MASK);
+  line_states&= ~(UART_ESC_RX_MASK |
+                  UART_BRK_RX_MASK |
+                  UART_BRKLEN_RX_MASK);
+  dlc->lines |= line_states;
+} /* sig_rx_ker_line_states_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rt_ker_timeout_t1_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_T1_IND
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rt_ker_timeout_t1_ind ()
+{
+  UBYTE   i;
+  T_desc2* temp_desc;
+  T_DLC*  dlc;
+  UBYTE   j;
+  UBYTE   dlci;
+  ULONG   forward;
+  BOOL    continuous;
+
+  TRACE_ISIG( "sig_rt_ker_timeout_t1_ind" );
+
+  for( i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++ )
+  {
+    /*
+     * set dlc value
+     */
+    dlc = &uart_data->dlc_table[i];
+    switch(dlc->connection_state)
+    {
+      case UART_CONNECTION_OPEN:
+      case UART_CONNECTION_DISC_SENT:
+        /*
+         * T1 is used for non UIH Control frames
+         */
+        if((dlc->last_command NEQ NULL) &&
+           (dlc->last_command->buffer[UART_OFFSET_CONTROL] NEQ
+             UART_UIH_CONTROL_FRAME))
+        {
+          if(dlc->retransmissions < uart_data->ker.n2)
+          {
+            /*
+             * retransmission of Control frame
+             */
+            dlc->retransmissions++;
+            MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
+              + dlc->last_command->len));
+
+            temp_desc->next = (ULONG)NULL;
+            temp_desc->len  = dlc->last_command->len;
+            memcpy(temp_desc->buffer,
+                   dlc->last_command->buffer,
+                   dlc->last_command->len);
+
+            ker_mux_send_frame( temp_desc );
+          }
+          else
+          {
+            /*
+             * maximum number of retransmissions reached
+             */
+            switch( GET_STATE( UART_SERVICE_KER ) )
+            {
+              case KER_MUX:
+                /*
+                 * act as on reception of a DM frame
+                 */
+                /*
+                 * create DM frame
+                 */
+                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 + 2));
+                temp_desc->next = (ULONG)NULL;
+                temp_desc->len  = 2;
+                memcpy(temp_desc->buffer, dlc->last_command->buffer, 2)
+                ;/*lint !e419 !e420 apparent data overrun and access beyond array*/
+                temp_desc->buffer[UART_OFFSET_CONTROL] = UART_DM_CONTROL_FRAME;
+                /*
+                 * act as on reception of a DM frame
+                 */
+                forward = 0;
+                ker_receive_dm_frame(&forward, temp_desc);
+                /*
+                 * process results of analysis
+                 */
+                if(forward)
+                {
+                  for(j=0; j <= UART_MAX_NUMBER_OF_CHANNELS; j++)
+                  {
+                    if(j NEQ UART_CONTROL_INSTANCE)
+                    {
+                      /*
+                       * set dlc values
+                       */
+                      dlc  = &uart_data->dlc_table[j];
+                      dlci = dlc->dlci;
+                      /*
+                       * channel to close
+                       */
+                      if((forward & UART_FORWARD_DLC_RELEASE) &&
+                         (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
+                         (dlci NEQ UART_DLCI_INVALID))
+                      {
+                        PALLOC(uart_mux_dlc_release_ind,
+                               UART_MUX_DLC_RELEASE_IND);
+                        /*
+                         * release channel
+                         */
+                        ker_mux_dlc_release(j);
+                        /*
+                         * inform ACI about DLC release
+                         */
+                        uart_mux_dlc_release_ind->device = uart_data->device;
+                        uart_mux_dlc_release_ind->dlci   = dlci;
+                        PSEND(hCommMMI, uart_mux_dlc_release_ind);
+                      }
+                    }
+                  }
+                }
+                break;
+
+              case KER_MUX_DLC_CLOSING:
+                /*
+                 * act as on reception of a DM frame
+                 */
+                /*
+                 * create DM frame
+                 */
+                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 + 2));
+                temp_desc->next = (ULONG)NULL;
+                temp_desc->len  = 2;
+                memcpy(temp_desc->buffer, dlc->last_command->buffer, 2)
+                ;/*lint !e419 !e420 apparent data overrun and access beyond array*/
+                temp_desc->buffer[UART_OFFSET_CONTROL] = UART_DM_CONTROL_FRAME;
+                /*
+                 * act as on reception of a DM frame
+                 */
+                forward = 0;
+                ker_receive_dm_frame(&forward, temp_desc);
+                /*
+                 * process results of analysis
+                 */
+                if(forward)
+                {
+                  continuous = FALSE;
+                  for(j=0; j <= UART_MAX_NUMBER_OF_CHANNELS; j++)
+                  {
+                    if(j NEQ UART_CONTROL_INSTANCE)
+                    {
+                      /*
+                       * set dlc values
+                       */
+                      dlc  = &uart_data->dlc_table[j];
+                      dlci = dlc->dlci;
+                      /*
+                       * channel to close
+                       */
+                      if((forward & UART_FORWARD_DLC_RELEASE) &&
+                         (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
+                         (dlci NEQ UART_DLCI_INVALID))
+                      {
+                        /*
+                         * release channel
+                         */
+                        ker_mux_dlc_release(j);
+                      }
+                      if(dlc->connection_state NEQ UART_CONNECTION_DEAD)
+                        continuous = TRUE;
+                    }
+                  }
+                  /*
+                   * change state if all channels are closed
+                   */
+                  if(continuous EQ FALSE)
+                  {
+                    SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSING );
+                    /*
+                     * build and send CLD command frame:
+                     */
+                    ker_mux_send_close_down();
+                    /*
+                     * start timer
+                     */
+                    sig_ker_rt_start_t3_req();
+                  }
+                }
+                break;
+
+              case KER_MUX_CLOSING:
+                /*
+                 * do not care about retransmission couter
+                 * retransmission stops if T3 expires
+                 */
+                dlc->retransmissions++;
+                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
+                  + dlc->last_command->len));
+
+                temp_desc->next = (ULONG)NULL;
+                temp_desc->len  = dlc->last_command->len;
+                memcpy(temp_desc->buffer,
+                       dlc->last_command->buffer,
+                       dlc->last_command->len);
+
+                ker_mux_send_frame( temp_desc );
+                break;
+
+              default:
+                TRACE_ERROR( "SIG_RT_KER_TIMEOUT_T1_IND unexpected" );
+                break;
+            }
+          }
+        }
+        break;
+
+      case UART_CONNECTION_DEAD:
+        break;
+
+      default:
+      {
+        TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
+                                             dlc->connection_state, __LINE__);
+        break;
+      }
+    }
+  }
+  if(uart_data->ker.nr_t1)
+  {
+    /*
+     * restart timer t1
+     */
+    sig_ker_rt_start_t1_req();
+  }
+} /* sig_rt_ker_timeout_t1_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rt_ker_timeout_t2_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_T2_IND
+|
+|               This signal means that no response to a sent command frame
+|               was received within the allowed time. It is assumed that
+|               the frame has been lost and a retransmission is done if the
+|               maximum number of retransmissions is not reached yet.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rt_ker_timeout_t2_ind ()
+{
+  UBYTE   i;
+  T_desc2* temp_desc;
+  T_DLC*  dlc;
+
+  TRACE_ISIG( "sig_rt_ker_timeout_t2_ind" );
+
+  for( i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++ )
+  {
+    /*
+     * set dlc value
+     */
+    dlc = &uart_data->dlc_table[i];
+    switch(dlc->connection_state)
+    {
+      case UART_CONNECTION_OPEN:
+      case UART_CONNECTION_DISC_SENT:
+        /*
+         * T2 is only used for UIH Control frames
+         */
+        if((dlc->last_command NEQ NULL) &&
+           (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
+             UART_UIH_CONTROL_FRAME))
+        {
+          if(dlc->retransmissions < uart_data->ker.n2)
+          {
+            /*
+             * retransmission of Control frame
+             */
+            dlc->retransmissions++;
+            MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
+              + dlc->last_command->len));
+
+            temp_desc->next = (ULONG)NULL;
+            temp_desc->len  = dlc->last_command->len;
+            memcpy(temp_desc->buffer,
+                   dlc->last_command->buffer,
+                   dlc->last_command->len);
+
+            ker_mux_send_frame( temp_desc );
+          }
+          else
+          {
+            /*
+             * maximum number of retransmissions reached
+             */
+            switch( GET_STATE( UART_SERVICE_KER ) )
+            {
+              case KER_MUX:
+              case KER_MUX_DLC_CLOSING:
+                /*
+                 * skip this frame and send next frame
+                 */
+                /*
+                 * remove current UIH frame
+                 */
+                MFREE_DESC2(dlc->last_command);
+                dlc->last_command = NULL;
+                uart_data->ker.nr_t2--;
+                if(dlc->next_command)
+                {
+                  /*
+                   * transmit next command frame
+                   */
+                  dlc->last_command       = dlc->next_command;
+                  dlc->next_command       = (T_desc2*)dlc->next_command->next;
+                  dlc->last_command->next = (ULONG)NULL;
+
+                  MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
+                                    dlc->last_command->len));
+                  temp_desc->next = (ULONG)NULL;
+                  temp_desc->len  = dlc->last_command->len;
+                  memcpy(temp_desc->buffer,
+                         dlc->last_command->buffer,
+                         dlc->last_command->len);
+
+                  dlc->retransmissions = 0;
+                  ker_mux_send_frame(temp_desc);
+                  uart_data->ker.nr_t2++;
+                }
+                break;
+
+              case KER_MUX_CLOSING:
+                /*
+                 * do not care about retransmission couter
+                 * retransmission stops if T3 expires
+                 */
+                dlc->retransmissions++;
+                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
+                  + dlc->last_command->len));
+
+                temp_desc->next = (ULONG)NULL;
+                temp_desc->len  = dlc->last_command->len;
+                memcpy(temp_desc->buffer,
+                       dlc->last_command->buffer,
+                       dlc->last_command->len);
+
+                ker_mux_send_frame( temp_desc );
+                break;
+
+              default:
+                TRACE_ERROR( "SIG_RT_KER_TIMEOUT_T2_IND unexpected" );
+                break;
+            }
+          }
+        }
+        break;
+
+      case UART_CONNECTION_DEAD:
+        break;
+
+      default:
+      {
+        TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
+                                             dlc->connection_state, __LINE__);
+        break;
+      }
+    }
+  }
+  if(uart_data->ker.nr_t2)
+  {
+    /*
+     * restart timer t2
+     */
+    sig_ker_rt_start_t2_req();
+  }
+} /* sig_rt_ker_timeout_t2_ind() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rt_ker_timeout_t3_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_T3_IND
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rt_ker_timeout_t3_ind ()
+{
+  TRACE_ISIG( "sig_rt_ker_timeout_t3_ind" );
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_MUX_ESTABLISH:
+    case KER_MUX_CLOSING:
+      SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
+      /*
+       * stop timers and
+       * remove all DLC instances
+       */
+      ker_mux_close_down();
+      if(uart_data->ker.tx_data_desc EQ NULL)
+      {
+        uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;
+
+        if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
+        {
+          uart_data->ker.flush_state = UART_KER_TX_FLUSH;
+          sig_ker_tx_flush_req();
+        }
+      }
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_RT_KER_TIMEOUT_T3_IND unexpected" );
+      break;
+  }
+} /* sig_rt_ker_timeout_t3_ind() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_rt_ker_timeout_tesd_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_TESD_IND
+|
+|               This signal means that the trailing guard period has completed.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_rt_ker_timeout_tesd_ind ()
+{
+  UBYTE   i;
+
+  TRACE_ISIG( "sig_rt_ker_timeout_tesd_ind" );
+
+  switch( GET_STATE( UART_SERVICE_KER ) )
+  {
+    case KER_READY:
+    case KER_MUX:
+      for( i = 0; i < UART_MAX_NUMBER_OF_CHANNELS; i++ )
+      { /*
+         * set current dtx
+         */
+        uart_data->dtx = &uart_data->dtx_base[i];
+        sig_ker_dtx_timeout_tesd_req();
+      }
+      break;
+
+    default:
+      TRACE_ERROR( "SIG_RT_KER_TIMEOUT_TESD_IND unexpected" );
+      break;
+  }
+} /* sig_rt_ker_timeout_tesd_ind() */
+