Files
templates/c/set-protocol/src/pcan_link.c

60 lines
1.6 KiB
C

#include "pcan_link.h"
bool pcan_link_init(pcan_link_t *link, const pcan_io_t *io,
pcan_frame_cb_t on_frame, void *user)
{
if ((link == NULL) || (io == NULL) || (io->write == NULL)) {
return false;
}
link->io = *io;
link->on_frame = on_frame;
link->user = user;
link->tx_seq = 0U;
link->tx.tx_frames = 0U;
link->tx.tx_dropped = 0U;
pcan_parser_init(&link->parser);
return true;
}
bool pcan_link_can_send(const pcan_link_t *link)
{
if (link->io.tx_space == NULL) {
return true;
}
return link->io.tx_space(link->io.ctx) >= PCAN_FRAME_MAX;
}
bool pcan_link_send_raw(pcan_link_t *link, const pcan_frame_t *frame)
{
uint8_t raw[PCAN_FRAME_MAX];
size_t n = pcan_frame_encode(frame, raw, sizeof raw);
if (n == 0U) {
link->tx.tx_dropped++;
return false;
}
if (link->io.write(link->io.ctx, raw, n) != n) {
link->tx.tx_dropped++;
return false;
}
link->tx.tx_frames++;
return true;
}
bool pcan_link_send(pcan_link_t *link, pcan_frame_t *frame)
{
frame->seq = link->tx_seq;
if (!pcan_link_send_raw(link, frame)) {
return false;
}
/* SEQ двигаем только на успешно отданном кадре: иначе приёмник
засчитает потерю там, где кадра просто не было. */
link->tx_seq++;
return true;
}
size_t pcan_link_feed(pcan_link_t *link, const uint8_t *data, size_t len)
{
return pcan_parser_feed(&link->parser, data, len, link->on_frame, link->user);
}