diff --git a/src/bacnet/datalink/dlmstp.c b/src/bacnet/datalink/dlmstp.c index 2ab34226..a259eb9d 100644 --- a/src/bacnet/datalink/dlmstp.c +++ b/src/bacnet/datalink/dlmstp.c @@ -372,6 +372,11 @@ uint16_t dlmstp_receive( MSTP_Port->DataRegister = data_register; } MSTP_Receive_Frame_FSM(MSTP_Port); + if (MSTP_Port->receive_state == MSTP_RECEIVE_STATE_PREAMBLE) { + if (user->Preamble_Callback) { + user->Preamble_Callback(); + } + } /* process another byte, if available */ if (!driver->read(NULL)) { break; @@ -387,9 +392,21 @@ uint16_t dlmstp_receive( } if (MSTP_Port->ReceivedValidFrame) { user->Statistics.receive_valid_frame_counter++; + if (user->Valid_Frame_Rx_Callback) { + user->Valid_Frame_Rx_Callback( + MSTP_Port->SourceAddress, MSTP_Port->DestinationAddress, + MSTP_Port->FrameType, MSTP_Port->InputBuffer, + MSTP_Port->DataLength); + } } if (MSTP_Port->ReceivedInvalidFrame) { user->Statistics.receive_invalid_frame_counter++; + if (user->Invalid_Frame_Rx_Callback) { + user->Invalid_Frame_Rx_Callback( + MSTP_Port->SourceAddress, MSTP_Port->DestinationAddress, + MSTP_Port->FrameType, MSTP_Port->InputBuffer, + MSTP_Port->DataLength); + } } if (MSTP_Port->receive_state == MSTP_RECEIVE_STATE_IDLE) { /* only node state machines while rx is idle */ @@ -805,6 +822,80 @@ uint32_t dlmstp_baud_rate(void) return driver->baud_rate(); } +/** + * @brief Set the MS/TP Frame Complete callback + * @param cb_func - callback function to be called when a frame is received + */ +void dlmstp_set_frame_rx_complete_callback( + dlmstp_hook_frame_rx_complete_cb cb_func) +{ + struct dlmstp_user_data_t *user; + + if (!MSTP_Port) { + return; + } + user = MSTP_Port->UserData; + if (!user) { + return; + } + user->Valid_Frame_Rx_Callback = cb_func; +} + +/** + * @brief Set the MS/TP Frame Complete callback + * @param cb_func - callback function to be called when a frame is received + */ +void dlmstp_set_invalid_frame_rx_complete_callback( + dlmstp_hook_frame_rx_complete_cb cb_func) +{ + struct dlmstp_user_data_t *user; + + if (!MSTP_Port) { + return; + } + user = MSTP_Port->UserData; + if (!user) { + return; + } + user->Invalid_Frame_Rx_Callback = cb_func; +} + +/** + * @brief Set the MS/TP Preamble callback + * @param cb_func - callback function to be called when a preamble is received + */ +void dlmstp_set_frame_rx_start_callback(dlmstp_hook_frame_rx_start_cb cb_func) +{ + struct dlmstp_user_data_t *user; + + if (!MSTP_Port) { + return; + } + user = MSTP_Port->UserData; + if (!user) { + return; + } + user->Preamble_Callback = cb_func; +} + +/** + * @brief Reset the MS/TP statistics + */ +void dlmstp_reset_statistics(void) +{ + struct dlmstp_user_data_t *user; + struct dlmstp_statistics *stats; + + if (!MSTP_Port) { + return; + } + user = MSTP_Port->UserData; + if (!user) { + return; + } + memset(&user->Statistics, 0, sizeof(struct dlmstp_statistics)); +} + /** * @brief Copy the MSTP port statistics if they exist * @param statistics - MSTP port statistics diff --git a/src/bacnet/datalink/dlmstp.h b/src/bacnet/datalink/dlmstp.h index da12eafd..2cf1c744 100644 --- a/src/bacnet/datalink/dlmstp.h +++ b/src/bacnet/datalink/dlmstp.h @@ -82,20 +82,6 @@ struct dlmstp_rs485_driver { void (*silence_reset)(void); }; -/** - * An example structure of user data for BACnet MS/TP - */ -struct dlmstp_user_data_t { - struct dlmstp_statistics Statistics; - struct dlmstp_rs485_driver *RS485_Driver; - /* the PDU Queue is made of Nmax_info_frames x dlmstp_packet's */ - RING_BUFFER PDU_Queue; - struct dlmstp_packet PDU_Buffer[DLMSTP_MAX_INFO_FRAMES]; - bool Initialized; - bool ReceivePacketPending; - void *Context; -}; - /* callback to signify the receipt of a preamble */ typedef void (*dlmstp_hook_frame_rx_start_cb)(void); @@ -107,6 +93,23 @@ typedef void (*dlmstp_hook_frame_rx_complete_cb)( uint8_t *pdu, uint16_t pdu_len); +/** + * An example structure of user data for BACnet MS/TP + */ +struct dlmstp_user_data_t { + struct dlmstp_statistics Statistics; + struct dlmstp_rs485_driver *RS485_Driver; + dlmstp_hook_frame_rx_start_cb Preamble_Callback; + dlmstp_hook_frame_rx_complete_cb Valid_Frame_Rx_Callback; + dlmstp_hook_frame_rx_complete_cb Invalid_Frame_Rx_Callback; + /* the PDU Queue is made of Nmax_info_frames x dlmstp_packet's */ + RING_BUFFER PDU_Queue; + struct dlmstp_packet PDU_Buffer[DLMSTP_MAX_INFO_FRAMES]; + bool Initialized; + bool ReceivePacketPending; + void *Context; +}; + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -216,6 +219,9 @@ void dlmstp_silence_reset(void *arg); BACNET_STACK_EXPORT void dlmstp_set_frame_rx_complete_callback( dlmstp_hook_frame_rx_complete_cb cb_func); +BACNET_STACK_EXPORT +void dlmstp_set_invalid_frame_rx_complete_callback( + dlmstp_hook_frame_rx_complete_cb cb_func); /* Set the callback function to be called every time the start of a */ /* frame is detected. This is not necessary for normal usage, but is */