HDLC Reference Library
This documentation package includes a full HDLC implementation in C in
src/hdlc/
, that we recommend using. src/linux_c_serial_demo
contains a complete demo application ready to communicate with any MyDefence
serial device.

To integrate the HDLC library into your own application, you need to implement an OS Abstraction Interface for your platform.
Application Interface
The application interface to send and receive HDLC frames is defined in the
header file src/hdlc/include/hdlc.h
.
Defines
-
HDLC_MAX_FRAME_LEN
Maximum length of HDLC data frame.
Enums
-
enum hdlc_result_t
Values:
-
enumerator HDLC_SUCCESS
-
enumerator HDLC_OS_ERROR
Call to hdlc_os_*() function in OS Abstraction Layer failed.
On some OS more information may be available, e.g. in errno.
-
enumerator HDLC_NOT_CONNECTED
HDLC layer is not connected, i.e. wait for hdlc_connected_cb().
-
enumerator HDLC_FRAME_TOO_LONG
Frame is too long.
-
enumerator HDLC_SUCCESS
-
enum hdlc_reset_cause_t
Values:
-
enumerator HDLC_RESET_CAUSE_APPLICATION_FREE
Reset by application.
-
enumerator HDLC_RESET_CAUSE_LINK_LOST
Reset by application due to loss of link.
-
enumerator HDLC_RESET_CAUSE_TIMEOUT_KEEP_ALIVE
Reset due to timeout during KEEP_ALIVE.
-
enumerator HDLC_RESET_CAUSE_TIMEOUT_RETRANSMIT
Reset due to timeout during retransmission.
-
enumerator HDLC_RESET_CAUSE_PEER_INITIATED
Reset due to peer initiated reset.
-
enumerator HDLC_RESET_CAUSE_NUMBER_OF_CAUSES
Not a real reset cause, but the number of reset causes Add new reset causes before this.
-
enumerator HDLC_RESET_CAUSE_APPLICATION_FREE
Functions
-
hdlc_result_t hdlc_send_frame(hdlc_data_t *h, const uint8_t *frame, uint32_t len)
Reliable transmission of one data frame.
This function is used to send one data frame. The frame is queued for transmission and the function returns immediately. When the frame has been successfully sent, the callback function hdlc_frame_sent_cb() is called with the same parameters. If frame transmission times out, hdlc_reset_cb() is called followed by hdlc_frame_sent_cb().
- Parameters:
h – HDLC instance data allocated by hdlc_init()
frame – Pointer to data to send. The pointer must be valid until hdlc_frame_sent_cb() is called
len – Length of data.
- Returns:
0 in case of success. Success means the data was correctly queued for transmission, not that it has been sent. See hdlc_result_t for error codes. In case of error, hdlc_frame_sent_cb() is not called.
-
void hdlc_frame_sent_cb(hdlc_data_t *h, const uint8_t *frame, uint32_t len)
Callback function called when a frame has been sent, or otherwise discarded.
- Parameters:
h – HDLC instance data allocated by hdlc_init()
frame – parameter from hdlc_send_frame()
len – parameter from hdlc_send_frame()
-
hdlc_result_t hdlc_send_frame_unacknowledged(hdlc_data_t *h, const uint8_t *frame, uint32_t len)
Unreliable transmission of one data frame.
This function is used to send one HDLC UI frame. The frame is attempted transmitted immediately. There is no way of knowing whether the frame has been delivered. frame may be freed immediately after return. hdlc_frame_sent_cb() is not called.
This frame may be dropped, delivered before, or delivered after unacknowledged frames already queued with hdlc_send_frame(). Data queued with hdlc_send_frame() or hdlc_send_frame_unacknowledged() after this frame, will always be delivered after this frame was delivered (if it is delivered).
- Parameters:
h – HDLC instance data allocated by hdlc_init()
frame – Pointer to data to send
len – Length of data.
- Returns:
0 in case of success. Success means the data was correctly queued for transmission, not that it has been sent. See hdlc_result_t for error codes.
-
void hdlc_recv_frame_cb(hdlc_data_t *h, uint8_t *frame, uint32_t len)
Callback function called when a frame (data or UI) has been received.
This function is called when a frame has been received. Frames are always delivered in the same order they are sent, with the exception that UI frames may overtake data frames.
- Parameters:
h – HDLC instance data allocated by hdlc_init()
frame – Pointer to a received HDLC frame. The pointer is invalid after this function returns.
len – Length of the frame
-
void hdlc_reset_cb(hdlc_data_t *h, hdlc_reset_cause_t cause)
This is called when HDLC sequence number are reset, which happens either.
In case of retransmission timeout (see HDLC_RETRANSMIT_CNT in hdlc_os.h)
If integration indicates loss of link or frees the HDLC instance
If HDLC SABM frame is received from peer
This is followed by cleanup of the current TX queue including calling hdlc_frame_sent_cb(). hdlc_send_frame() and hdcl_send_frame_unacknowledged() will fail until hdlc_connected_cb() is called.
- Parameters:
h – HDLC instance data allocated by hdlc_init()
cause – Reason for reset
-
void hdlc_connected_cb(hdlc_data_t *h)
This is called when HDLC is connected, i.e.
when the HDLC SABM frame is acknowledged by peer. All frames sent between system startup OR hdlc_reset_cb() and this are discarded.
- Parameters:
h – HDLC instance data allocated by hdlc_init()
Variables
-
struct hdlc_stat_t hdlc_stat
Various statistics about the HDLC layer, that may be useful for diagnosing link performance.
-
struct hdlc_stat_t
- #include <hdlc.h>
Public Members
-
uint32_t rx
Data frames received (not including retransmissions)
-
uint32_t ui_rx
UI frames received (not including retransmissions)
-
uint32_t rx_retrans
Out-of-sequence rx frames.
-
uint32_t rx_err
Failure to decode HDLC frame.
-
uint32_t rx_ack
Ack frames received.
-
uint32_t rx_nack
Nack frames received.
-
uint32_t tx
Data frames transmitted (not including retransmissions)
-
uint32_t ui_tx
UI frames transmitted (not including retransmissions)
-
uint32_t tx_err
Failure of hdlc_os_tx()
-
uint32_t tx_retrans
Data frames retransmitted (including retransmission frames)
-
uint32_t tx_ack
Ack frames transmitted.
-
uint32_t tx_nack
Nack frames transmitted.
-
uint32_t tx_keep_alive
Number of keep alive frames transmitted (not including retransmissions)
-
uint32_t reset
Number of times sequence number handling has been reset.
-
uint32_t rx
OS Abstraction Interface
The HDLC implementation is attempted to be generic, and requires integration
into the OS as specified in src/hdlc/include/hdlc_os.h
.
Some reference integrations are available in src/hdlc/ports/
.
Defines
-
HDLC_RETRANSMIT_CNT
Number of retransmissions to attempt before resetting the link.
Thus the timeout is this value times the hdlc_os_start_timer() time.
-
HDLC_KEEP_ALIVE_CNT
Number of timeouts with no data transmission before sending keep-alive packet.
Thus detection of broken link takes
(HDLC_KEEP_ALIVE_CNT + HDLC_RETRANSMIT_CNT)
* hdlc_os_start_timer() time
-
log_trace(...)
Define log_ macros to enable logging.
The integration may omit this. Default no logging is enabled.
-
log_debug(...)
-
log_info(...)
-
log_warn(...)
-
log_error(...)
-
log_fatal(...)
Functions
-
hdlc_data_t *hdlc_init(void *user_data)
Called by integration to initialize an hdlc instance.
May be called multiple times if more than one HDLC device is connected.
- Parameters:
user_data – pointer to user data. The pointer will be copied to hdlc_data_t.
-
void hdlc_free(hdlc_data_t *hdlc)
Called by integration to free resources allocated by hdlc_init().
The integration is responsible for cleanup of anything in hdlc->user_data. After call to this, no other
hdlc_*()
/hdlc_os_*()
functions may be called andhdlc
must not be accessed. Note: This function uses varioushdlc_os_*()
callbacks, so do not free any instance resources until AFTER this call.
-
int hdlc_os_tx(hdlc_data_t *hdlc, const uint8_t *buf, uint32_t count)
Called by hdlc to transmit raw serial data.
This function should be implemented by the integration.
buf
pointer is valid until function returns. The function is expected to send the entirebuf
or nothing, hdlc does not explicitly handle partial writes, but the underlying error handling will recover from it.Beware, that if this blocks, that will also cause blocking of receive handling.
- Parameters:
buf – data
count – length of data
- Returns:
< 0 in case of error, otherwise number of bytes sent (== count).
-
void hdlc_os_rx(hdlc_data_t *hdlc, const uint8_t *buf, uint32_t count)
Called by integration when new raw serial data is received.
This function called from the integration. data pointed to by
buf
may be freed or overwritten after the function call returns.- Parameters:
buf – data
count – length of data
-
void hdlc_os_start_timer(hdlc_data_t *hdlc)
Called by hdlc to (re)start retransmission timer.
Integration must provide a single-shot timer for retransmission handling. This function is called after transmission of the first outstanding packet. Integration must select an appropriate timeout value for the time it is expected to receive an ACK, i.e. the round trip time of the largest frame plus ack.
This function will also be called to restart timer when an ACK is received, and there are still outstanding frames.
-
void hdlc_os_stop_timer(hdlc_data_t *hdlc)
Called by hdlc to stop retransmission timer started by hdlc_os_start_timer().
-
void hdlc_os_timeout(hdlc_data_t *hdlc)
Called by integration when retransmission timer expires.
Note, that the function will call hdlc_os_exit_critical_section(), hdlc_os_exit_critical_section(), hdlc_os_start_timer() and hdlc_os_tx().
-
void hdlc_os_link_lost(hdlc_data_t *hdlc)
Called by integration to indicate link loss.
This will reset HDLC. hdlc_reset_cb() and later hdlc_connected_cb() will be called. The integration may omit this.
-
void hdlc_os_enter_critical_section(hdlc_data_t *hdlc)
Called by hdlc lock a mutex.
If integration does not use multi-threading it may provide empty functions.
-
void hdlc_os_exit_critical_section(hdlc_data_t *hdlc)
Called by hdlc unlock a mutex.
If integration does not use multi-threading it may provide empty functions
-
struct hdlc_data_t
- #include <hdlc_os.h>
HDLC instance data, allocated by hdlc_init().
The actual struct allocated by HDLC is larger than this and contains internal data.
Public Members
-
void *user_data
The user data field is a pointer the application may use to refer to any data it needs.
The integration may set it to anything it wishes including NULL. It will not be touched by hdlc.
-
unsigned int hdlc_tx_queue_size
Number of frames in the TX queue.
Can be used to throttle the sender. Alternatively a sender may use hdlc_frame_sent_cb() for throttling.
-
void *user_data