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

Message handlers for processing received CAN frames into OpenLCB messages. More...

Go to the source code of this file.

Data Structures

struct  interface_can_rx_message_handler_t
 Dependency-injection interface for the CAN receive message handlers. More...
 

Functions

void CanRxMessageHandler_initialize (const interface_can_rx_message_handler_t *interface_can_frame_message_handler)
 Registers the dependency-injection interface for this module.
 
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 framing bits.
 
void CanRxMessageHandler_stream_frame (can_msg_t *can_msg, uint8_t offset, payload_type_enum data_type)
 Handles stream protocol CAN frames (placeholder, not yet implemented).
 
void CanRxMessageHandler_rid_frame (can_msg_t *can_msg)
 Handles RID (Reserve ID) CAN control frames.
 
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 (Alias Map Enquiry) CAN control frames.
 
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 CAN control frames.
 
void CanRxMessageHandler_cid_frame (can_msg_t *can_msg)
 Handles CID (Check ID) CAN control frames (CanFrameTransferS §6.2.5).
 

Detailed Description

Message handlers for processing received CAN frames into OpenLCB messages.

Handles multi-frame assembly, legacy SNIP, and all CAN control frames (CID, RID, AMD, AME, AMR, error reports). Invoked by the CAN Rx state machine.

Author
Jim Kueneman
Date
4 Mar 2026

Function Documentation

◆ CanRxMessageHandler_initialize()

void CanRxMessageHandler_initialize ( const interface_can_rx_message_handler_t * interface_can_frame_message_handler)
extern

Registers the dependency-injection interface for this module.

Parameters
interface_can_frame_message_handlerPointer to a populated interface_can_rx_message_handler_t. Must remain valid for the lifetime of the application. All function pointers must be non-NULL.
Warning
NOT thread-safe - call during single-threaded initialization only.
Must be called before any CAN frames are processed.
See also
CanRxStatemachine_initialize

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 )
extern

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 )
extern

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 )
extern

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 )
extern

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 )
extern

Handles legacy SNIP messages that lack standard framing bits.

Accumulates frames and counts NULL terminators to detect completion. A complete SNIP message contains exactly 6 NULLs.

Parameters
can_msgReceived CAN frame.
offsetByte offset where SNIP data begins.
data_typeMust be SNIP.
Warning
NOT thread-safe.
Only correct for MTI_SIMPLE_NODE_INFO_REPLY without framing bits.
See also
CanRxMessageHandler_first_frame - modern multi-frame handling

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 )
extern

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

Parameters
can_msgReceived CAN frame.
offsetByte offset where stream data begins.
data_typeMust be STREAM.
Warning
Empty body - reserved for future use.

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

◆ CanRxMessageHandler_rid_frame()

void CanRxMessageHandler_rid_frame ( can_msg_t * can_msg)
extern

Handles RID (Reserve ID) CAN control frames.

Checks for a duplicate alias condition and flags it if found.

Parameters
can_msgReceived RID frame.
Warning
NOT thread-safe.

Handles RID (Reserve ID) CAN control frames.

◆ CanRxMessageHandler_amd_frame()

void CanRxMessageHandler_amd_frame ( can_msg_t * can_msg)
extern

Handles AMD (Alias Map Definition) CAN control frames.

Checks for a duplicate alias condition and flags it if found.

Parameters
can_msgReceived AMD frame (6-byte NodeID in payload).
Warning
NOT thread-safe.

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)
extern

Handles AME (Alias Map Enquiry) CAN control frames.

Responds with AMD frames for all our aliases (global query) or for a specific NodeID (targeted query if 6-byte payload present).

Parameters
can_msgReceived AME frame.
Warning
Silently drops responses if buffer allocation fails.
NOT thread-safe.

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)
extern

Handles AMR (Alias Map Reset) CAN control frames.

Checks for a duplicate alias condition and flags it if found.

Parameters
can_msgReceived AMR frame.
Warning
NOT thread-safe.

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)
extern

Handles Error Information Report CAN control frames.

Checks for a duplicate alias condition and flags it if found.

Parameters
can_msgReceived error report frame.
Warning
NOT thread-safe.

Handles Error Information Report CAN control frames.

◆ CanRxMessageHandler_cid_frame()

void CanRxMessageHandler_cid_frame ( can_msg_t * can_msg)
extern

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." This applies regardless of whether the node is Permitted or still Inhibited. CID is a probe during alias reservation — the correct defence is always RID.

Parameters
can_msgReceived CID frame.
Warning
Silently drops the reply if buffer allocation fails.
NOT thread-safe.
See also
CanRxMessageHandler_rid_frame

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.
* 

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