OpenLcbCLib 1.0 Alpha
OpenSource C Library to create OpenLcb/Lcc Nodes
Loading...
Searching...
No Matches
can_rx_message_handler.c File Reference

Implementation of message handlers for CAN receive operations. More...

Macros

#define CAN_RX_INPROCESS_TIMEOUT_TICKS   30
 Multi-frame assembly timeout in 100ms ticks (3 seconds).
 

Functions

void CanRxMessageHandler_initialize (const interface_can_rx_message_handler_t *interface_can_frame_message_handler)
 Stores the dependency-injection interface pointer.
 
void CanRxMessageHandler_first_frame (can_msg_t *can_msg, uint8_t offset, payload_type_enum data_type)
 Handles the first frame of a multi-frame OpenLCB message.
 
void CanRxMessageHandler_middle_frame (can_msg_t *can_msg, uint8_t offset)
 Handles a middle frame of a multi-frame OpenLCB message.
 
void CanRxMessageHandler_last_frame (can_msg_t *can_msg, uint8_t offset)
 Handles the last frame of a multi-frame OpenLCB message.
 
void CanRxMessageHandler_single_frame (can_msg_t *can_msg, uint8_t offset, payload_type_enum data_type)
 Handles a complete single-frame OpenLCB message.
 
void CanRxMessageHandler_can_legacy_snip (can_msg_t *can_msg, uint8_t offset, payload_type_enum data_type)
 Handles legacy SNIP messages that lack standard multi-frame framing bits.
 
void CanRxMessageHandler_stream_frame (can_msg_t *can_msg, uint8_t offset, payload_type_enum data_type)
 Stream frame handler — reserved for future use, not yet implemented.
 
void CanRxMessageHandler_cid_frame (can_msg_t *can_msg)
 Handles CID frames per CanFrameTransferS §6.2.5.
 
void CanRxMessageHandler_rid_frame (can_msg_t *can_msg)
 Handles RID frames: checks for a duplicate alias and flags it if found.
 
void CanRxMessageHandler_amd_frame (can_msg_t *can_msg)
 Handles AMD (Alias Map Definition) CAN control frames.
 
void CanRxMessageHandler_ame_frame (can_msg_t *can_msg)
 Handles AME frames: responds with AMD frames for matching aliases.
 
void CanRxMessageHandler_amr_frame (can_msg_t *can_msg)
 Handles AMR (Alias Map Reset) CAN control frames.
 
void CanRxMessageHandler_error_info_report_frame (can_msg_t *can_msg)
 Handles Error Information Report frames: checks for a duplicate alias and flags it if found.
 

Detailed Description

Implementation of message handlers for CAN receive operations.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Handles multi-frame assembly (first/middle/last), single-frame messages, legacy SNIP, and all CAN control frames (CID, RID, AMD, AME, AMR). Also manages duplicate alias detection and listener alias table updates. Invoked by the CAN Rx state machine via dependency-injected callbacks.

Author
Jim Kueneman
Date
4 Mar 2026

Macro Definition Documentation

◆ CAN_RX_INPROCESS_TIMEOUT_TICKS

#define CAN_RX_INPROCESS_TIMEOUT_TICKS   30

Multi-frame assembly timeout in 100ms ticks (3 seconds).

Function Documentation

◆ CanRxMessageHandler_initialize()

void CanRxMessageHandler_initialize ( const interface_can_rx_message_handler_t * interface_can_frame_message_handler)

Stores the dependency-injection interface pointer.

Registers the dependency-injection interface for this module.

◆ CanRxMessageHandler_first_frame()

void CanRxMessageHandler_first_frame ( can_msg_t * can_msg,
uint8_t offset,
payload_type_enum data_type )

Handles the first frame of a multi-frame OpenLCB message.

Allocates an OpenLCB buffer, initializes it with source/dest/MTI from the CAN header, copies the first payload chunk, and adds it to the buffer list for continued assembly. Sends a rejection if a duplicate first frame is detected or if buffer allocation fails.

Parameters
can_msgReceived CAN frame.
offsetByte offset where OpenLCB data begins (2 if addressed, 0 if global).
data_typeBuffer type to allocate (BASIC, DATAGRAM, SNIP, STREAM).
Warning
NOT thread-safe.
See also
CanRxMessageHandler_middle_frame
CanRxMessageHandler_last_frame

◆ CanRxMessageHandler_middle_frame()

void CanRxMessageHandler_middle_frame ( can_msg_t * can_msg,
uint8_t offset )

Handles a middle frame of a multi-frame OpenLCB message.

Finds the in-progress message by source/dest/MTI and appends payload. Sends a rejection if no matching message is found.

Parameters
can_msgReceived CAN frame.
offsetByte offset where OpenLCB data begins.
Warning
NOT thread-safe.
See also
CanRxMessageHandler_first_frame
CanRxMessageHandler_last_frame

◆ CanRxMessageHandler_last_frame()

void CanRxMessageHandler_last_frame ( can_msg_t * can_msg,
uint8_t offset )

Handles the last frame of a multi-frame OpenLCB message.

Appends final payload, marks message complete, removes from buffer list, and pushes to the OpenLCB FIFO. Sends a rejection if no matching in-progress message is found.

