2086 lines
71 KiB
C
2086 lines
71 KiB
C
/******************************************************************************
|
|
*
|
|
* Freescale Semiconductor Inc.
|
|
* (c) Copyright 2008-2015 Freescale Semiconductor, Inc.
|
|
* ALL RIGHTS RESERVED.
|
|
*
|
|
******************************************************************************/
|
|
/**************************************************************************//**
|
|
* @addtogroup transport_group
|
|
* @{
|
|
******************************************************************************/
|
|
/**************************************************************************//**
|
|
*
|
|
* @file lin_commontl_proto.c
|
|
*
|
|
* @author FPT Software
|
|
*
|
|
* @brief Common Handle LIN transport layer and configuration functions
|
|
*
|
|
******************************************************************************/
|
|
/******************************************************************************
|
|
*
|
|
* History:
|
|
*
|
|
* 20090409 v1.0 First version
|
|
* 20111005 v1.1 Added code for save configuration request and response
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "lin_commontl_proto.h"
|
|
#include "lin_diagnostic_service.h"
|
|
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
#include "lin_commontl_api.h"
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/* Define functionality */
|
|
#ifndef MULTI_PDU_SUPPORT
|
|
#define MULTI_PDU_SUPPORT 0 /**< multi PDU support */
|
|
#endif /* MULTI_PDU_SUPPORT */
|
|
|
|
/********------------- Code supports SINGLE interface ----------------**********/
|
|
|
|
#if LIN_MODE == _SLAVE_MODE_
|
|
/* Unuse for GPIO */
|
|
#if (_LIN_GPIO_ == 0) && !defined(_MC9S08SC4_H) && !defined(MCU_SKEAZN84)
|
|
/*************************** FUNCTIONS *******************/
|
|
|
|
|
|
void lin_tl_make_slaveres_pdu
|
|
(
|
|
/* [IN] service identifier */
|
|
l_u8 sid,
|
|
/* [IN] type of response */
|
|
l_u8 res_type,
|
|
/* [IN] Error code in case of negative response, if positive = 0 */
|
|
l_u8 error_code
|
|
|
|
)
|
|
{
|
|
lin_tl_pdu_data lin_tl_pdu;
|
|
l_u8 i;
|
|
|
|
lin_tl_pdu[0] = lin_configured_NAD; /* NAD */
|
|
lin_tl_pdu[1] = 0x03; /* PCI */
|
|
lin_tl_pdu[2] = RES_NEGATIVE; /* SID */
|
|
lin_tl_pdu[3] = sid; /* D0 */
|
|
lin_tl_pdu[4] = error_code; /* D1 */
|
|
lin_tl_pdu[5] = 0xFF; /* D2 */
|
|
lin_tl_pdu[6] = 0xFF; /* D3 */
|
|
lin_tl_pdu[7] = 0xFF; /* D4 */
|
|
|
|
switch (sid)
|
|
{
|
|
#if (LIN_PROTOCOL == PROTOCOL_J2602)
|
|
|
|
case SERVICE_TARGET_RESET:
|
|
/* PCI type */
|
|
lin_tl_pdu[1] = 0x06;
|
|
/* SID */
|
|
if (NEGATIVE == res_type)
|
|
{
|
|
lin_tl_pdu[2] = RES_NEGATIVE;
|
|
}
|
|
else
|
|
{
|
|
lin_tl_pdu[2] = RES_POSITIVE+ sid;
|
|
}
|
|
/* Get Identifier infor */
|
|
lin_tl_pdu[3] = (l_u8)(product_id.supplier_id & 0xFF);
|
|
lin_tl_pdu[4] = (l_u8)(product_id.supplier_id >> 8);
|
|
lin_tl_pdu[5] = (l_u8)(product_id.function_id & 0xFF);
|
|
lin_tl_pdu[6] = (l_u8)(product_id.function_id >> 8);
|
|
lin_tl_pdu[7] = product_id.variant;
|
|
break;
|
|
#endif /* End (LIN_PROTOCOL == PROTOCOL_J2602) */
|
|
|
|
#if (LIN_PROTOCOL == PROTOCOL_21)
|
|
case SERVICE_ASSIGN_FRAME_ID:
|
|
if (POSITIVE == res_type)
|
|
{
|
|
/* SID */
|
|
lin_tl_pdu[2] = RES_POSITIVE + sid;
|
|
if (error_code == LIN_PRODUCT_IDENT)
|
|
{
|
|
/* PCI type */
|
|
lin_tl_pdu[1] = 0x01;
|
|
/* Get Identifier infor */
|
|
lin_tl_pdu[3] = 0xFF;
|
|
lin_tl_pdu[4] = 0xFF;
|
|
lin_tl_pdu[5] = 0xFF;
|
|
lin_tl_pdu[6] = 0xFF;
|
|
lin_tl_pdu[7] = 0xFF;
|
|
}
|
|
}
|
|
break;
|
|
case SERVICE_READ_BY_IDENTIFY:
|
|
if (POSITIVE == res_type)
|
|
{
|
|
/* SID */
|
|
lin_tl_pdu[2] = RES_POSITIVE + sid;
|
|
|
|
if (error_code == LIN_PRODUCT_IDENT)
|
|
{
|
|
/* PCI type */
|
|
lin_tl_pdu[1] = PCI_RES_READ_BY_IDENTIFY;
|
|
/* Get Identifier infor */
|
|
lin_tl_pdu[3] = (l_u8)(product_id.supplier_id >> 8);
|
|
lin_tl_pdu[4] = (l_u8)(product_id.supplier_id & 0xFF);
|
|
lin_tl_pdu[5] = (l_u8)(product_id.function_id & 0xFF);
|
|
lin_tl_pdu[6] = (l_u8)(product_id.function_id >> 8);
|
|
lin_tl_pdu[7] = product_id.variant;
|
|
}
|
|
else if (error_code == SERIAL_NUMBER)
|
|
{
|
|
/* PCI type */
|
|
lin_tl_pdu[1] = PCI_RES_READ_BY_IDENTIFY1;
|
|
lin_tl_pdu[3] = 0x00;
|
|
lin_tl_pdu[4] = 0x00;
|
|
lin_tl_pdu[5] = 0x00;
|
|
lin_tl_pdu[6] = 0x00;
|
|
lin_tl_pdu[7] = 0xFF;
|
|
}
|
|
|
|
else if (error_code >= LIN_READ_USR_DEF_MIN && error_code <= LIN_READ_USR_DEF_MAX)
|
|
{
|
|
|
|
//l_u8 data_callout[5] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
|
// l_u8 retval = ld_read_by_id_callout(error_code, data_callout);
|
|
/* packing user defined pdu */
|
|
lin_tl_pdu[1] = 0x04;
|
|
lin_tl_pdu[3] = 0x00;
|
|
lin_tl_pdu[4] = 0x00;
|
|
lin_tl_pdu[5] = 0x00;
|
|
lin_tl_pdu[6] = 0x00;
|
|
lin_tl_pdu[7] = 0x00;
|
|
/* Check for data values*/
|
|
// for (i = 4; i >= 0; i --)
|
|
// {
|
|
// if (data_callout[i] != 0xFF)
|
|
// {
|
|
// /* PCI: Data length is 1 (RSID) + all data exclude 0xFF */
|
|
// lin_tl_pdu[1] = i + 2;
|
|
// break;
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
break;
|
|
case SERVICE_ASSIGN_FRAME_ID_RANGE: /* Mandatory for TL LIN 2.1 */
|
|
if (POSITIVE == res_type)
|
|
{
|
|
lin_tl_pdu[1] = 0x06;
|
|
lin_tl_pdu[2] = RES_POSITIVE + sid;
|
|
lin_tl_pdu[3] = 0xFF;
|
|
lin_tl_pdu[4] = 0xFF;
|
|
lin_tl_pdu[5] = 0xFF;
|
|
lin_tl_pdu[6] = 0xFF;
|
|
lin_tl_pdu[7] = 0xFF;
|
|
}
|
|
break;
|
|
case SERVICE_SAVE_CONFIGURATION:
|
|
if (POSITIVE == res_type)
|
|
{
|
|
/* PCI type */
|
|
lin_tl_pdu[1] = PCI_RES_SAVE_CONFIGURATION;
|
|
/* SID */
|
|
lin_tl_pdu[2] = RES_POSITIVE + sid;
|
|
/* Data unused */
|
|
lin_tl_pdu[3] = 0xFF;
|
|
lin_tl_pdu[4] = 0xFF;
|
|
}
|
|
break;
|
|
case SERVICE_ASSIGN_NAD:
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
lin_configured_NAD = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][7];
|
|
#else /* Single frame support */
|
|
lin_configured_NAD = (*tl_current_rx_pdu_ptr)[7];
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
lin_tl_pdu[0] = lin_initial_NAD; /* Use Initial NAD */
|
|
lin_tl_pdu[1] = 0x01; /* PCI */
|
|
lin_tl_pdu[2] = 0xF0; /* RSID */
|
|
lin_tl_pdu[3] = 0xFF;
|
|
lin_tl_pdu[4] = 0xFF;
|
|
break;
|
|
case SERVICE_CONDITIONAL_CHANGE_NAD:
|
|
lin_tl_pdu[1] = 0x01; /* PCI */
|
|
lin_tl_pdu[2] = 0xF3; /* RSID */
|
|
lin_tl_pdu[3] = 0xFF;
|
|
lin_tl_pdu[4] = 0xFF;
|
|
break;
|
|
#endif /* End (LIN_PROTOCOL == PROTOCOL_21) */
|
|
default:
|
|
break;
|
|
}/* end of switch statement */
|
|
/* Multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
lin_tl_tx_queue.queue_status = LD_QUEUE_FULL;
|
|
lin_tl_tx_queue.queue_current_size = 1;
|
|
|
|
/* Put to transmit queue */
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
lin_tl_tx_queue.tl_pdu[lin_tl_tx_queue.queue_header][i] = lin_tl_pdu[i];
|
|
}
|
|
/* Set check N_As Timeout */
|
|
tl_tx_msg_index = lin_tl_tx_queue.queue_tail;
|
|
tl_tx_msg_size = 1;
|
|
tl_tx_msg_status = LD_IN_PROGRESS;
|
|
#else /* Single frame support */
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
tx_single_pdu_data[i] = lin_tl_pdu[i];
|
|
}
|
|
/* set current TX PDU to send out */
|
|
tl_current_tx_pdu_ptr = (lin_tl_pdu_data*)tx_single_pdu_data;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
/* Set check N_As timeout */
|
|
tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
tl_check_timeout_type = LD_CHECK_N_AS_TIMEOUT;
|
|
/* set number of SlaveResp response data */
|
|
tl_slaveresp_cnt = 1;
|
|
}
|
|
|
|
void lin_tl_get_pdu()
|
|
{
|
|
l_u8 i;
|
|
/* Multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
lin_tl_pdu_data lin_tl_pdu;
|
|
|
|
tl_get_raw(lin_tl_pdu, &lin_tl_tx_queue, TRANSMISSION);
|
|
/* Copy PDU to response buffer */
|
|
for (i = 1; i < 9; i++)
|
|
{
|
|
lin_lld_response_buffer[i] = lin_tl_pdu[i - 1];
|
|
}
|
|
#else /* Single frame support */
|
|
/* Copy PDU to response buffer */
|
|
for (i = 1; i < 9; i++)
|
|
{
|
|
lin_lld_response_buffer[i] = (*tl_current_tx_pdu_ptr)[i - 1];
|
|
}
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
}
|
|
|
|
/* Single frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_)
|
|
void lin_tl_put_pdu ()
|
|
{
|
|
l_u8 i;
|
|
|
|
/* Set PDU for RX buffer */
|
|
tl_current_rx_pdu_ptr = &rx_single_pdu_data;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
(*tl_current_rx_pdu_ptr)[i] = lin_lld_response_buffer[i+1];
|
|
}
|
|
}
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_) */
|
|
|
|
|
|
/* Multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
|
|
/*FUNCTION*--------------------------------------------------------------*//**
|
|
* @fn void lin_process_pdu(lin_tl_pdu_data *pdu)
|
|
* @brief LIN process packet data unit
|
|
*
|
|
* @param pdu <B>[IN]</B> packet data unit
|
|
*
|
|
* @return #void
|
|
*
|
|
* @SDD_ID LIN_SDD_354
|
|
* @endif
|
|
*
|
|
* @local_var
|
|
* -# <B>#l_u8</B> <I>pci_type</I>
|
|
* -# <B>#lin_configuration</B> <I>*conf</I>
|
|
* -# <B>#lin_tl_descriptor</B> <I>*tl_conf</I>
|
|
* -# <B>#l_u16</B> <I>length</I>
|
|
* -# <B>#l_u8</B> <I>tmp_frame_counter</I>
|
|
* -# <B>#lin_transport_layer_queue</B> <I>*tl_queue</I>
|
|
* -# <B>#l_u8</B> <I>i</I>
|
|
*
|
|
*
|
|
* @static_global_var
|
|
* -# <B>#lin_ifc_configuration</B>
|
|
*
|
|
* @see tl_get_raw
|
|
* @see tl_put_raw
|
|
* @see lin_tl_get_response
|
|
*
|
|
* @details
|
|
* LIN process packet data unit
|
|
*//*END*----------------------------------------------------------------------*/
|
|
|
|
static void lin_process_pdu(lin_tl_pdu_data *pdu)
|
|
{
|
|
l_u8 pci_type;
|
|
l_u16 length;
|
|
l_u8 tmp_frame_counter;
|
|
|
|
/* get PCI type */
|
|
pci_type = ((*pdu)[1] & 0xF0) >> 4;
|
|
switch (pci_type)
|
|
{
|
|
case PCI_SF:
|
|
length = ((*pdu)[1]) & 0x0F;
|
|
/* check length of SF. If not valid, ignore this PDU */
|
|
if (length <= 6)
|
|
{
|
|
tl_receive_msg_status = LD_COMPLETED;
|
|
tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
tl_service_status = LD_REQUEST_FINISHED;
|
|
/* put PDU to rx queue */
|
|
lin_tl_rx_queue.queue_header = 0;
|
|
lin_tl_rx_queue.queue_tail = 0;
|
|
lin_tl_rx_queue.queue_current_size = 0;
|
|
lin_tl_rx_queue.queue_status = LD_NO_DATA;
|
|
tl_put_raw(&(lin_lld_response_buffer[1]), &lin_tl_rx_queue, RECEIVING);
|
|
tl_frame_counter = 1;
|
|
tl_no_of_pdu = 1;
|
|
if (tl_diag_state != LD_DIAG_RX_FUNCTIONAL)
|
|
{
|
|
tl_diag_state = LD_DIAG_TX_PHY;
|
|
}
|
|
lin_tl_attach_service();
|
|
}
|
|
else
|
|
{
|
|
tl_diag_state = LD_DIAG_IDLE;
|
|
}
|
|
break;
|
|
case PCI_FF:
|
|
length = ((*pdu)[1] & 0x0F) * 256 + ((*pdu)[2]);
|
|
/* check length of FF. If not valid, ignore this PDU */
|
|
if (length >= 7 && length <= (MAX_QUEUE_SIZE*6 - 1))
|
|
{
|
|
/* Set check N_Cr timeout */
|
|
tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
tl_check_timeout_type = LD_CHECK_N_CR_TIMEOUT;
|
|
/* put PDU to rx queue */
|
|
lin_tl_rx_queue.queue_header = 0;
|
|
lin_tl_rx_queue.queue_tail = 0;
|
|
lin_tl_rx_queue.queue_current_size = 0;
|
|
lin_tl_rx_queue.queue_status = LD_NO_DATA;
|
|
tl_put_raw(lin_lld_response_buffer + 1, &lin_tl_rx_queue, RECEIVING);
|
|
|
|
/* canculate number of PDU for this message */
|
|
if ((length-5)%6 == 0)
|
|
{
|
|
tl_no_of_pdu = (l_u8)((length - 5) / 6);
|
|
}
|
|
else
|
|
{
|
|
tl_no_of_pdu = (l_u8)((length - 5) / 6) + 1;
|
|
}
|
|
/* set frame counter = 1 */
|
|
tl_frame_counter = 1;
|
|
tl_service_status = LD_SERVICE_BUSY;
|
|
if (tl_diag_state != LD_DIAG_RX_FUNCTIONAL)
|
|
{
|
|
tl_diag_state = LD_DIAG_RX_PHY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tl_diag_state = LD_DIAG_IDLE;
|
|
}
|
|
break;
|
|
case PCI_CF:
|
|
/* Set check N_Cr timeout */
|
|
tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
tl_check_timeout_type = LD_CHECK_N_CR_TIMEOUT;
|
|
/* get frame counter of this PDU */
|
|
tmp_frame_counter = ((*pdu)[1] & 0x0F);
|
|
/* Check valid frame counter */
|
|
if (tmp_frame_counter == tl_frame_counter)
|
|
{
|
|
/* increase frame counter */
|
|
tl_frame_counter++;
|
|
if (tl_frame_counter > 15)
|
|
{
|
|
tl_frame_counter = 0;
|
|
}
|
|
/* decrease number of PDU to check message is complete */
|
|
tl_no_of_pdu--;
|
|
/* put PDU to rx queue */
|
|
tl_put_raw(&(lin_lld_response_buffer[1]), &lin_tl_rx_queue, RECEIVING);
|
|
if (tl_diag_state != LD_DIAG_RX_FUNCTIONAL)
|
|
{
|
|
tl_diag_state = LD_DIAG_RX_PHY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* abort this message */
|
|
tl_receive_msg_status = LD_WRONG_SN;
|
|
tl_rx_msg_status = LD_WRONG_SN;
|
|
tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
}
|
|
if (0 == tl_no_of_pdu)
|
|
{
|
|
/* message is received completely */
|
|
/* set status is IDLE to receive new message */
|
|
|
|
tl_receive_msg_status = LD_COMPLETED;
|
|
tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
|
|
tl_service_status = LD_REQUEST_FINISHED;
|
|
if (tl_diag_state != LD_DIAG_RX_FUNCTIONAL)
|
|
{
|
|
tl_diag_state = LD_DIAG_TX_PHY;
|
|
}
|
|
lin_tl_attach_service();
|
|
}
|
|
break;
|
|
default:
|
|
/* ignore this PDU */
|
|
break;
|
|
}
|
|
}
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
void lin_tl_handler()
|
|
{
|
|
l_u8 NAD, SID;
|
|
/* Multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
l_u8 frame_type;
|
|
NAD = lin_lld_response_buffer[1];
|
|
SID = lin_lld_response_buffer[3];
|
|
frame_type = (l_u8)((lin_lld_response_buffer[2] & 0xF0) >> 4);
|
|
/* check NAD whether or not belongs to this slave node */
|
|
/* receive both broadcast NAD and functional NAD */
|
|
if ((LD_BROADCAST != NAD) && \
|
|
(LD_FUNCTIONAL_NAD != NAD) && \
|
|
(((lin_configured_NAD != NAD) && \
|
|
(SERVICE_ASSIGN_NAD != SID)) || \
|
|
((lin_initial_NAD != NAD) && \
|
|
(SERVICE_ASSIGN_NAD == SID))))
|
|
{
|
|
/* ignore any response */
|
|
tl_slaveresp_cnt = 0;
|
|
return;
|
|
}
|
|
/* check if functional request is received while transmitting response */
|
|
if ((tl_diag_state == LD_DIAG_TX_PHY || tl_diag_state == LD_DIAG_RX_PHY) && NAD == LD_FUNCTIONAL_NAD && tl_service_status == LD_SERVICE_BUSY)
|
|
{
|
|
tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
tl_check_timeout_type = LD_CHECK_N_CR_TIMEOUT;
|
|
/* ignore request */
|
|
NAD = 0x00;
|
|
return;
|
|
}
|
|
/* check if slave node is transmitting response while receive functional request */
|
|
if (tl_diag_state == LD_DIAG_TX_PHY && NAD != LD_FUNCTIONAL_NAD)
|
|
{
|
|
/* clear received request & response */
|
|
tl_service_status = LD_SERVICE_BUSY;
|
|
/* clear queue */
|
|
lin_tl_tx_queue.queue_tail = 0;
|
|
lin_tl_tx_queue.queue_header = 0;
|
|
lin_tl_tx_queue.queue_current_size = 0;
|
|
lin_tl_tx_queue.queue_status = LD_QUEUE_EMPTY;
|
|
|
|
lin_tl_rx_queue.queue_tail = 0;
|
|
lin_tl_rx_queue.queue_header = 0;
|
|
lin_tl_rx_queue.queue_current_size = 0;
|
|
lin_tl_rx_queue.queue_status = LD_NO_DATA;
|
|
/* transmit status */
|
|
tl_tx_msg_status = LD_COMPLETED;
|
|
/* receive status */
|
|
tl_receive_msg_status = LD_NO_MSG;
|
|
tl_rx_msg_status = LD_COMPLETED;
|
|
|
|
tl_slaveresp_cnt = 0;
|
|
/* then receive and process new request */
|
|
}
|
|
|
|
if (tl_service_status == LD_SERVICE_ERROR && frame_type == PCI_CF)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (NAD != LD_FUNCTIONAL_NAD)
|
|
{
|
|
tl_diag_state = LD_DIAG_RX_PHY;
|
|
}
|
|
else
|
|
{
|
|
tl_diag_state = LD_DIAG_RX_FUNCTIONAL;
|
|
}
|
|
/* call process pdu */
|
|
lin_process_pdu((lin_tl_pdu_data *)&(lin_lld_response_buffer[1]));
|
|
|
|
#else /* Single frame support */
|
|
|
|
l_u8 pci_type, length;
|
|
|
|
NAD = (*tl_current_rx_pdu_ptr)[0];
|
|
SID = (*tl_current_rx_pdu_ptr)[2];
|
|
/* check NAD whether or not belongs to this slave node */
|
|
/* receive both broadcast NAD and functional NAD */
|
|
|
|
if (NAD == 0x05)
|
|
{
|
|
length = 1;
|
|
}
|
|
if ((LD_BROADCAST != NAD) && \
|
|
(LD_FUNCTIONAL_NAD != NAD) && \
|
|
(((lin_configured_NAD != NAD) && (SERVICE_ASSIGN_NAD != SID)) || \
|
|
((lin_initial_NAD != NAD) && (SERVICE_ASSIGN_NAD == SID))))
|
|
{
|
|
tl_slaveresp_cnt = 0;
|
|
return;
|
|
}
|
|
|
|
/* Get PCI type */
|
|
pci_type = ((*tl_current_rx_pdu_ptr)[1] & 0xF0) >> 4;
|
|
switch (pci_type)
|
|
{
|
|
case PCI_SF: /* Single frame */
|
|
/* error handling: check length of message */
|
|
length = (*tl_current_rx_pdu_ptr)[1] & 0x0F;
|
|
if (6 < length)
|
|
{
|
|
return;
|
|
}
|
|
lin_tl_attach_service();
|
|
break;
|
|
default:
|
|
break;
|
|
} /* End of ckeck PCI_type */
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
}
|
|
|
|
void lin_tl_attach_service()
|
|
{
|
|
l_u8 sid;
|
|
l_u8 i;
|
|
l_u8 sid_supported_flag = 0;
|
|
|
|
/* Multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
l_u8 frame_type, NAD;
|
|
l_u16 supplierIdLsb;
|
|
l_u16 supplierIdMsb;
|
|
l_u16 functionIdLsb;
|
|
l_u16 functionIdMsb;
|
|
|
|
/* get frame type */
|
|
frame_type = (lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][1] & 0xF0) >> 4;
|
|
NAD = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][0];
|
|
/* check if request is functional request */
|
|
if (NAD == LD_FUNCTIONAL_NAD)
|
|
{
|
|
#if (LIN_PROTOCOL == PROTOCOL_21)
|
|
lin_diagsrv_functional_service();
|
|
#endif /* End (LIN_PROTOCOL == PROTOCOL_21) */
|
|
/* update service state */
|
|
tl_diag_state = LD_DIAG_IDLE;
|
|
tl_service_status = LD_SERVICE_IDLE;
|
|
/* ignore response */
|
|
tl_no_of_pdu = 0;
|
|
tl_frame_counter = 0;
|
|
return;
|
|
}
|
|
|
|
/* Get SID information */
|
|
if (frame_type == PCI_FF)
|
|
{
|
|
sid = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][3];
|
|
}
|
|
else
|
|
{
|
|
sid = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][2];
|
|
}
|
|
#else /* Single frame support */
|
|
l_u8 NAD;
|
|
l_u16 supplierIdLsb;
|
|
l_u16 supplierIdMsb;
|
|
l_u16 functionIdLsb;
|
|
l_u16 functionIdMsb;
|
|
|
|
NAD = (*tl_current_rx_pdu_ptr)[0];
|
|
/* check functional request */
|
|
if (NAD == LD_FUNCTIONAL_NAD)
|
|
{
|
|
return;
|
|
}
|
|
/* Get SID information */
|
|
sid = (*tl_current_rx_pdu_ptr)[2];
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
for (i = 0; i < _DIAG_NUMBER_OF_SERVICES_; i++)
|
|
{
|
|
if (lin_diag_services_supported[i] == sid)
|
|
{
|
|
lin_diag_services_flag[i] = 1;
|
|
sid_supported_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (sid_supported_flag == 1)
|
|
{
|
|
/*Clear sid_supported_flag */
|
|
sid_supported_flag = 0;
|
|
switch (sid)
|
|
{
|
|
#if LIN_PROTOCOL == PROTOCOL_21
|
|
case SERVICE_ASSIGN_FRAME_ID:
|
|
if(NAD==lin_configured_NAD|| NAD==0x7F){
|
|
lin_diagservice_assign_frame_id();
|
|
}
|
|
|
|
break;
|
|
case SERVICE_READ_BY_IDENTIFY: /* Mandatory for TL LIN 2.1 & 2.0 */
|
|
lin_diagservice_read_by_identifier();
|
|
break;
|
|
|
|
case SERVICE_ASSIGN_FRAME_ID_RANGE: /* Mandatory for TL LIN 2.1 */
|
|
lin_diagservice_assign_frame_id_range();
|
|
break;
|
|
|
|
case SERVICE_SAVE_CONFIGURATION:
|
|
/* Set save configuration flag */
|
|
lin_save_configuration_flg = 1;
|
|
/* Response to master - RSID */
|
|
lin_tl_make_slaveres_pdu(SERVICE_SAVE_CONFIGURATION, POSITIVE, 0);
|
|
break;
|
|
|
|
case SERVICE_ASSIGN_NAD:
|
|
/* Get Supplier ID and Function ID*/
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
if ((NAD == lin_initial_NAD)|| (NAD == LD_BROADCAST))
|
|
{
|
|
supplierIdLsb = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][3];
|
|
supplierIdMsb = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][4];
|
|
functionIdLsb = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][5];
|
|
functionIdMsb = lin_tl_rx_queue.tl_pdu[lin_tl_rx_queue.queue_header][6];
|
|
/*Check if Supplier ID and Function ID match, then send positive response */
|
|
if ((((supplierIdMsb<<8)|supplierIdLsb) == product_id.supplier_id)||(((supplierIdMsb<<8)|supplierIdLsb) == LD_ANY_SUPPLIER))
|
|
if ((((functionIdMsb<<8)|functionIdLsb) == product_id.function_id)||(((functionIdMsb<<8)|functionIdLsb) == LD_ANY_FUNCTION))
|
|
{
|
|
lin_tl_make_slaveres_pdu(SERVICE_ASSIGN_NAD, POSITIVE, 0);
|
|
}
|
|
}
|
|
#else
|
|
if ((NAD == lin_initial_NAD)|| (NAD == LD_BROADCAST))
|
|
{
|
|
supplierIdLsb = (*tl_current_rx_pdu_ptr)[3];
|
|
supplierIdMsb = (*tl_current_rx_pdu_ptr)[4];
|
|
functionIdLsb = (*tl_current_rx_pdu_ptr)[5];
|
|
functionIdMsb = (*tl_current_rx_pdu_ptr)[6];
|
|
/*Check if Supplier ID and Function ID match, then send positive response */
|
|
if ((((supplierIdMsb<<8)|supplierIdLsb) == product_id.supplier_id)||(((supplierIdMsb<<8)|supplierIdLsb) == LD_ANY_SUPPLIER))
|
|
if ((((functionIdMsb<<8)|functionIdLsb) == product_id.function_id)||(((functionIdMsb<<8)|functionIdLsb) == LD_ANY_FUNCTION))
|
|
{
|
|
lin_tl_make_slaveres_pdu(SERVICE_ASSIGN_NAD, POSITIVE, 0);
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case SERVICE_CONDITIONAL_CHANGE_NAD:
|
|
lin_condittional_change_nad();
|
|
break;
|
|
#endif /* (End LIN_PROTOCOL == LIN_PROTOCOL_21) */
|
|
|
|
#if LIN_PROTOCOL == PROTOCOL_J2602
|
|
case SERVICE_TARGET_RESET:
|
|
lin_diagservice_target_reset();
|
|
break;
|
|
#endif /* (End LIN_PROTOCOL == LIN_PROTOCOL_J2602) */
|
|
default:
|
|
break;
|
|
}/* end of switch */
|
|
}
|
|
else
|
|
{
|
|
lin_tl_make_slaveres_pdu(sid, NEGATIVE, SERVICE_NOT_SUPPORTED);
|
|
}
|
|
}
|
|
|
|
#endif /* End (_LIN_GPIO_ == 0) && !defined(_MC9S08SC4_H) */
|
|
#endif /* End (LIN_MODE == _SLAVE_MODE_) */
|
|
|
|
/********------------ End of code for SINGLE Interface --------------**********/
|
|
|
|
|
|
/********------------- Code supports Multi interface ----------------**********/
|
|
#if LIN_MODE == _MASTER_MODE_
|
|
#ifdef MULTI_TIMER_MODE
|
|
extern const l_u16 max_tl_timeout_counter[LIN_NUM_OF_IFCS];
|
|
#endif /* End MULTI_TIMER_MODE */
|
|
|
|
/*************************** FUNCTIONS *******************/
|
|
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
void tl_process_mreq
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii
|
|
)
|
|
{
|
|
const lin_configuration *conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
/* Get TL configuration */
|
|
tl_conf = conf->tl_desc;
|
|
|
|
/* decrease number of PDU for sending message */
|
|
tl_conf->tl_tx_msg_size--;
|
|
/* Check message is sent completely */
|
|
if (0 == tl_conf->tl_tx_msg_size)
|
|
{
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
tl_conf->tl_tx_msg_status = LD_COMPLETED;
|
|
*conf->tl_service_status = LD_REQUEST_FINISHED;
|
|
/* back to normal table */
|
|
*conf->active_schedule_id = *conf->previous_schedule_id;
|
|
conf->schedule_start_entry[*(conf->active_schedule_id)] = 0;
|
|
}
|
|
else
|
|
{
|
|
#ifdef MULTI_TIMER_MODE
|
|
tl_conf->tl_check_timeout = max_tl_timeout_counter[iii];
|
|
#else
|
|
tl_conf->tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
#endif /* End MULTI_TIMER_MODE */
|
|
tl_conf->tl_check_timeout_type = LD_CHECK_N_AS_TIMEOUT;
|
|
}
|
|
}
|
|
|
|
|
|
/*FUNCTION*--------------------------------------------------------------*//**
|
|
* @fn void lin_process_pdu(l_ifc_handle iii, lin_tl_pdu_data *pdu)
|
|
* @brief LIN process packet data unit
|
|
*
|
|
* @param iii <B>[IN]</B> interface name
|
|
* @param pdu <B>[IN]</B> packet data unit
|
|
*
|
|
* @return #void
|
|
*
|
|
* @SDD_ID LIN_SDD_327
|
|
* @endif
|
|
*
|
|
* @local_var
|
|
* -# <B>#l_u8</B> <I>pci_type</I>
|
|
* -# <B>#lin_configuration</B> <I>*conf</I>
|
|
* -# <B>#lin_tl_descriptor</B> <I>*tl_conf</I>
|
|
* -# <B>#l_u16</B> <I>length</I>
|
|
* -# <B>#l_u8</B> <I>tmp_frame_counter</I>
|
|
* -# <B>#lin_transport_layer_queue</B> <I>*tl_queue</I>
|
|
* -# <B>#l_u8</B> <I>i</I>
|
|
*
|
|
*
|
|
* @static_global_var
|
|
* -# <B>#lin_ifc_configuration</B>
|
|
*
|
|
* @see tl_get_raw
|
|
* @see tl_put_raw
|
|
* @see lin_tl_get_response
|
|
*
|
|
* @details
|
|
* LIN process packet data unit
|
|
*//*END*----------------------------------------------------------------------*/
|
|
|
|
static void lin_process_pdu(l_ifc_handle iii, lin_tl_pdu_data *pdu)
|
|
{
|
|
l_u8 pci_type;
|
|
l_u16 length;
|
|
l_u8 tmp_frame_counter;
|
|
const lin_configuration * conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
|
|
/* Get the current configuration */
|
|
conf = (lin_configuration *)&lin_ifc_configuration[iii];
|
|
tl_conf = conf->tl_desc;
|
|
|
|
/* get PCI type */
|
|
pci_type = ((*pdu)[1] & 0xF0) >> 4;
|
|
switch(pci_type)
|
|
{
|
|
case PCI_SF:
|
|
length = ((*pdu)[1]) & 0x0F;
|
|
/* check length of SF. If not valid, ignore this PDU */
|
|
if (length <= 6)
|
|
{
|
|
if (_MASTER_ == conf->function)
|
|
{
|
|
/* reset queue header and queue tail */
|
|
tl_conf->tl_rx_queue->queue_header = 0;
|
|
tl_conf->tl_rx_queue->queue_tail = 0;
|
|
tl_conf->tl_rx_queue->queue_current_size = 0;
|
|
tl_conf->tl_rx_queue->queue_status = LD_NO_DATA;
|
|
/* put to rx queue */
|
|
tl_put_raw(&(conf->response_buffer[1]), tl_conf->tl_rx_queue, RECEIVING);
|
|
|
|
/* process diagnostic interleaved mode */
|
|
*conf->tl_diag_interleave_state = DIAG_NOT_START;
|
|
|
|
/* set status is IDLE to receive new message */
|
|
tl_conf->tl_receive_msg_status = LD_COMPLETED;
|
|
/* Exit Diagnostic Interleaved Mode*/
|
|
*conf->diagnostic_mode = DIAG_NONE;
|
|
*conf->tl_service_status = LD_SERVICE_IDLE;
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
|
|
/* process response */
|
|
lin_tl_get_response(iii);
|
|
|
|
/*If Master node is running with Diagnostic Slave Response Schedule table */
|
|
/* then switch back to previous normal table */
|
|
if (*conf->active_schedule_id == (conf->schedule_start + 3))
|
|
{
|
|
/* switch to normal table */
|
|
*conf->active_schedule_id = *conf->previous_schedule_id;
|
|
conf->schedule_start_entry[*conf->active_schedule_id] = 0;
|
|
|
|
}
|
|
}
|
|
else /* Slave interface */
|
|
{
|
|
/* put PDU to rx queue */
|
|
tl_conf->tl_receive_msg_status = LD_COMPLETED;
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
*conf->tl_service_status = LD_REQUEST_FINISHED;
|
|
/* reset queue header and queue tail */
|
|
tl_conf->tl_rx_queue->queue_header = 0;
|
|
tl_conf->tl_rx_queue->queue_tail = 0;
|
|
tl_conf->tl_rx_queue->queue_current_size = 0;
|
|
tl_conf->tl_rx_queue->queue_status = LD_NO_DATA;
|
|
/* put to rx queue */
|
|
tl_put_raw(&(conf->response_buffer[1]), tl_conf->tl_rx_queue, RECEIVING);
|
|
tl_conf->tl_frame_counter = 1;
|
|
tl_conf->tl_no_of_pdu = 1;
|
|
lin_tl_attach_service(iii);
|
|
}
|
|
}
|
|
break;
|
|
case PCI_FF:
|
|
/* for both MASTER and SLAVE */
|
|
length = ((*pdu)[1] & 0x0F) * 256 + ((*pdu)[2]);
|
|
/* check length of FF. If not valid, ignore this PDU */
|
|
if (length >= 7 && length <= (MAX_QUEUE_SIZE*6 - 1))
|
|
{
|
|
/* Set check N_Cr timeout */
|
|
|
|
#ifdef MULTI_TIMER_MODE
|
|
tl_conf->tl_check_timeout = max_tl_timeout_counter[iii];
|
|
#else
|
|
tl_conf->tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
#endif /* End MULTI_TIMER_MODE */
|
|
|
|
tl_conf->tl_check_timeout_type = LD_CHECK_N_CR_TIMEOUT;
|
|
/* put PDU to rx queue */
|
|
/* reset queue header and queue tail */
|
|
tl_conf->tl_rx_queue->queue_header = 0;
|
|
tl_conf->tl_rx_queue->queue_tail = 0;
|
|
tl_conf->tl_rx_queue->queue_current_size = 0;
|
|
tl_conf->tl_rx_queue->queue_status = LD_NO_DATA;
|
|
tl_put_raw(&(conf->response_buffer[1]), tl_conf->tl_rx_queue, RECEIVING);
|
|
|
|
/* calculate number of PDU for this message */
|
|
if ((length-5)%6 == 0)
|
|
{
|
|
tl_conf->tl_no_of_pdu = (l_u8)((length - 5) / 6);
|
|
}
|
|
else
|
|
{
|
|
tl_conf->tl_no_of_pdu = (l_u8)((length - 5) / 6) + 1;
|
|
}
|
|
/* set frame counter = 1 */
|
|
tl_conf->tl_frame_counter = 1;
|
|
*conf->tl_service_status = LD_SERVICE_BUSY;
|
|
}
|
|
break;
|
|
case PCI_CF:
|
|
/* Only for MASTER */
|
|
if (_MASTER_ == conf->function)
|
|
{
|
|
/* Set check N_Cr timeout */
|
|
#ifdef MULTI_TIMER_MODE
|
|
tl_conf->tl_check_timeout = max_tl_timeout_counter[iii];
|
|
#else
|
|
tl_conf->tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
#endif /* End MULTI_TIMER_MODE */
|
|
tl_conf->tl_check_timeout_type = LD_CHECK_N_CR_TIMEOUT;
|
|
/* get frame counter of this PDU */
|
|
tmp_frame_counter = ((*pdu)[1]&0x0F);
|
|
/* Check valid frame counter */
|
|
if (tmp_frame_counter == tl_conf->tl_frame_counter)
|
|
{
|
|
/* increase frame counter */
|
|
tl_conf->tl_frame_counter++;
|
|
if (tl_conf->tl_frame_counter > 15)
|
|
{
|
|
tl_conf->tl_frame_counter = 0;
|
|
}
|
|
/* decrease number of PDU to check message is complete */
|
|
tl_conf->tl_no_of_pdu--;
|
|
/* put PDU to rx queue */
|
|
tl_put_raw(&(conf->response_buffer[1]), tl_conf->tl_rx_queue, RECEIVING);
|
|
}
|
|
else
|
|
{
|
|
/* abort this message */
|
|
tl_conf->tl_rx_msg_status = LD_WRONG_SN;
|
|
tl_conf->tl_receive_msg_status = LD_WRONG_SN;
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
*conf->diagnostic_mode = DIAG_NONE;
|
|
|
|
/*If Master node is running with Diagnostic Slave Response Schedule table */
|
|
/* then switch back to previous normal table */
|
|
if (*conf->active_schedule_id == (conf->schedule_start + 3))
|
|
{
|
|
/* switch to normal table */
|
|
*conf->active_schedule_id = *conf->previous_schedule_id;
|
|
conf->schedule_start_entry[*conf->active_schedule_id] = 0;
|
|
}
|
|
}
|
|
if (0 == tl_conf->tl_no_of_pdu)
|
|
{
|
|
/* message is received completely */
|
|
|
|
/* set status is IDLE to receive new message */
|
|
tl_conf->tl_receive_msg_status = LD_COMPLETED;
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
*conf->tl_service_status = LD_SERVICE_IDLE;
|
|
/* process diagnostic interleaved mode */
|
|
if (*conf->current_pid == 0x3D && *conf->diagnostic_mode == DIAG_INTER_LEAVE_MODE)
|
|
{
|
|
*conf->tl_diag_interleave_state = DIAG_NOT_START;
|
|
*conf->diagnostic_mode = DIAG_NONE;
|
|
}
|
|
|
|
/* call function to process this response */
|
|
lin_tl_get_response(iii);
|
|
/*If Master node is running with Diagnostic Slave Response Schedule table */
|
|
/* then switch back to previous normal table */
|
|
if (*conf->active_schedule_id == (conf->schedule_start + 3))
|
|
{
|
|
/* switch to normal table */
|
|
*conf->active_schedule_id = *conf->previous_schedule_id;
|
|
conf->schedule_start_entry[*conf->active_schedule_id] = 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
else /* for SLAVE */
|
|
{
|
|
/* Set check N_Cr timeout */
|
|
#ifdef MULTI_TIMER_MODE
|
|
tl_conf->tl_check_timeout = max_tl_timeout_counter[iii];
|
|
#else
|
|
tl_conf->tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
#endif /* End MULTI_TIMER_MODE */
|
|
tl_conf->tl_check_timeout_type = LD_CHECK_N_CR_TIMEOUT;
|
|
/* get frame counter of this PDU */
|
|
tmp_frame_counter = ((*pdu)[1]&0x0F);
|
|
/* Check valid frame counter */
|
|
if (tmp_frame_counter == tl_conf->tl_frame_counter)
|
|
{
|
|
/* increase frame counter */
|
|
tl_conf->tl_frame_counter++;
|
|
if (tl_conf->tl_frame_counter > 15)
|
|
{
|
|
tl_conf->tl_frame_counter = 0;
|
|
}
|
|
/* decrease number of PDU to check message is complete */
|
|
tl_conf->tl_no_of_pdu--;
|
|
/* put PDU to rx queue */
|
|
tl_put_raw(&(conf->response_buffer[1]), tl_conf->tl_rx_queue, RECEIVING);
|
|
}
|
|
else
|
|
{
|
|
/* abort this message */
|
|
tl_conf->tl_receive_msg_status = LD_WRONG_SN;
|
|
tl_conf->tl_rx_msg_status = LD_WRONG_SN;
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
}
|
|
if (0 == tl_conf->tl_no_of_pdu)
|
|
{
|
|
/* message is received completely */
|
|
/* set status is IDLE to receive new message */
|
|
tl_conf->tl_receive_msg_status = LD_COMPLETED;
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
*conf->tl_service_status = LD_REQUEST_FINISHED;
|
|
|
|
lin_tl_attach_service(iii);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
/* ignore this PDU */
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void lin_tl_handler_error
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii,
|
|
/* [IN] interface name */
|
|
l_u8 pid
|
|
)
|
|
{
|
|
const lin_configuration* conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
/* Get TL description */
|
|
tl_conf = conf->tl_desc;
|
|
|
|
/* for master */
|
|
if ((_MASTER_ == conf->function) && (DIAG_INTER_LEAVE_MODE == *conf->diagnostic_mode))
|
|
{
|
|
/* Master request */
|
|
if (0x3C == pid)
|
|
{
|
|
/* update status of message and queue */
|
|
tl_conf->tl_tx_msg_status = LD_FAILED;
|
|
tl_conf->tl_tx_queue->queue_status = LD_TRANSMIT_ERROR;
|
|
}
|
|
else /* Slave Response */
|
|
{
|
|
/* update status of message and queue */
|
|
tl_conf->tl_receive_msg_status = LD_FAILED;
|
|
tl_conf->tl_rx_msg_status = LD_FAILED;
|
|
tl_conf->tl_rx_queue->queue_status = LD_RECEIVE_ERROR;
|
|
} /* end of (0x3C == pid) */
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
*conf->tl_service_status = LD_SERVICE_ERROR;
|
|
*conf->diagnostic_mode = DIAG_NONE;
|
|
/* switch to normal table */
|
|
*conf->active_schedule_id = *conf->previous_schedule_id;
|
|
conf->schedule_start_entry[*conf->active_schedule_id] = 0;
|
|
}
|
|
else
|
|
{
|
|
/* for slave */
|
|
/* Master request */
|
|
if (0x3C == pid)
|
|
{
|
|
/* update status of message and queue */
|
|
tl_conf->tl_receive_msg_status = LD_FAILED;
|
|
tl_conf->tl_rx_msg_status = LD_FAILED;
|
|
tl_conf->tl_rx_queue->queue_status = LD_RECEIVE_ERROR;
|
|
tl_conf->tl_slaveresp_cnt = 0;
|
|
}
|
|
else /* Slave Response */
|
|
{
|
|
/* update status of message and queue */
|
|
tl_conf->tl_tx_msg_status = LD_FAILED;
|
|
tl_conf->tl_tx_queue->queue_status = LD_TRANSMIT_ERROR;
|
|
} /* end of (0x3C == pid) */
|
|
*conf->tl_service_status = LD_SERVICE_ERROR;
|
|
tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT;
|
|
}
|
|
}
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
|
|
void lin_tl_make_mreq_pdu
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii
|
|
/* single frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_)
|
|
,/* [IN] PDU pointer */
|
|
lin_tl_pdu_data *pdu_ptr
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_) */
|
|
)
|
|
{
|
|
const lin_configuration *conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
/* Single frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_)
|
|
l_u8 i;
|
|
lin_tl_pdu_data *tl_tx_pdu;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_) */
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
/* Get TL configuration */
|
|
tl_conf = conf->tl_desc;
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
tl_get_raw(&conf->response_buffer[1], tl_conf->tl_tx_queue, TRANSMISSION);
|
|
conf->response_buffer[0] = 8;
|
|
#else /* single frame support */
|
|
/* check if Service Mode and set current PDU pointer to PDU data based on Diag Service */
|
|
|
|
tl_conf->tl_current_tx_pdu_ptr = (lin_tl_pdu_data*)tl_conf->tl_tx_single_pdu;
|
|
tl_tx_pdu = (lin_tl_pdu_data*)tl_conf->tl_tx_single_pdu;
|
|
|
|
for (i = 0; i < 8; ++i)
|
|
{
|
|
conf->response_buffer[i+1] = (*tl_tx_pdu)[i];
|
|
}
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
}
|
|
|
|
void lin_tl_make_slaveres_pdu
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii,
|
|
/* [IN] service identifier */
|
|
l_u8 sid,
|
|
/* [IN] type of response */
|
|
l_u8 res_type,
|
|
/* [IN] Error code in case of negative response, if positive = 0 */
|
|
l_u8 error_code
|
|
|
|
)
|
|
{
|
|
const lin_configuration * conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
lin_node_attribute *node_conf;
|
|
lin_product_id *ident;
|
|
l_u8 i;
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
lin_tl_pdu_data lin_tl_pdu_buff, *lin_tl_pdu;
|
|
lin_transport_layer_queue *rx_queue;
|
|
lin_tl_pdu = (lin_tl_pdu_data *)&lin_tl_pdu_buff;
|
|
#else /* single frame support */
|
|
lin_tl_pdu_data *lin_tl_pdu;
|
|
lin_tl_pdu_data *lin_tl_rx_pdu;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
/* Get the current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
|
|
/* Get TL configuratio */
|
|
tl_conf = conf->tl_desc;
|
|
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
/* Get receive queue */
|
|
rx_queue = tl_conf->tl_rx_queue;
|
|
|
|
/* Single frame suport */
|
|
#else
|
|
lin_tl_pdu = (lin_tl_pdu_data *)tl_conf->tl_tx_single_pdu;
|
|
/* Get current PDU pointer of RX buffer */
|
|
lin_tl_rx_pdu = tl_conf->tl_current_rx_pdu_ptr;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_) */
|
|
|
|
/* Get the node attribute */
|
|
node_conf = conf->node_attribute;
|
|
|
|
/* Pack data to response PDU */
|
|
(*lin_tl_pdu)[0] = node_conf->configured_NAD;
|
|
(*lin_tl_pdu)[1] = 0x03; /* PCI */
|
|
(*lin_tl_pdu)[2] = RES_NEGATIVE; /* SID */
|
|
(*lin_tl_pdu)[3] = sid; /* D0 */
|
|
(*lin_tl_pdu)[4] = error_code; /* D1 */
|
|
(*lin_tl_pdu)[5] = 0xFF; /* D2 */
|
|
(*lin_tl_pdu)[6] = 0xFF; /* D3 */
|
|
(*lin_tl_pdu)[7] = 0xFF; /* D4 */
|
|
|
|
switch (sid)
|
|
{
|
|
#if (LIN_PROTOCOL == PROTOCOL_J2602)
|
|
case SERVICE_TARGET_RESET:
|
|
(*lin_tl_pdu)[1] = 0x06;
|
|
|
|
if (NEGATIVE == res_type)
|
|
{
|
|
(*lin_tl_pdu)[2] = RES_NEGATIVE;
|
|
}
|
|
else
|
|
{
|
|
|
|
(*lin_tl_pdu)[2] = RES_POSITIVE+ sid;
|
|
}
|
|
|
|
ident = (lin_product_id*)&node_conf->product_id;
|
|
(*lin_tl_pdu)[3] = (l_u8)(ident->supplier_id & 0xFF);
|
|
(*lin_tl_pdu)[4] = (l_u8)(ident->supplier_id >> 8);
|
|
(*lin_tl_pdu)[5] = (l_u8)(ident->function_id & 0xFF);
|
|
(*lin_tl_pdu)[6] = (l_u8)(ident->function_id >> 8);
|
|
(*lin_tl_pdu)[7] = ident->variant;
|
|
break;
|
|
#endif /* End (LIN_PROTOCOL == PROTOCOL_J2602) */
|
|
|
|
#if (LIN_PROTOCOL == PROTOCOL_21)
|
|
case SERVICE_READ_BY_IDENTIFY:
|
|
if (NEGATIVE == res_type)
|
|
{
|
|
(*lin_tl_pdu)[1] = 0x03;
|
|
(*lin_tl_pdu)[2] = RES_NEGATIVE;
|
|
(*lin_tl_pdu)[3] = sid;
|
|
(*lin_tl_pdu)[4] = error_code;
|
|
(*lin_tl_pdu)[5] = 0xFF;
|
|
(*lin_tl_pdu)[6] = 0xFF;
|
|
(*lin_tl_pdu)[7] = 0xFF;
|
|
}
|
|
else
|
|
{
|
|
(*lin_tl_pdu)[1] = PCI_RES_READ_BY_IDENTIFY;
|
|
(*lin_tl_pdu)[2] = RES_POSITIVE + sid;
|
|
|
|
if (error_code == LIN_PRODUCT_IDENT)
|
|
{
|
|
/* Get Identifier infor */
|
|
ident = (lin_product_id*)&node_conf->product_id;
|
|
(*lin_tl_pdu)[3] = (l_u8)(ident->supplier_id & 0xFF);
|
|
(*lin_tl_pdu)[4] = (l_u8)(ident->supplier_id >> 8);
|
|
(*lin_tl_pdu)[5] = (l_u8)(ident->function_id & 0xFF);
|
|
(*lin_tl_pdu)[6] = (l_u8)(ident->function_id >> 8);
|
|
(*lin_tl_pdu)[7] = ident->variant;
|
|
}
|
|
else if (error_code >= LIN_READ_USR_DEF_MIN && error_code <= LIN_READ_USR_DEF_MAX)
|
|
{
|
|
l_u8 data_callout[5] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
|
l_u8 retval = ld_read_by_id_callout(iii, error_code, data_callout);
|
|
if (retval == LD_POSITIVE_RESPONSE)
|
|
{
|
|
/* packing user defined pdu */
|
|
(*lin_tl_pdu)[3] = data_callout[0];
|
|
(*lin_tl_pdu)[4] = data_callout[1];
|
|
(*lin_tl_pdu)[5] = data_callout[2];
|
|
(*lin_tl_pdu)[6] = data_callout[3];
|
|
(*lin_tl_pdu)[7] = data_callout[4];
|
|
}
|
|
/* Check for data values*/
|
|
for (i = 4; i >= 0; i --)
|
|
{
|
|
if (data_callout[i] != 0xFF)
|
|
{
|
|
/* PCI: Data length is 1 (RSID) + all data exclude 0xFF */
|
|
(*lin_tl_pdu)[1] = i + 2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SERVICE_ASSIGN_FRAME_ID_RANGE: /* Mandatory for TL LIN 2.1 */
|
|
if (POSITIVE == res_type)
|
|
{
|
|
(*lin_tl_pdu)[1] = PCI_RES_ASSIGN_FRAME_ID_RANGE;
|
|
(*lin_tl_pdu)[2] = RES_POSITIVE + sid;
|
|
(*lin_tl_pdu)[3] = 0xFF;
|
|
(*lin_tl_pdu)[4] = 0xFF;
|
|
}
|
|
break;
|
|
|
|
case SERVICE_SAVE_CONFIGURATION:
|
|
if (POSITIVE == res_type)
|
|
{
|
|
/* PCI type */
|
|
(*lin_tl_pdu)[1] = PCI_RES_SAVE_CONFIGURATION;
|
|
/* SID */
|
|
(*lin_tl_pdu)[2] = RES_POSITIVE + sid;
|
|
/* Data unused */
|
|
(*lin_tl_pdu)[3] = 0xFF;
|
|
(*lin_tl_pdu)[4] = 0xFF;
|
|
}
|
|
break;
|
|
case SERVICE_ASSIGN_NAD:
|
|
if (POSITIVE == res_type)
|
|
{
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
node_conf->configured_NAD = rx_queue->tl_pdu[rx_queue->queue_header][7];
|
|
#else /* Single frame support */
|
|
node_conf->configured_NAD = (*lin_tl_rx_pdu)[7];
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/* Use intial NAD in response */
|
|
(*lin_tl_pdu)[0] = node_conf->initial_NAD;
|
|
/* PCI */
|
|
(*lin_tl_pdu)[1] = 0x01;
|
|
/* RSID */
|
|
(*lin_tl_pdu)[2] = 0xF0;
|
|
(*lin_tl_pdu)[3] = 0xFF;
|
|
(*lin_tl_pdu)[4] = 0xFF;
|
|
}
|
|
break;
|
|
case SERVICE_CONDITIONAL_CHANGE_NAD:
|
|
(*lin_tl_pdu)[1] = 0x01; /* PCI */
|
|
(*lin_tl_pdu)[2] = 0xF3; /* RSID */
|
|
(*lin_tl_pdu)[3] = 0xFF;
|
|
(*lin_tl_pdu)[4] = 0xFF;
|
|
break;
|
|
#endif /* End (LIN_PROTOCOL == PROTOCOL_21) */
|
|
default:
|
|
break;
|
|
} /* end of switch statement */
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
tl_conf->tl_tx_queue->queue_status = LD_QUEUE_FULL;
|
|
tl_conf->tl_tx_queue->queue_current_size = 1;
|
|
/* Put to transmit queue */
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
tl_conf->tl_tx_queue->tl_pdu[0][i] = (*lin_tl_pdu)[i];
|
|
}
|
|
tl_conf->tl_tx_msg_size = 1;
|
|
/* Set check N_As timeout */
|
|
tl_conf->tl_check_timeout = N_MAX_TIMEOUT_CNT;
|
|
tl_conf->tl_check_timeout_type = LD_CHECK_N_AS_TIMEOUT;
|
|
#else /* single frame support */
|
|
/* set current TX PDU to send out */
|
|
tl_conf->tl_current_tx_pdu_ptr = lin_tl_pdu;
|
|
tl_check_timeout_array[iii] = N_MAX_TIMEOUT_CNT;
|
|
tl_check_timeout_type_array[iii] = LD_CHECK_N_AS_TIMEOUT;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/* set number of SlaveResp response data */
|
|
tl_conf->tl_slaveresp_cnt = 1;
|
|
}
|
|
|
|
|
|
void lin_tl_get_pdu
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii
|
|
)
|
|
{
|
|
l_u8 i;
|
|
const lin_configuration *conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
lin_tl_pdu_data lin_tl_pdu_buff;
|
|
lin_tl_pdu_data *lin_tl_pdu = (lin_tl_pdu_data *)&lin_tl_pdu_buff;
|
|
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
|
|
/* Get TL configuration */
|
|
tl_conf = conf->tl_desc;
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
/* Get data from tx queue */
|
|
tl_get_raw(*lin_tl_pdu, tl_conf->tl_tx_queue, TRANSMISSION);
|
|
#else /* single frame support */
|
|
/* Get current PDU poiter of TX buffer */
|
|
lin_tl_pdu = tl_conf->tl_current_tx_pdu_ptr;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
/* Copy PDU to response buffer */
|
|
for (i = 1; i < 9; i++)
|
|
{
|
|
conf->response_buffer[i] = (*lin_tl_pdu)[i - 1];
|
|
}
|
|
}
|
|
|
|
|
|
void lin_tl_handler
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii
|
|
)
|
|
{
|
|
const lin_configuration * conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
lin_tl_pdu_data *lin_tl_pdu;
|
|
lin_node_attribute *node_conf;
|
|
l_u8 pci_type;
|
|
|
|
/* single frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_)
|
|
l_u8 length;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
|
|
/* Get the current configuration */
|
|
conf = (lin_configuration *)&lin_ifc_configuration[iii];
|
|
|
|
/* Get TL configuration */
|
|
tl_conf = conf->tl_desc;
|
|
|
|
/* Get the node attribute */
|
|
node_conf = (lin_node_attribute *)conf->node_attribute;
|
|
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
lin_tl_pdu = (lin_tl_pdu_data *)&(conf->response_buffer[1]);
|
|
pci_type = ((*lin_tl_pdu)[1] & 0xF0) >> 4;
|
|
#else /* single frame support */
|
|
lin_tl_pdu = tl_conf->tl_current_rx_pdu_ptr;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/* check NAD whether or not belongs to this slave node */
|
|
if (_SLAVE_ == conf->function)
|
|
{
|
|
if ((LD_BROADCAST != (*lin_tl_pdu)[0]) && \
|
|
(LD_FUNCTIONAL_NAD != (*lin_tl_pdu)[0]) && \
|
|
(((node_conf->configured_NAD != (*lin_tl_pdu)[0]) && (SERVICE_ASSIGN_NAD != (*lin_tl_pdu)[2])) || \
|
|
((node_conf->initial_NAD != (*lin_tl_pdu)[0]) && (SERVICE_ASSIGN_NAD == (*lin_tl_pdu)[2]))))
|
|
{
|
|
tl_conf->tl_slaveresp_cnt = 0;
|
|
return;
|
|
}
|
|
}
|
|
/* ingore Functional request */
|
|
if ((*lin_tl_pdu)[0] == LD_FUNCTIONAL_NAD)
|
|
{
|
|
return;
|
|
}
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
/* check error */
|
|
if (*conf->tl_service_status == LD_SERVICE_ERROR && pci_type == PCI_CF)
|
|
{
|
|
return;
|
|
}
|
|
/* process received PDU */
|
|
lin_process_pdu(iii, lin_tl_pdu);
|
|
#else /* single frame support */
|
|
/* Get PCI type */
|
|
pci_type = ((*lin_tl_pdu)[1] & 0xF0) >> 4;
|
|
switch (pci_type)
|
|
{
|
|
case PCI_SF: /* Single frame */
|
|
/* error handling: check length of message */
|
|
length = (*lin_tl_pdu)[1] & 0x0F;
|
|
if (6 < length)
|
|
{
|
|
return;
|
|
}
|
|
if (_SLAVE_ == conf->function)
|
|
{
|
|
lin_tl_attach_service(iii);
|
|
}
|
|
else
|
|
{
|
|
lin_tl_get_response(iii);
|
|
}
|
|
break;
|
|
case PCI_FF: /* First frame */
|
|
break;
|
|
case PCI_CF: /* Consecutive frame */
|
|
break;
|
|
default:
|
|
break;
|
|
} /* end of ckeck PCI_type */
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
}
|
|
|
|
|
|
void lin_tl_attach_service (l_ifc_handle iii)
|
|
{
|
|
const lin_configuration* conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
lin_node_attribute *node_conf;
|
|
l_u8 sid;
|
|
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
l_u8 frame_type;
|
|
lin_transport_layer_queue *rx_queue, *tx_queue;
|
|
l_u8 *service_flag;
|
|
l_u8 *service_supported;
|
|
l_u8 i;
|
|
l_u8 sid_supported_flag;
|
|
l_u8 NAD;
|
|
l_u16 supplierIdLsb;
|
|
l_u16 supplierIdMsb;
|
|
l_u16 functionIdLsb;
|
|
l_u16 functionIdMsb;
|
|
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
/* Get the node attribute */
|
|
node_conf = (lin_node_attribute *)conf->node_attribute;
|
|
/* Get TL description */
|
|
tl_conf = conf->tl_desc;
|
|
/* Get support sid */
|
|
service_supported = tl_conf->tl_service_supported;
|
|
service_flag = tl_conf->tl_service_flags;
|
|
rx_queue = tl_conf->tl_rx_queue;
|
|
tx_queue = tl_conf->tl_tx_queue;
|
|
NAD = rx_queue->tl_pdu[rx_queue->queue_header][0];
|
|
/* check if request is functional request */
|
|
if (NAD == LD_FUNCTIONAL_NAD)
|
|
{
|
|
/* reset receive queue */
|
|
rx_queue->queue_current_size = 0;
|
|
rx_queue->queue_header = 0;
|
|
rx_queue->queue_tail = 0;
|
|
rx_queue->queue_status = LD_NO_DATA;
|
|
/* update service state */
|
|
*conf->tl_diag_state = LD_DIAG_IDLE;
|
|
*conf->tl_service_status = LD_SERVICE_IDLE;
|
|
/* ignore response */
|
|
tl_conf->tl_no_of_pdu = 0;
|
|
tl_conf->tl_frame_counter = 0;
|
|
return;
|
|
}
|
|
/* prepare tx queue */
|
|
tx_queue->queue_current_size = 0;
|
|
tx_queue->queue_header = 0;
|
|
tx_queue->queue_tail = 0;
|
|
tx_queue->queue_status = LD_QUEUE_EMPTY;
|
|
/* Check whether RX Queue contains data */
|
|
if ((LD_DATA_AVAILABLE == ld_raw_rx_status(iii)))
|
|
{
|
|
/* get frame type */
|
|
frame_type = (rx_queue->tl_pdu[rx_queue->queue_header][1] & 0xF0) >> 4;
|
|
/* Get SID information */
|
|
if (frame_type == PCI_FF)
|
|
{
|
|
sid = rx_queue->tl_pdu[rx_queue->queue_header][3];
|
|
}
|
|
else
|
|
{
|
|
sid = rx_queue->tl_pdu[rx_queue->queue_header][2];
|
|
}
|
|
|
|
sid_supported_flag = 0;
|
|
for (i = 0; i < tl_conf->number_support_sid; i++)
|
|
{
|
|
if (service_supported[i] == sid)
|
|
{
|
|
service_flag[i] = 1;
|
|
sid_supported_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sid_supported_flag == 1)
|
|
{
|
|
switch (sid)
|
|
{
|
|
#if (LIN_PROTOCOL == PROTOCOL_21)
|
|
case SERVICE_ASSIGN_FRAME_ID_RANGE: /* Mandatory for TL LIN 2.1 */
|
|
lin_diagservice_assign_frame_id_range(iii);
|
|
break;
|
|
case SERVICE_READ_BY_IDENTIFY: /* Mandatory for TL LIN 2.1 & 2.0, Reject by J2602 */
|
|
lin_diagservice_read_by_identifier(iii); /* Mandatory LIN TL 2.1 */
|
|
break;
|
|
case SERVICE_SAVE_CONFIGURATION:
|
|
/* Set save configuration flag */
|
|
if (_MASTER_ == conf->function)
|
|
{
|
|
lin_save_configuration_flg[iii] = 0U;
|
|
}
|
|
else
|
|
{
|
|
lin_save_configuration_flg[iii] = 1U;
|
|
}
|
|
/* Response to master - RSID */
|
|
lin_tl_make_slaveres_pdu(iii, SERVICE_SAVE_CONFIGURATION, POSITIVE, 0U);
|
|
break;
|
|
case SERVICE_ASSIGN_NAD:
|
|
/* Get Supplier ID and Function ID*/
|
|
if ((NAD == node_conf->initial_NAD)|| (NAD == LD_BROADCAST))
|
|
{
|
|
supplierIdLsb = rx_queue->tl_pdu[rx_queue->queue_header][3];
|
|
supplierIdMsb = rx_queue->tl_pdu[rx_queue->queue_header][4];
|
|
functionIdLsb = rx_queue->tl_pdu[rx_queue->queue_header][5];
|
|
functionIdMsb = rx_queue->tl_pdu[rx_queue->queue_header][6];
|
|
/*Check if Supplier ID and Function ID match, then send positive response */
|
|
if ((((supplierIdMsb<<8)|supplierIdLsb) == (node_conf->product_id).supplier_id)||(((supplierIdMsb<<8)|supplierIdLsb) == LD_ANY_SUPPLIER))
|
|
if ((((functionIdMsb<<8)|functionIdLsb) == (node_conf->product_id).function_id)||(((functionIdMsb<<8)|functionIdLsb) == LD_ANY_FUNCTION))
|
|
{
|
|
lin_tl_make_slaveres_pdu(iii,SERVICE_ASSIGN_NAD, POSITIVE, 0);
|
|
}
|
|
}
|
|
break;
|
|
case SERVICE_CONDITIONAL_CHANGE_NAD:
|
|
lin_condittional_change_nad(iii);
|
|
break;
|
|
#endif /* (End LIN_PROTOCOL == LIN_PROTOCOL_21) */
|
|
|
|
#if LIN_PROTOCOL == PROTOCOL_J2602
|
|
case SERVICE_TARGET_RESET:
|
|
if (LIN_PROTOCOL_J2602 == conf->lin_protocol_version)
|
|
{
|
|
lin_diagservice_target_reset(iii);
|
|
}
|
|
break;
|
|
#endif /* (End LIN_PROTOCOL == LIN_PROTOCOL_J2602) */
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lin_tl_make_slaveres_pdu(iii, sid, NEGATIVE, SERVICE_NOT_SUPPORTED);
|
|
/* clear queue */
|
|
tl_conf->tl_receive_msg_status = LD_NO_MSG;
|
|
tl_conf->tl_rx_msg_status = LD_COMPLETED;
|
|
rx_queue->queue_status = LD_NO_DATA;
|
|
rx_queue->queue_current_size = 0;
|
|
rx_queue->queue_header = rx_queue->queue_tail;
|
|
}
|
|
}
|
|
|
|
#else /* single frame support */
|
|
lin_tl_pdu_data *lin_tl_pdu;
|
|
l_u8 NAD;
|
|
l_u8 *service_flag;
|
|
l_u8 *service_supported;
|
|
l_u8 i;
|
|
l_u8 sid_supported_flag;
|
|
l_u16 supplierIdLsb;
|
|
l_u16 supplierIdMsb;
|
|
l_u16 functionIdLsb;
|
|
l_u16 functionIdMsb;
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
/* Get the node attribute */
|
|
node_conf = (lin_node_attribute *)conf->node_attribute;
|
|
/* Get TL description */
|
|
tl_conf = conf->tl_desc;
|
|
/* Get support sid */
|
|
service_supported = tl_conf->tl_service_supported;
|
|
/* Get service flag */
|
|
service_flag = tl_conf->tl_service_flags;
|
|
/* Get current PDU pointer of RX buffer */
|
|
lin_tl_pdu = tl_conf->tl_current_rx_pdu_ptr;
|
|
/* Get SCI information */
|
|
sid = (*lin_tl_pdu)[2];
|
|
NAD = (*lin_tl_pdu)[0];
|
|
if (NAD == LD_FUNCTIONAL_NAD)
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
sid_supported_flag = 0;
|
|
for (i = 0; i < tl_conf->number_support_sid; i++)
|
|
{
|
|
if (service_supported[i] == sid)
|
|
{
|
|
service_flag[i] = 1;
|
|
sid_supported_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sid_supported_flag == 1)
|
|
{/* Check whether or not the Service is supported by the Slave node */
|
|
switch (sid)
|
|
{
|
|
#if LIN_PROTOCOL == PROTOCOL_21
|
|
case SERVICE_ASSIGN_FRAME_ID_RANGE: /* Mandatory for TL LIN 2.1 */
|
|
lin_diagservice_assign_frame_id_range(iii);
|
|
break;
|
|
case SERVICE_READ_BY_IDENTIFY: /* Mandatory for TL LIN 2.1 & 2.0, Reject by J2602 */
|
|
lin_diagservice_read_by_identifier(iii); /* Mandatory LIN TL 2.1 */
|
|
break;
|
|
|
|
case SERVICE_SAVE_CONFIGURATION:
|
|
/* Set save configuration flag */
|
|
if (_MASTER_ == conf->function)
|
|
{
|
|
lin_save_configuration_flg[iii] = 0;
|
|
}
|
|
else
|
|
{
|
|
lin_save_configuration_flg[iii] = 1;
|
|
}
|
|
/* Response to master - RSID */
|
|
lin_tl_make_slaveres_pdu(iii, SERVICE_SAVE_CONFIGURATION, POSITIVE, 0);
|
|
break;
|
|
case SERVICE_ASSIGN_NAD:
|
|
if ((NAD == node_conf->initial_NAD)|| (NAD == LD_BROADCAST))
|
|
{
|
|
supplierIdLsb = (*lin_tl_pdu)[3];
|
|
supplierIdMsb = (*lin_tl_pdu)[4];
|
|
functionIdLsb = (*lin_tl_pdu)[5];
|
|
functionIdMsb = (*lin_tl_pdu)[6];
|
|
/*Check if Supplier ID and Function ID match, then send positive response */
|
|
if ((((supplierIdMsb<<8)|supplierIdLsb) == (node_conf->product_id).supplier_id)||(((supplierIdMsb<<8)|supplierIdLsb) == LD_ANY_SUPPLIER))
|
|
if ((((functionIdMsb<<8)|functionIdLsb) == (node_conf->product_id).function_id)||(((functionIdMsb<<8)|functionIdLsb) == LD_ANY_FUNCTION))
|
|
{
|
|
lin_tl_make_slaveres_pdu(iii,SERVICE_ASSIGN_NAD, POSITIVE, 0);
|
|
}
|
|
}
|
|
break;
|
|
case SERVICE_CONDITIONAL_CHANGE_NAD:
|
|
lin_condittional_change_nad(iii);
|
|
break;
|
|
#endif /* (End LIN_PROTOCOL == LIN_PROTOCOL_21) */
|
|
|
|
#if LIN_PROTOCOL == PROTOCOL_J2602
|
|
case SERVICE_TARGET_RESET:
|
|
if (LIN_PROTOCOL_J2602 == conf->lin_protocol_version)
|
|
{
|
|
lin_diagservice_target_reset(iii);
|
|
}
|
|
break;
|
|
#endif /* (End LIN_PROTOCOL == LIN_PROTOCOL_J2602) */
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lin_tl_make_slaveres_pdu(iii, sid, NEGATIVE, SERVICE_NOT_SUPPORTED);
|
|
}
|
|
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
}
|
|
|
|
void lin_tl_get_response (l_ifc_handle iii)
|
|
{
|
|
const lin_configuration* conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
lin_tl_pdu_data *lin_tl_pdu;
|
|
l_u8 *service_flag;
|
|
l_u8 *service_supported;
|
|
l_u8 i;
|
|
l_u8 sid_supported_flag;
|
|
l_u8 sci = 0;
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
lin_transport_layer_queue *rx_queue;
|
|
l_u8 frame_type;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
|
|
/* Get TL description */
|
|
tl_conf = conf->tl_desc;
|
|
/* Get support sid */
|
|
service_supported = tl_conf->tl_service_supported;
|
|
/* Get service flag */
|
|
service_flag = tl_conf->tl_service_flags;
|
|
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
/* Get current PDU pointer of RX buffer */
|
|
rx_queue = tl_conf->tl_rx_queue;
|
|
lin_tl_pdu = (lin_tl_pdu_data *)(tl_conf->tl_rx_queue->tl_pdu[rx_queue->queue_header]);
|
|
/* get frame type */
|
|
frame_type = ((*lin_tl_pdu)[1] & 0xF0) >> 4;
|
|
/* Set configuration service status */
|
|
*conf->tl_service_status = LD_SERVICE_IDLE;
|
|
if (frame_type == SF)
|
|
{
|
|
sci = (*lin_tl_pdu)[2];
|
|
}
|
|
else if (frame_type == FF)
|
|
{
|
|
sci = (*lin_tl_pdu)[3];
|
|
}
|
|
#else /* single frame support */
|
|
/* Get current PDU pointer of RX buffer */
|
|
lin_tl_pdu = tl_conf->tl_current_rx_pdu_ptr;
|
|
tl_conf->tl_service_status = LD_SERVICE_IDLE;
|
|
sci = (*lin_tl_pdu)[2];
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/* Update last RSID */
|
|
tl_conf->tl_last_RSID = sci;
|
|
/* Get SID information */
|
|
|
|
if (RES_NEGATIVE == sci)
|
|
{
|
|
/* set response configuration status to negative response */
|
|
tl_conf->tl_last_cfg_result = LD_NEGATIVE;
|
|
/* update error code */
|
|
tl_conf->tl_ld_error_code = (*lin_tl_pdu)[4];
|
|
|
|
/* switch to normal schedule table */
|
|
*conf->active_schedule_id = *conf->previous_schedule_id;
|
|
/* Clear queue */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
tl_conf->tl_rx_msg_status = LD_COMPLETED;
|
|
*conf->tl_service_status = LD_SERVICE_IDLE;
|
|
#else
|
|
tl_conf->tl_service_status = LD_SERVICE_IDLE;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
return;
|
|
}
|
|
sci = sci - 0x40;
|
|
|
|
sid_supported_flag = 0;
|
|
for (i = 0; i < tl_conf->number_support_sid; i++)
|
|
{
|
|
if (service_supported[i] == sci)
|
|
{
|
|
service_flag[i] = 1;
|
|
sid_supported_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (sid_supported_flag == 1)
|
|
{
|
|
|
|
sid_supported_flag = 0;
|
|
/* Check the result of service */
|
|
switch (sci)
|
|
{
|
|
case SERVICE_READ_BY_IDENTIFY:
|
|
(tl_conf->tl_ident_data)[0] = (*lin_tl_pdu)[4];
|
|
(tl_conf->tl_ident_data)[1] = (*lin_tl_pdu)[3];
|
|
(tl_conf->tl_ident_data)[2] = (*lin_tl_pdu)[6];
|
|
(tl_conf->tl_ident_data)[3] = (*lin_tl_pdu)[5];
|
|
(tl_conf->tl_ident_data)[4] = (*lin_tl_pdu)[7];
|
|
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
tl_conf->tl_rx_msg_status = LD_COMPLETED;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
break;
|
|
case SERVICE_TARGET_RESET:
|
|
case SERVICE_ASSIGN_FRAME_ID:
|
|
case SERVICE_ASSIGN_FRAME_ID_RANGE:
|
|
case SERVICE_ASSIGN_NAD:
|
|
case SERVICE_CONDITIONAL_CHANGE_NAD:
|
|
case SERVICE_SAVE_CONFIGURATION:
|
|
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
tl_conf->tl_rx_msg_status = LD_COMPLETED;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
break;
|
|
/* check diagnostic service is belong to class II or class III */
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
/* Set the last configuration result */
|
|
tl_conf->tl_last_cfg_result = LD_SUCCESS;
|
|
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
*conf->tl_service_status = LD_SERVICE_IDLE;
|
|
#else
|
|
tl_conf->tl_service_status = LD_SERVICE_IDLE;
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/*If Master node is running with Diagnostic Slave Response Schedule table */
|
|
/* then switch back to previous normal table */
|
|
if (*conf->active_schedule_id == (conf->schedule_start + 3))
|
|
{
|
|
/* switch to normal schedule table */
|
|
*conf->active_schedule_id = *conf->previous_schedule_id;
|
|
conf->schedule_start_entry[*conf->active_schedule_id] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* single frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_)
|
|
|
|
void lin_tl_update_tx_flag
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii
|
|
)
|
|
{
|
|
const lin_configuration *conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
|
|
/* Get TL configuration */
|
|
tl_conf = conf->tl_desc;
|
|
|
|
/* Check if master node */
|
|
if (_MASTER_ == conf->function)
|
|
{
|
|
/* Update TX : Master ->Slave */
|
|
/* Master request */
|
|
if (0x3C == *(conf->current_pid))
|
|
{
|
|
tl_conf->tl_cnt_to_send--;
|
|
/* Set state of service is LD_REQUEST_FINISHED */
|
|
tl_conf->tl_service_status = LD_REQUEST_FINISHED;
|
|
}
|
|
}
|
|
/* Slave node */
|
|
else
|
|
{
|
|
/* Update TX SlaveResponse Frame: Slave->Master */
|
|
|
|
}
|
|
}
|
|
|
|
void lin_tl_put_pdu
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii
|
|
)
|
|
{
|
|
l_u8 i;
|
|
const lin_configuration *conf;
|
|
lin_tl_descriptor *tl_conf;
|
|
lin_tl_pdu_data *lin_tl_pdu;
|
|
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
|
|
/* Get TL configuration */
|
|
tl_conf = conf->tl_desc;
|
|
|
|
/* Set PDU for RX buffer */
|
|
tl_conf->tl_current_rx_pdu_ptr = (lin_tl_pdu_data *)tl_conf->tl_rx_single_pdu;
|
|
|
|
/* Get current PDU poiter of RX buffer */
|
|
lin_tl_pdu = tl_conf->tl_current_rx_pdu_ptr;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
(*lin_tl_pdu)[i] = conf->response_buffer[i+1];
|
|
}
|
|
}
|
|
|
|
|
|
void lin_tl_no_response
|
|
(
|
|
/* [IN] interface name */
|
|
l_ifc_handle iii
|
|
)
|
|
{
|
|
const lin_configuration* conf;
|
|
|
|
/* Get current configuration */
|
|
conf = &lin_ifc_configuration[iii];
|
|
|
|
/* Clear response data */
|
|
conf->tl_desc->tl_slaveresp_cnt = 0;
|
|
/* Set configuration service status */
|
|
conf->tl_desc->tl_service_status = LD_SERVICE_ERROR;
|
|
/* Set the last configuration result */
|
|
conf->tl_desc->tl_last_cfg_result = LD_NO_RESPONSE;
|
|
}
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_SINGLE_FRAME_) */
|
|
|
|
|
|
#endif /* End (_LIN_MODE_ == _MASTER_MODE_) */
|
|
|
|
/* ------------- End of code for Multi Interface --------------- */
|
|
/* multi frame support */
|
|
#if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)
|
|
/* COMMON FUNCTIONS */
|
|
void tl_put_raw
|
|
(
|
|
/* [IN] buffer for the data */
|
|
const l_u8* const data,
|
|
/* [IN] queue for containing data */
|
|
lin_transport_layer_queue *queue,
|
|
/* [IN] Direction */
|
|
l_u8 direction
|
|
)
|
|
{
|
|
lin_tl_pdu_data *queue_data;
|
|
l_u8 i;
|
|
|
|
/* Get transmit queue */
|
|
queue_data = queue->tl_pdu;
|
|
|
|
/* check status of queue */
|
|
if (LD_QUEUE_FULL != queue->queue_status)
|
|
{
|
|
/* prcess queue tail */
|
|
if ((LD_QUEUE_EMPTY == queue->queue_status) || (LD_NO_DATA == queue->queue_status))
|
|
{
|
|
/* Set status of queue */
|
|
if (TRANSMISSION == direction)
|
|
{
|
|
queue->queue_status = LD_QUEUE_AVAILABLE;
|
|
}
|
|
else
|
|
{
|
|
queue->queue_status = LD_DATA_AVAILABLE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Check if queue size equal to queue tail */
|
|
if (queue->queue_max_size == queue->queue_tail + 1)
|
|
{
|
|
queue->queue_tail = 0;
|
|
}
|
|
else
|
|
{
|
|
queue->queue_tail++;
|
|
}
|
|
}
|
|
/* copy data to queue */
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
queue_data[queue->queue_tail][i] = data[i];
|
|
}
|
|
/* update queue status */
|
|
queue->queue_current_size++;
|
|
if (queue->queue_current_size >= queue->queue_max_size)
|
|
{
|
|
queue->queue_status = LD_QUEUE_FULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void tl_get_raw
|
|
(
|
|
/* [OUT] buffer for store data received */
|
|
l_u8* const data,
|
|
/* queue for containing data */
|
|
lin_transport_layer_queue *queue,
|
|
/* direction for transmission */
|
|
l_u8 direction
|
|
)
|
|
{
|
|
|
|
lin_transport_layer_queue *tl_queue;
|
|
lin_tl_pdu_data *queue_data;
|
|
l_u8 i;
|
|
l_u16 queue_header;
|
|
|
|
tl_queue = queue;
|
|
/* Get queue */
|
|
queue_data = tl_queue->tl_pdu;
|
|
|
|
/* Check queue status (is the queue contains data? if yes: get data from queue and put them to buffer) */
|
|
if ((LD_NO_DATA != tl_queue->queue_status) && (LD_QUEUE_EMPTY != tl_queue->queue_status))
|
|
{
|
|
/* get data from head queue */
|
|
queue_header = tl_queue->queue_header;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
*(data+i) = queue_data[queue_header][i];
|
|
}
|
|
|
|
/* update queue status */
|
|
if (0 == (--queue->queue_current_size))
|
|
{
|
|
if (TRANSMISSION == direction)
|
|
{
|
|
queue->queue_status = LD_QUEUE_EMPTY;
|
|
}
|
|
else
|
|
{
|
|
queue->queue_status = LD_NO_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TRANSMISSION == direction)
|
|
{
|
|
queue->queue_status = LD_QUEUE_AVAILABLE;
|
|
}
|
|
else
|
|
{
|
|
queue->queue_status = LD_DATA_AVAILABLE;
|
|
}
|
|
}
|
|
|
|
/* change queue header */
|
|
if (0 != queue->queue_current_size)
|
|
{
|
|
if (queue->queue_header == queue->queue_max_size - 1)
|
|
{
|
|
queue->queue_header = 0;
|
|
}
|
|
else
|
|
{
|
|
queue->queue_header++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */
|
|
/**
|
|
* @}
|
|
*/
|