#ifndef CSPCL_H
#define CSPCL_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifndef FREERTOS
#include <pthread.h>
#include <time.h>
#else
#include <FreeRTOS.h>
#include <semphr.h>
#endif
#include <csp/csp.h>
#include <csp/csp_types.h>
#include <csp/csp_rtable.h>
#include <csp/interfaces/csp_if_zmqhub.h>
#ifdef CSP_HAVE_LIBSOCKETCAN
#include <csp/drivers/can_socketcan.h>
#include <csp/interfaces/csp_if_can.h>
#endif
#define CSP_IFACE_PARAM_MAX 64
#ifdef __cplusplus
extern "C" {
#endif
#define CSPCL_PORT_BP 10
#define CSPCL_CSP_MTU 256
#define CSPCL_SFP_HEADER_SIZE 8
#define CSPCL_MAX_PAYLOAD (CSPCL_CSP_MTU - CSPCL_SFP_HEADER_SIZE)
#define CSPCL_MAX_BUNDLE_SIZE 65535
#define CSPCL_CONN_POOL_SIZE 16
#define CSPCL_CSP_TIMEOUT_MS 1000
#define CSPCL_SFP_TIMEOUT_MS 5000
typedef enum {
CSPCL_OK = 0,
CSPCL_ERR_INVALID_PARAM,
CSPCL_ERR_NO_MEMORY,
CSPCL_ERR_BUNDLE_TOO_LARGE,
CSPCL_ERR_CSP_SEND,
CSPCL_ERR_CSP_RECV,
CSPCL_ERR_TIMEOUT,
CSPCL_ERR_SFP,
CSPCL_ERR_NOT_INITIALIZED,
CSPCL_ERR_CONNECTION,
CSPCL_ERR_CSPINIT,
CSPCL_ERR_CSP_STACK_INIT,
CSPCL_ERR_CSP_ZMQHUB_INIT,
CSPCL_ERR_CSP_CAN_INIT,
CSPCL_ERR_CSP_CAN_NOT_SUPPORTED,
CSPCL_ERR_CSP_ROUTER,
CSPCL_ERR_POOL_FULL
} cspcl_error_t;
enum csp_iface_type {
CSP_IFACE_ZMQHUB,
CSP_IFACE_CAN,
CSP_IFACE_LOOPBACK
};
typedef struct {
uint32_t hits;
uint32_t misses;
uint32_t evictions;
uint32_t connect_failures;
uint32_t invalidations;
} cspcl_conn_pool_stats_t;
typedef struct {
bool used;
uint8_t dest_addr;
uint8_t dest_port;
csp_conn_t *conn;
uint32_t last_used;
#ifndef FREERTOS
time_t connected_at;
#endif
} cspcl_conn_pool_entry_t;
typedef struct {
bool initialized;
#ifndef FREERTOS
pthread_mutex_t lock;
#else
SemaphoreHandle_t lock;
#endif
cspcl_conn_pool_entry_t entries[CSPCL_CONN_POOL_SIZE];
uint32_t tick;
uint32_t max_conn_age_ms;
cspcl_conn_pool_stats_t stats;
} cspcl_conn_pool_t;
typedef struct {
bool initialized;
uint8_t local_addr;
void *
rx_socket;
uint8_t csp_port;
enum csp_iface_type iface_type;
char zmqhub_addr[CSP_IFACE_PARAM_MAX];
char can_iface[CSP_IFACE_PARAM_MAX];
cspcl_conn_pool_t conn_pool;
csp_iface_t *active_iface;
} cspcl_t;
cspcl_error_t cspcl_init(cspcl_t *cspcl);
void cspcl_cleanup(cspcl_t *cspcl);
cspcl_error_t cspcl_conn_pool_init(cspcl_conn_pool_t *pool);
void cspcl_conn_pool_cleanup(cspcl_conn_pool_t *pool);
void cspcl_conn_pool_get_stats(const cspcl_conn_pool_t *pool,
cspcl_conn_pool_stats_t *stats);
cspcl_error_t cspcl_send_bundle(cspcl_t *cspcl, const uint8_t *bundle,
size_t len, uint8_t dest_addr,
uint8_t dest_port);
cspcl_error_t cspcl_recv_bundle(cspcl_t *cspcl, uint8_t *bundle, size_t *len,
uint8_t *src_addr, uint8_t *src_port,
uint32_t timeout_ms);
cspcl_error_t cspcl_open_rx_socket(cspcl_t *cspcl);
void cspcl_close_rx_socket(cspcl_t *cspcl);
uint8_t cspcl_endpoint_to_addr(const char *endpoint_id);
cspcl_error_t cspcl_addr_to_endpoint(uint8_t addr, char *endpoint, size_t len);
const char *cspcl_strerror(cspcl_error_t err);
#ifdef __cplusplus
}
#endif
#endif