/*
 * SPDX-License-Identifier: Apache-2.0
 * Copyright (c) 2026 Embedya.
 *
 * TraxProbe custom transport (reference skeleton). Licensed under the Apache
 * License, Version 2.0 (see LICENSE-Apache-2.0.txt). You may copy and modify
 * this file to support additional hardware or RTOS targets.
 *
 * This file depends on TraxProbe core headers, which remain licensed under the
 * TraxProbe Commercial License and are NOT relicensed by this notice.
 */

/**
******************************************************************************
* @file           : trax_transport_custom.c
* @date        	  : Jun 15, 2026
* @author         : bemre
* @version        : 1.0
*
* @brief          : Copy-paste skeleton for a custom TraxProbe transport
******************************************************************************
* @attention
* 	THIS IS A TEMPLATE, NOT A BUILD FILE. It ships with a ".example" extension
* 	so it is never auto-compiled (a stub that defined these functions for real
* 	would be a silent fake — TraxProbe deliberately wants an "undefined
* 	reference" link error instead). To use it:
* 	  1. Copy it into your application and rename to a ".c" (e.g.
* 	     App/Transport/trax_transport.c).
* 	  2. Set TRAX_CFG_TRANSPORT == TRAX_TRANSPORT_CUSTOM in trax_config.h.
* 	  3. Fill in each function body with your hardware driver and remove the
* 	     "#error" guard.
*
* 	The contract (prototypes + per-function @brief guidance) is in
* 	<trax_transport.h>. See .cursor/rules/trax-transport-transmission.mdc for the
* 	strict all-or-nothing write rule every transport must honour.
******************************************************************************
*/

#error "trax_transport_custom.c.example is a template. Copy, rename to .c, implement each function, then delete this #error."

#include <stddef.h>
#include <trax_transport.h>

/*=============================================================================
 ====================LOCAL MACRO FUNCTIONS=====================================
 ============================================================================*/

/*=============================================================================
 ====================LOCAL MACRO DEFINITIONS===================================
 ============================================================================*/

/*=============================================================================
 ====================GLOBAL VARIABLES==========================================
 ============================================================================*/

/*=============================================================================
 ====================LOCAL STUCTURES===========================================
 ============================================================================*/

/*=============================================================================
 ====================LOCAL VARIABLES===========================================
 ============================================================================*/

/*=============================================================================
 ====================LOCAL FUNCTION DECLARATION================================
 ============================================================================*/

/*=============================================================================
 ====================GLOBAL FUNCTION IMPLEMANTATION============================
 ============================================================================*/

/**
 * One-time arm of the transport binding (NOT the hardware itself — your
 * bsp_init() is expected to own clocks/GPIO/baud already). Return 0 on success,
 * non-zero to abort trax_init(). If there is nothing to arm, just `return 0;`.
 */
int trax_transport_init(void)
{
}

/**
 * Up-channel (Target -> Host): send trace data. STRICTLY ALL-OR-NOTHING —
 * commit every byte and return `size`, or accept nothing and return 0 (soft
 * backpressure; the core keeps the batch queued and retries next pass). A
 * partial return (0 < n < size) means a torn frame is on the wire and tears
 * the stream down fatally.
 *
 * Note: if you opt in to TRAX_CFG_TRANSPORT_TX_FREE (see below), the core
 * sizes each batch to your reported free space before calling this, so this
 * function should never actually have to return 0 — keep the check anyway as
 * the contract's safety net.
 */
size_t trax_transport_write(const void *p_src, size_t size)
{
}

/**
 * Down-channel (Host -> Target): read commands. NON-BLOCKING — copy up to
 * `size` bytes into p_dst and return immediately with whatever is available
 * (0 is valid).
 *
 * The core drains by calling this until it returns less than `size`, so a
 * short read is the "nothing left" signal and there is no separate has-data
 * hook. It runs on every trax_process() pass including idle ones, so keep it
 * cheap — and put any per-poll housekeeping the link needs (e.g. a
 * non-blocking accept() on a socket backend) right here.
 */
size_t trax_transport_read(void *p_dst, size_t size)
{
}

/**
 * Session restart: drop stale bytes still sitting in your software TX ring
 * (leave RX alone). REQUIRED. A blocking UART that has already handed
 * bytes to the peripheral cannot recall them — empty body is then correct.
 */
void trax_transport_clear_tx(void)
{
}

/*
 * That is the whole required set: init + write + read + clear_tx.
 *
 * Everything else is optional and opts in from trax_config.h by naming your
 * own function — nothing here has to exist for TraxProbe to stream:
 *
 *   #define TRAX_CFG_TRANSPORT_TX_FREE     my_tx_free      // recommended
 *   #define TRAX_CFG_TRANSPORT_BUF_SIZE    sizeof(my_ring) // diagnostics
 *   #define TRAX_CFG_TRANSPORT_BYTES_USED  my_tx_pending   // diagnostics
 *
 * TX_FREE is the one worth wiring up. It reports how many bytes a write()
 * is guaranteed to accept right now (free bytes in your TX ring / DMA queue);
 * the core caps each drain batch at it BEFORE collecting frames, so write()
 * never has to reject and a saturated link costs a short walk per pass
 * instead of a collect/reject/retry cycle over the whole backlog. Without it
 * the core assumes free space is unknown and keeps TRAX_CFG_TX_BATCH_MAX_BYTES
 * load-bearing — that cap must stay below your TX buffer's real capacity.
 *
 * Occupancy for the diagnostics gauge is derived as BUF_SIZE minus TX_FREE,
 * so defining BYTES_USED as well is only worth it when that subtraction does
 * not match your TX path.
 */

/*=============================================================================
 ====================LOCAL FUNCTION IMPLEMANTATION=============================
 ============================================================================*/
