/****************************************************************************** * * Freescale Semiconductor Inc. * (c) Copyright 2008-2015 Freescale Semiconductor, Inc. * ALL RIGHTS RESERVED. * ******************************************************************************/ /**************************************************************************//** * @addtogroup lin21tl_api_group * @{ ******************************************************************************/ /**************************************************************************//** * * @file lin_lin21tl_api.c * * @author FPT Software * * @brief LIN21 LIN transport layer and configuration functions * ******************************************************************************/ /****************************************************************************** * * History: * * 20090409 v1.0 First version * *****************************************************************************/ #include "lin_lin21tl_api.h" #if LIN_MODE == _MASTER_MODE_ #if LIN_PROTOCOL == PROTOCOL_21 /** @} */ /** @addtogroup node_configuration_group * @{ */ l_u8 ld_is_ready( /* [IN] interface name */ l_ifc_handle iii) { /* multi frame support */ #if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) return (l_u8) (*lin_ifc_configuration[iii].tl_service_status); #else /* single frame support */ lin_configuration const *conf; /* Get current configuration */ conf = &lin_ifc_configuration[iii]; return (l_u8)(conf->tl_desc->tl_service_status); #endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */ } void ld_check_response( /* [IN] interface name */ l_ifc_handle iii, /* [OUT] buffer for saving the response ID */ l_u8* const RSID, /* [OUT] buffer for saving the error code */ l_u8* const error_code) { lin_configuration const *conf; lin_tl_descriptor *_tl_desc; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; /* Get TL configuration */ _tl_desc = conf->tl_desc; /* Get last reponse service identifier */ *RSID = _tl_desc->tl_last_RSID; /* Get the error code of the last config sercive if it is negative response */ if (LD_NEGATIVE == (_tl_desc->tl_last_cfg_result)) { *error_code = _tl_desc->tl_ld_error_code; } } void ld_assign_frame_id_range( /* [IN] interface name */ l_ifc_handle iii, /* [IN] NAD value of the target node */ l_u8 NAD, /* [IN] specifies which is the first frame to assign a PID */ l_u8 start_index, /* [IN] list of protected identifier */ const l_u8* const PIDs) { /* multi frame support */ #if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) const lin_configuration * conf; l_u8 Buff[6]; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; if (*conf->tl_service_status != LD_SERVICE_BUSY) { /* pack data into a single frame */ Buff[0] = 0xB7; Buff[1] = start_index; Buff[2] = PIDs[0]; Buff[3] = PIDs[1]; Buff[4] = PIDs[2]; Buff[5] = PIDs[3]; /* put data into TX_QUEUE */ ld_send_message(iii, 6, NAD, Buff); /* set node config status to busy */ *conf->tl_service_status = LD_SERVICE_BUSY; } #else /* single frame support */ lin_tl_pdu_data *lin_tl_pdu; lin_configuration *conf; lin_tl_descriptor *tl_conf; /* Get current configuration */ conf = (lin_configuration *)&lin_ifc_configuration[iii]; /* Get TL configuration */ tl_conf = conf->tl_desc; /* Get pointer to TX single frame PDU */ lin_tl_pdu = (lin_tl_pdu_data *)tl_conf->tl_tx_single_pdu; /* check service is busy? */ if (LD_SERVICE_BUSY != tl_conf->tl_service_status) { /* Create data for PDU */ (*lin_tl_pdu)[0] = NAD; (*lin_tl_pdu)[1] = 0x06; (*lin_tl_pdu)[2] = 0xB7; (*lin_tl_pdu)[3] = start_index; (*lin_tl_pdu)[4] = PIDs[0]; (*lin_tl_pdu)[5] = PIDs[1]; (*lin_tl_pdu)[6] = PIDs[2]; (*lin_tl_pdu)[7] = PIDs[3]; /* Set state of service is BUSY */ tl_conf->tl_service_status = LD_SERVICE_BUSY; /* Notify to Master task sending frame */ tl_conf->tl_cnt_to_send = 1; /* Switch to master request schedule table */ *conf->previous_schedule_id = *conf->active_schedule_id; *conf->active_schedule_id = conf->schedule_start + 2; conf->schedule_start_entry[*conf->active_schedule_id] = 0; /* End of switch to diagnostic schedule table */ } /* End of checking service status */ #endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */ } /* End of checking service status */ /** @} */ /** @addtogroup lin21tl_api_group * @{ */ /* multi frame support */ #if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) l_u8 diag_get_flag( /* [IN] interface name */ l_ifc_handle iii, /* [IN] flag order */ l_u8 flag_order) { lin_configuration *conf; lin_tl_descriptor *tl_conf; l_u8 *service_flag; /* Get current configuration */ conf = (lin_configuration *) &lin_ifc_configuration[iii]; /* Get TL configuration */ tl_conf = conf->tl_desc; service_flag = tl_conf->tl_service_flags; if (flag_order >= tl_conf->number_support_sid) { return 0; } else { return (l_u8) service_flag[flag_order]; } } void diag_clear_flag(l_ifc_handle iii, l_u8 flag_order) { lin_configuration *conf; lin_tl_descriptor *tl_conf; l_u8 *service_flag; /* Get current configuration */ conf = (lin_configuration *) &lin_ifc_configuration[iii]; /* Get TL configuration */ tl_conf = conf->tl_desc; service_flag = tl_conf->tl_service_flags; if (flag_order < tl_conf->number_support_sid) { service_flag[flag_order] = 0; } } /* diagnostic services class II */ void diag_read_data_by_identifier(l_ifc_handle iii, const l_u8 NAD, l_u8 * const data) { l_u8 Buff[3]; const lin_configuration *conf; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; /* check whether service status is idle or not */ if (*conf->tl_service_status != LD_SERVICE_BUSY) { /* check whether input data contains correct data */ /* pack data */ Buff[0] = 0x22; Buff[1] = data[0]; Buff[2] = data[1]; /* send message to transport layer */ ld_send_message(iii, 3, NAD, Buff); /* set service status to busy */ *conf->tl_service_status = LD_SERVICE_BUSY; } } void diag_write_data_by_identifier(l_ifc_handle iii, const l_u8 NAD, l_u16 data_length, l_u8 * const data) { l_u8 Buff[MAX_LENGTH_SERVICE]; l_u8 i; l_u16 temp = 0; const lin_configuration * conf; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; /* Check if length of data is greater than length maximum */ if (data_length < MAX_LENGTH_SERVICE) { /* check whether service status is idle or not */ if (*conf->tl_service_status != LD_SERVICE_BUSY) { /* check whether input data contains correct data */ temp = data[0]; temp <<= 8; temp |= data[1]; /* pack data */ Buff[0] = 0x2E; if ((temp == 0x0092) || (temp == 0x0205)) { for (i = 0; i < data_length; i++) { Buff[i + 1] = data[i]; } ld_send_message(iii, data_length + 1, NAD, Buff); /* set service status to busy */ *conf->tl_service_status = LD_SERVICE_BUSY; } } } } /* Diagnostic services class III */ #if (_DIAG_CLASS_SUPPORT_ == _DIAG_CLASS_III_) /* ----------------- Session control -------------------- */ void diag_session_control (l_ifc_handle iii, const l_u8 NAD, l_u16 data_length, l_u8 *const data) { l_u8 Buff[MAX_LENGTH_SERVICE]; l_u8 i; const lin_configuration * conf; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; /* Check if length of data is greater than length maximum */ if (data_length < MAX_LENGTH_SERVICE) { /* check whether service status is idle or not */ if (*conf->tl_service_status != LD_SERVICE_BUSY) { /* pack data */ Buff[0] = 0x10; for (i = 0; i < data_length; i++) { Buff[i+1] = data[i]; } ld_send_message(iii, data_length+1, NAD, Buff); /* set service status to busy */ *conf->tl_service_status = LD_SERVICE_BUSY; } } } /* ----------------- Fault memory -------------------- */ void diag_fault_memory_read (l_ifc_handle iii, const l_u8 NAD, l_u16 data_length, l_u8 *const data) { l_u8 Buff[MAX_LENGTH_SERVICE]; l_u8 i; l_u16 temp = 0; const lin_configuration * conf; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; /* Check if length of data is greater than length maximum */ if (data_length < MAX_LENGTH_SERVICE) { /* check whether service status is idle or not */ if (*conf->tl_service_status != LD_SERVICE_BUSY) { /* pack data */ Buff[0] = 0x19; for (i = 0; i < data_length; i++) { Buff[i+1] = data[i]; } ld_send_message(iii, data_length+1, NAD, Buff); /* set service status to busy */ *conf->tl_service_status = LD_SERVICE_BUSY; } } } void diag_fault_memory_clear (l_ifc_handle iii, const l_u8 NAD, l_u16 data_length, l_u8 *const data) { l_u8 Buff[MAX_LENGTH_SERVICE]; l_u8 i; l_u16 temp = 0; const lin_configuration * conf; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; /* Check if length of data is greater than length maximum */ if (data_length < MAX_LENGTH_SERVICE) { /* check whether service status is idle or not */ if (*conf->tl_service_status != LD_SERVICE_BUSY) { /* pack data */ Buff[0] = 0x14; for (i = 0; i < data_length; i++) { Buff[i+1] = data[i]; } ld_send_message(iii, data_length+1, NAD, Buff); /* set service status to busy */ *conf->tl_service_status = LD_SERVICE_BUSY; } } } /* ----------------- I/O control -------------------- */ void diag_IO_control (l_ifc_handle iii, const l_u8 NAD, l_u16 data_length, l_u8 *const data) { l_u8 Buff[MAX_LENGTH_SERVICE]; l_u8 i; l_u16 temp = 0; const lin_configuration * conf; /* Get the current configuration */ conf = &lin_ifc_configuration[iii]; /* Check if length of data is greater than length maximum */ if (data_length < MAX_LENGTH_SERVICE) { /* check whether service status is idle or not */ if (*conf->tl_service_status != LD_SERVICE_BUSY) { /* pack data */ Buff[0] = 0x2F; for (i = 0; i < data_length; i++) { Buff[i+1] = data[i]; } ld_send_message(iii, data_length+1, NAD, Buff); /* set service status to busy */ *conf->tl_service_status = LD_SERVICE_BUSY; } } } #endif /* End (_DIAG_CLASS_SUPPORT_ == _DIAG_CLASS_III_) */ #endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */ #endif /* End of (LIN_PROTOCOL == PROTOCOL_21) */ #endif /* End LIN_MODE == _MASTER_MODE_ */ #if LIN_MODE == _SLAVE_MODE_ #if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) /* get diagnostic flag */ l_u8 diag_get_flag(l_u8 flag_order) { if (flag_order >= _DIAG_NUMBER_OF_SERVICES_) { return 0; } else { return (l_u8) lin_diag_services_flag[flag_order]; } } void diag_clear_flag(l_u8 flag_order) { if (flag_order < _DIAG_NUMBER_OF_SERVICES_) { lin_diag_services_flag[flag_order] = 0; } } #endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */ #endif/* End LIN_MODE == _SLAVE_MODE_ */ /** @} */