Parameters
can_msgReceived CAN frame.
offsetByte offset where OpenLCB data begins.
Warning
NOT thread-safe.
See also
CanRxMessageHandler_first_frame
CanRxMessageHandler_middle_frame

◆ CanRxMessageHandler_single_frame()

void CanRxMessageHandler_single_frame ( can_msg_t * can_msg,
uint8_t offset,
payload_type_enum data_type )

Handles a complete single-frame OpenLCB message.

Allocates a buffer, copies all payload data, and pushes directly to the OpenLCB FIFO. Silently drops if allocation fails.

Parameters
can_msgReceived CAN frame.
offsetByte offset where OpenLCB data begins.
data_typeBuffer type to allocate (typically BASIC).
Warning
NOT thread-safe.
See also
OpenLcbBufferFifo_push

◆ CanRxMessageHandler_can_legacy_snip()

void CanRxMessageHandler_can_legacy_snip ( can_msg_t * can_msg,
uint8_t offset,
payload_type_enum data_type )

Handles legacy SNIP messages that lack standard multi-frame framing bits.

Handles legacy SNIP messages that lack standard framing bits.

Algorithm:

  1. Search for an in-progress SNIP message matching source/dest/MTI.
  2. If none found: delegate to CanRxMessageHandler_first_frame to allocate and start one.
  3. If found and NULL count < 6: delegate to CanRxMessageHandler_middle_frame to append data.
  4. If found and NULL count >= 6: delegate to CanRxMessageHandler_last_frame to complete it.
* @param can_msg    Received CAN frame containing SNIP data.
* @param offset     Byte offset where SNIP data begins.
* @param data_type  Must be SNIP.
* 
Warning
Only correct for MTI_SIMPLE_NODE_INFO_REPLY without framing bits.

◆ CanRxMessageHandler_stream_frame()

void CanRxMessageHandler_stream_frame ( can_msg_t * can_msg,
uint8_t offset,
payload_type_enum data_type )

Stream frame handler — reserved for future use, not yet implemented.

Handles stream protocol CAN frames (placeholder, not yet implemented).

◆ CanRxMessageHandler_cid_frame()

void CanRxMessageHandler_cid_frame ( can_msg_t * can_msg)

Handles CID frames per CanFrameTransferS §6.2.5.

Handles CID (Check ID) CAN control frames (CanFrameTransferS §6.2.5).

Per the standard (§6.2.5 Node ID Alias Collision Handling): "If the frame is a Check ID (CID) frame, send a Reserve ID (RID) frame in response." The correct defence is always RID, regardless of whether the node is Permitted or still Inhibited. This differs from non-CID frames (RID/AMD/AMR) which indicate an active alias collision and are handled by the internal _check_for_duplicate_alias() helper.

* @param can_msg  Received CID frame.
* 

◆ CanRxMessageHandler_rid_frame()

void CanRxMessageHandler_rid_frame ( can_msg_t * can_msg)

Handles RID frames: checks for a duplicate alias and flags it if found.

Handles RID (Reserve ID) CAN control frames.

◆ CanRxMessageHandler_amd_frame()

void CanRxMessageHandler_amd_frame ( can_msg_t * can_msg)

Handles AMD (Alias Map Definition) CAN control frames.

Performs two actions:

  1. Checks for a duplicate alias condition (our own alias conflict).
  2. If the listener alias feature is linked in, updates the listener table with the resolved alias and releases any held attach messages that were waiting on this Node ID.
* @param can_msg  Received AMD frame (6-byte NodeID in payload).
* 
Warning
NOT thread-safe.

◆ CanRxMessageHandler_ame_frame()

void CanRxMessageHandler_ame_frame ( can_msg_t * can_msg)

Handles AME frames: responds with AMD frames for matching aliases.

Handles AME (Alias Map Enquiry) CAN control frames.

Algorithm:

  1. Check for duplicate alias; return early if detected.
  2. If payload is non-empty: look up by Node ID, respond with one AMD if found.
  3. If payload is empty (global query): respond with AMD for every registered alias.
* @param can_msg Received AME frame.
* 
Warning
Silently drops responses if buffer allocation fails.

◆ CanRxMessageHandler_amr_frame()

void CanRxMessageHandler_amr_frame ( can_msg_t * can_msg)

Handles AMR (Alias Map Reset) CAN control frames.

Performs four actions when a remote node releases its alias:

  1. Checks for a duplicate alias condition (our own alias conflict).
  2. BufferList scrub: frees all messages from the released alias (partial assemblies will never complete, completed messages should not generate replies to a stale alias).
  3. FIFO scrub: marks queued incoming messages from the released alias as invalid so the pop-phase guard or TX guard will discard them, preventing late replies to the stale alias.
  4. Listener table cleanup: clears the released alias from the listener table so future TX-path lookups return alias == 0 (unresolved) instead of the stale alias. DI, no-op if not linked in.
* @param can_msg  Received AMR frame.
* 
Warning
NOT thread-safe.

◆ CanRxMessageHandler_error_info_report_frame()

void CanRxMessageHandler_error_info_report_frame ( can_msg_t * can_msg)

Handles Error Information Report frames: checks for a duplicate alias and flags it if found.

Handles Error Information Report CAN control frames.


Copyright (c) 2026 Jim Kueneman all rights reserved. See the License