#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); }