+static void ax25_putchar(AX25Ctx *ctx, uint8_t c)
+{
+ if (c == HDLC_FLAG || c == HDLC_RESET
+ || c == AX25_ESC)
+ kfile_putc(AX25_ESC, ctx->ch);
+ ctx->crc_out = updcrc_ccitt(c, ctx->crc_out);
+ kfile_putc(c, ctx->ch);
+}
+
+static void ax25_sendCall(AX25Ctx *ctx, const AX25Call *addr)
+{
+ unsigned len = MIN(sizeof(addr->call), strlen(addr->call));
+
+ for (unsigned i = 0; i < len; i++)
+ {
+ uint8_t c = addr->call[i];
+ ASSERT(isalnum(c) || c == ' ');
+ c = toupper(c);
+ ax25_putchar(ctx, c << 1);
+ }
+
+ /* Fill with spaces the rest of the CALL if it's shorter */
+ if (len < sizeof(addr->call))
+ for (unsigned i = 0; i < sizeof(addr->call) - len; i++)
+ ax25_putchar(ctx, ' ' << 1);
+}
+
+/**
+ * Send an AX25 frame on the channel.
+ * \param ctx AX25 context to operate on.
+ * \param dst the destination callsign for the frame, \see AX25_CALL
+ * for a handy way to create a callsign on the fly.
+ * \param src the source callsign for the frame, \see AX25_CALL
+ * for a handy way to create a callsign on the fly.
+ * \param _buf payload buffer.
+ * \param len length of the payload.
+ */
+void ax25_send(AX25Ctx *ctx, const AX25Call *dst, const AX25Call *src, const void *_buf, size_t len)
+{
+ const uint8_t *buf = (const uint8_t *)_buf;
+
+ ctx->crc_out = CRC_CCITT_INIT_VAL;
+ kfile_putc(HDLC_FLAG, ctx->ch);
+
+ ax25_sendCall(ctx, dst);
+ ax25_putchar(ctx, dst->ssid << 1);
+
+ ax25_sendCall(ctx, src);
+ ax25_putchar(ctx, (src->ssid << 1) | 0x01);
+ ax25_putchar(ctx, AX25_CTRL_UI);
+ ax25_putchar(ctx, AX25_PID_NOLAYER3);
+
+ while (len--)
+ ax25_putchar(ctx, *buf++);
+
+ /*
+ * According to AX25 protocol,
+ * CRC is sent in reverse order!
+ */
+ uint8_t crcl = (ctx->crc_out & 0xff) ^ 0xff;
+ uint8_t crch = (ctx->crc_out >> 8) ^ 0xff;
+ ax25_putchar(ctx, crcl);
+ ax25_putchar(ctx, crch);
+
+ ASSERT(ctx->crc_out == AX25_CRC_CORRECT);
+
+ kfile_putc(HDLC_FLAG, ctx->ch);
+}
+
+
+/**
+ * Init the AX25 protocol decoder.
+ *
+ * \param ctx AX25 context to init.
+ * \param channel Used to gain access to the physical medium
+ * \param hook Callback function called when a message is received
+ */