Knowledge Base

Everything you need to know and understand to develop V2X applications.

denm-generator.py
msg = self.generate_denm()
future = self.send_request(msg)
future.add_done_callback(self.request_completed)

Radio API Developer Guide

The Radio API provides a modern C interface for direct access to the cube:radio subsystem. It allows developers to initialize the radio, configure parameters, and transmit or receive V2X frames over both ITS-G5 / DSRC and C-V2X / LTE-V2X technologies.


1. Overview

The API abstracts the underlying hardware (Qualcomm V2X 200 Chipset, prev. Autotalks SECTON/PLUTON2) into a unified C interface that works for both technologies. All cube-radio-* tools (such as cube-radio-transmit, cube-radio-receive, and cube-radio-pcap) are built on top of this API.

With it, developers can:

✅ Initialize and attach to a radio
✅ Configure channel, power, and modulation settings
✅ Transmit and receive PDUs (frames)
✅ Query link status and CBR (Channel Busy Ratio)

The Cube Radio API unifies DSRC and C-V2X into a single C interface — ideal for direct integration, testing, and V2X application development.


2. Core API Structures

CubeRadioTechnology

tech.h

The CubeRadioTechnology enumeration identifies which V2X communication technology is currently active. It distinguishes between ITS-G5 (DSRC) and C-V2X (LTE-V2X) — the two physical layers supported by the radio. This value determines which configuration and PDU structures are used, ensuring proper message formatting and protocol handling.

typedef enum {
CUBE_RADIO_UNDEFINED = 0,
CUBE_RADIO_ITS_G5 = 1,
CUBE_RADIO_CV2X = 2,
} CubeRadioTechnology;

Applications typically set this field when preparing a CubeRadioConfiguration before calling cube_radio_configure(). It also appears in status queries to indicate the currently attached radio technology.

struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_ITS_G5,
.g5 = { .channel = CUBE_RADIO_G5_CCH },
};
cube_radio_configure(radio, &cfg);

ITS-G5 Configuration

configuration.h

The ITS-G5 configuration defines the operating channel and parameters used when the radio is running in ETSI ITS-G5 mode.

enum CubeRadioG5Channel {
CUBE_RADIO_G5_CCH = 0, /* 5.90 GHz */
CUBE_RADIO_G5_SCH1 = 1, /* 5.88 GHz */
CUBE_RADIO_G5_SCH2 = 2, /* 5.89 GHz */
};
struct CubeRadioG5Configuration {
enum CubeRadioG5Channel channel;
};

The channel parameter determines the center frequency, permitted power limits, and default data rate according to the selected regulatory and safety band definitions according to ETSI EN 302 663.

Example — selecting the 5.88 GHz service channel:

struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_ITS_G5,
.g5 = { .channel = CUBE_RADIO_G5_SCH1 },
};
cube_radio_configure(radio, &cfg);

Developers can switch channels to evaluate performance or interoperability across different ITS-G5 frequency allocations.

C-V2X Configuration

configuration.h

The C-V2X configuration defines the parameters for operation in LTE-V2X or 5G NR V2X mode. It specifies both the radio access technology (RAT) and the message family used to interpret and format transmitted frames. The message family affects the compliance of PC5 sidelink messages according to standards required in certain regions, such as ETSI ITS, ISO, or IEEE 1609.

enum CubeRadioCv2xAccessTechnology {
CUBE_RADIO_CV2X_RAT_UNSPECIFIED = 0,
CUBE_RADIO_CV2X_RAT_LTE = 1,
CUBE_RADIO_CV2X_RAT_5GNR = 2,
};
enum CubeRadioCv2xMessageFamily {
CUBE_RADIO_CV2X_MESSAGE_FAMILY_NONE = 0,
CUBE_RADIO_CV2X_MESSAGE_FAMILY_IEEE1609 = 1,
CUBE_RADIO_CV2X_MESSAGE_FAMILY_ISO = 2,
CUBE_RADIO_CV2X_MESSAGE_FAMILY_ETSI_ITS = 3,
CUBE_RADIO_CV2X_MESSAGE_FAMILY_CCSA = 4,
};
struct CubeRadioCv2xConfiguration {
enum CubeRadioCv2xAccessTechnology rat;
enum CubeRadioCv2xMessageFamily family;
};

Example — configuring LTE-V2X with the ETSI ITS message family:

struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_CV2X,
.cv2x = {
.rat = CUBE_RADIO_CV2X_RAT_LTE,
.family = CUBE_RADIO_CV2X_MESSAGE_FAMILY_ETSI_ITS,
},
};
cube_radio_configure(radio, &cfg);

This example activates the LTE PC5 radio stack with ETSI ITS-compatible message framing — suitable for cooperative ITS and CAM/DENM transmission.

Note on C-V2X Configuration

The C-V2X RRC (Radio Resource Control) defines the actual physical and link-layer parameters. You cannot change these values at runtime via this API. See /system/radio/#3-c-v2-x-configuration for details on how to modify RRC configuration files.


General Configuration

The general radio configuration structure is used to initialize and switch between the supported V2X technologies — ITS-G5 and C-V2X. It provides a single entry point for defining all technology-specific parameters before activating or reconfiguring the radio.

struct CubeRadioConfiguration {
CubeRadioTechnology tech;
union {
struct CubeRadioG5Configuration g5;
struct CubeRadioCv2xConfiguration cv2x;
};
};

This structure is passed to cube_radio_configure() when setting up the radio.

  • ´tech´ determines which radio technology is active.
  • Depending on the selected ´tech´, either the g5 or cv2x configuration block must be filled.
  • Once configured, the parameters are applied using cube_radio_configure().

Example — configuring ITS-G5 operation on the 5.90 GHz control channel:

struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_ITS_G5,
.g5 = { .channel = CUBE_RADIO_G5_CCH },
};
cube_radio_configure(radio, &cfg);

Example — using C-V2X LTE operation with ETSI ITS message family:

struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_CV2X,
.cv2x = {
.rat = CUBE_RADIO_CV2X_RAT_LTE,
.family = CUBE_RADIO_CV2X_MESSAGE_FAMILY_ETSI_ITS,
},
};
cube_radio_configure(radio, &cfg);

Power Level

power.h

The power level structure defines the transmit power used for sending V2X frames. It uses 1/8 dBm resolution to allow fine-grained adjustment of output levels, which can be important when testing link quality, range, or regulatory limits.

struct CubeRadioPowerLevel {
enum CubeRadioPowerLevelType type; /* usually CUBE_RADIO_POWERLEVEL_DBM8 */
union {
int16_t dbm8; /* 1/8 dBm resolution */
};
};

For example, to configure a transmit power of 23 dBm:

struct CubeRadioPowerLevel level = {
.type = CUBE_RADIO_POWERLEVEL_DBM8,
.dbm8 = 23 * 8
};

Power level settings are applied automatically when a frame is transmitted through the corresponding PDU (CubeRadioG5Pdu or CubeRadioCv2xPdu). They can also be used to compare received frame power levels (RSSI) for link characterization or antenna evaluation.


ITS-G5 PDU

pdu.h

The ITS-G5 PDU (Protocol Data Unit) defines the metadata and transmission parameters for an ITS-G5 frame. Each PDU describes how a payload is sent — including source and destination MAC addresses, transmit power, data rate (MCS), and QoS priority.

struct CubeRadioG5Pdu {
CubeRadioG5MacAddr src; // Source MAC address
CubeRadioG5MacAddr dest; // Destination MAC address
struct CubeRadioPowerLevel power_level; // TX power in 1/8 dBm
struct CubeRadioG5DataRate data_rate; // PHY data rate / MCS
uint8_t user_priority; // IEEE 802.11p user priority (0–7)
};

The data rate field uses the CubeRadioG5DataRate structure to select a predefined modulation and coding scheme (MCS) index. Alternatively, you can select a MCS by requesting a particular data rate given in 500 kbps steps.

enum CubeRadioG5DataRateType {
CUBE_RADIO_G5_DATARATE_UNSPECIFIED = 0,
CUBE_RADIO_G5_DATARATE_MCS_INDEX = 1,
CUBE_RADIO_G5_DATARATE_500KBPS = 2,
};
enum CubeRadioG5McsIndex {
CUBE_RADIO_MCS_BPSK_12 = 0, // ~3 Mbps
CUBE_RADIO_MCS_BPSK_34 = 1, // ~4.5 Mbps
CUBE_RADIO_MCS_QPSK_12 = 2, // ~6 Mbps
CUBE_RADIO_MCS_QPSK_34 = 3, // ~9 Mbps
CUBE_RADIO_MCS_16QAM_12 = 4, // ~12 Mbps
CUBE_RADIO_MCS_16QAM_34 = 5, // ~18 Mbps
CUBE_RADIO_MCS_64QAM_23 = 6, // ~24 Mbps
CUBE_RADIO_MCS_64QAM_34 = 7, // ~27 Mbps
};
struct CubeRadioG5DataRate {
enum CubeRadioG5DataRateType type;
union {
enum CubeRadioG5McsIndex mcs_index;
unsigned steps_of_500kbps; // e.g., 12 = 6 Mbps
};
};

Example — Transmitting a Frame with QPSK ½ at 20 dBm:

struct CubeRadioG5Pdu pdu = {0};
memset(&pdu, 0, sizeof(pdu));
// Broadcast frame
memset(pdu.dest, 0xFF, sizeof(pdu.dest));
// Power and data rate
pdu.power_level.type = CUBE_RADIO_POWERLEVEL_DBM8;
pdu.power_level.dbm8 = 20 * 8; // 20 dBm
pdu.data_rate.type = CUBE_RADIO_G5_DATARATE_MCS_INDEX;
pdu.data_rate.mcs_index = CUBE_RADIO_MCS_QPSK_12; // 6 Mbps
pdu.user_priority = 3; // medium-priority traffic
// Transmit with payload
const char payload[] = "Hello ITS-G5 World!";
cube_radio_transmit_g5(radio, &pdu, payload, sizeof(payload));

When receiving, the PDU metadata (RSSI, MCS, etc.) is populated automatically by the radio driver and returned by cube_radio_receive_g5(). CubeRadioG5Pdu encapsulates all relevant metadata for an ITS-G5 frame, including addressing, transmit power, data rate, and priority. It allows developers to precisely control or inspect radio-level transmission parameters when sending or receiving V2X messages.


C-V2X PDU

pdu.h

The C-V2X PDU (Protocol Data Unit) defines the metadata associated with a sidelink frame in LTE-V2X or 5G NR V2X mode. It provides identifiers for source and destination Layer-2 IDs, transmit power, and priority, enabling structured and standards-compliant message exchange between nearby vehicles or infrastructure.

struct CubeRadioCv2xPdu {
CubeRadioCv2xL2Id src; // Source Layer-2 ID (24-bit)
CubeRadioCv2xL2Id dest; // Destination Layer-2 ID (24-bit)
struct CubeRadioPowerLevel power_level; // TX power (1/8 dBm)
uint8_t pppp; // Priority and packet properties
};

Each Layer-2 ID is represented as a 24-bit identifier (uint8_t[3]). The pppp field corresponds to the 4-bit priority and packet control field defined in the 3GPP sidelink PC5 specification.

Example — Transmitting a C-V2X Frame at 23 dBm:

struct CubeRadioCv2xPdu pdu = {0};
memset(&pdu, 0, sizeof(pdu));
// Broadcast destination (0xFFFFFF)
pdu.dest[0] = 0xFF;
pdu.dest[1] = 0xFF;
pdu.dest[2] = 0xFF;
// Transmit power
pdu.power_level.type = CUBE_RADIO_POWERLEVEL_DBM8;
pdu.power_level.dbm8 = 23 * 8; // 23 dBm
// Priority (0–15)
pdu.pppp = 4;
// Payload
const char payload[] = "Hello C-V2X World!";
cube_radio_transmit_cv2x(radio, &pdu, payload, sizeof(payload));

When receiving a frame, the metadata (including the received power and source Layer-2 ID) is filled automatically by the radio driver and returned by cube_radio_receive_cv2x().


3. API Usage Workflow

Step 1 – Attach to the Radio

struct CubeRadio* radio = cube_radio_attach("dsrc");

This opens a connection to the radio daemon (DSRC or C-V2X).

Step 2 – Configure

struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_ITS_G5,
.g5 = {
.channel = CUBE_RADIO_G5_CCH
},
};
cube_radio_configure(radio, &cfg);

Step 3 – Transmit a Frame

uint8_t payload[] = "Hello ITS-G5";
struct CubeRadioG5Pdu pdu = { 0 };
pdu.data_rate.type = CUBE_RADIO_G5_DATARATE_MCS_INDEX;
pdu.data_rate.mcs_index = CUBE_RADIO_MCS_11P_6MBIT;
cube_radio_transmit_g5(radio, &pdu, payload, sizeof(payload));

Step 4 – Receive a Frame

uint8_t rx_buf[1500] = {0};
size_t rx_len = sizeof(rx_buf);
struct CubeRadioG5Pdu rx_pdu;
cube_radio_ec rc = cube_radio_receive_g5(radio, &rx_pdu, rx_buf, &rx_len);
if (rc == CUBE_RADIO_SUCCESS) {
printf("Received %zu bytes from %02X:%02X:%02X:%02X:%02X:%02X\n",
rx_len,
rx_pdu.src[0], rx_pdu.src[1], rx_pdu.src[2],
rx_pdu.src[3], rx_pdu.src[4], rx_pdu.src[5]);
// Convert RSSI from 1/8 dBm units
double rssi_dbm = rx_pdu.power_level.dbm8 / 8.0;
printf("RSSI: %.1f dBm\n", rssi_dbm);
printf("Payload (ASCII): %.*s\n", (int)rx_len, rx_buf);
} else {
fprintf(stderr, "Failed to receive frame (error %d)\n", rc);
}

Step 5 – Fetch CBR

The Channel Busy Ratio (CBR) indicates the percentage of time the radio channel is occupied by transmissions. It is defined by ETSI for congestion control and performance monitoring ITS-G5.

struct CubeRadioCbrSample cbr;
cube_radio_fetch_cbr(radio, &cbr);
printf("Channel Busy Ratio: %.2f%%\n", cbr.num * 100.0 / cbr.den);

Step 6 – Detach

cube_radio_detach(radio);

Complete Example

The following example demonstrates the complete workflow: attach → configure → transmit → receive → monitor → detach.

#include <stdio.h>
#include <string.h>
#include <cube/radio/radio.h>
#include <cube/radio/configuration.h>
#include <cube/radio/pdu.h>
#include <cube/radio/error.h>
int main(void) {
cube_radio_ec rc;
// Step 1: Attach to the radio
struct CubeRadio* radio = cube_radio_attach("dsrc");
if (!radio) {
fprintf(stderr, "Failed to attach to radio\n");
return 1;
}
// Step 2: Configure for ITS-G5 operation
struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_ITS_G5,
.g5 = {
.channel = CUBE_RADIO_G5_CCH
},
};
rc = cube_radio_configure(radio, &cfg);
if (rc != CUBE_RADIO_SUCCESS) {
fprintf(stderr, "Configuration failed: %d\n", rc);
cube_radio_detach(radio);
return 1;
}
// Step 3: Transmit a frame
uint8_t payload[] = "Hello ITS-G5 World!";
struct CubeRadioG5Pdu tx_pdu = {0};
memset(tx_pdu.dest, 0xFF, sizeof(tx_pdu.dest)); // Broadcast
tx_pdu.power_level.type = CUBE_RADIO_POWERLEVEL_DBM8;
tx_pdu.power_level.dbm8 = 20 * 8; // 20 dBm
tx_pdu.data_rate.type = CUBE_RADIO_G5_DATARATE_MCS_INDEX;
tx_pdu.data_rate.mcs_index = CUBE_RADIO_MCS_QPSK_12; // 6 Mbps
tx_pdu.user_priority = 3;
rc = cube_radio_transmit_g5(radio, &tx_pdu, payload, sizeof(payload));
if (rc != CUBE_RADIO_SUCCESS) {
fprintf(stderr, "Transmission failed: %d\n", rc);
} else {
printf("Transmitted %zu bytes\n", sizeof(payload));
}
// Step 4: Receive a frame
uint8_t rx_buf[1500] = {0};
size_t rx_len = sizeof(rx_buf);
struct CubeRadioG5Pdu rx_pdu;
rc = cube_radio_receive_g5(radio, &rx_pdu, rx_buf, &rx_len);
if (rc == CUBE_RADIO_SUCCESS) {
printf("Received %zu bytes from %02X:%02X:%02X:%02X:%02X:%02X\n",
rx_len,
rx_pdu.src[0], rx_pdu.src[1], rx_pdu.src[2],
rx_pdu.src[3], rx_pdu.src[4], rx_pdu.src[5]);
double rssi_dbm = rx_pdu.power_level.dbm8 / 8.0;
printf("RSSI: %.1f dBm\n", rssi_dbm);
printf("Payload: %.*s\n", (int)rx_len, rx_buf);
}
// Step 5: Fetch CBR
struct CubeRadioCbrSample cbr;
rc = cube_radio_fetch_cbr(radio, &cbr);
if (rc == CUBE_RADIO_SUCCESS) {
printf("Channel Busy Ratio: %.2f%%\n", cbr.num * 100.0 / cbr.den);
}
// Step 6: Detach
cube_radio_detach(radio);
printf("Radio detached\n");
return 0;
}

Compile it using this CMakeLists.txt alongside the main.cpp:

cmake_minimum_required(VERSION 3.16)
project(main)
find_package(CubeRadio REQUIRED)
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} PUBLIC CubeRadio::user)
cube:~/radio-example$ ls
CMakeLists.txt main.c
cube:~/radio-example$ mkdir build && cd build
cube:~/radio-example/build$ cmake ..
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/cube/radio-example/build
cube:~/radio-example/build$ make
[ 50%] Building C object CMakeFiles/main.dir/main.c.o
[100%] Linking C executable main
[100%] Built target main
cube:~/radio-example/build$ ./main
Transmitted 20 bytes
Radio detached

4. Example: C-V2X Transmission

struct CubeRadio* radio = cube_radio_attach("cv2x");
struct CubeRadioConfiguration cfg = {
.tech = CUBE_RADIO_CV2X,
.cv2x = {
.rat = CUBE_RADIO_CV2X_RAT_LTE,
.family = CUBE_RADIO_CV2X_MESSAGE_FAMILY_ETSI_ITS,
},
};
cube_radio_configure(radio, &cfg);
uint8_t payload[] = "Hello C-V2X";
struct CubeRadioCv2xPdu pdu = { 0 };
cube_radio_transmit_cv2x(radio, &pdu, payload, sizeof(payload));
cube_radio_detach(radio);

This example transmits a raw payload using the C-V2X sidelink. For performance or compliance testing, parameters such as the RAT and family can be changed — but the RRC file must define the actual radio configuration.


5. Status and Polling

The Cube Radio API provides mechanisms to query the current radio link state and to poll for events such as received frames, CBR updates, or transmit readiness. These functions are essential for building responsive applications that process radio activity without blocking.

struct CubeRadioStatus {
CubeRadioTechnology technology; // ITS-G5 or C-V2X
bool command_link; // Control link active
bool data_link; // Data socket connected
bool cbr_link; // CBR (Channel Busy Ratio) socket connected
};

Query the current status using cube_radio_status():

struct CubeRadioStatus status;
cube_radio_ec rc = cube_radio_status(radio, &status);
if (rc == CUBE_RADIO_SUCCESS) {
printf("Active technology: %s\n",
(status.technology == CUBE_RADIO_ITS_G5) ? "ITS-G5" :
(status.technology == CUBE_RADIO_CV2X) ? "C-V2X" : "Undefined");
printf("Command link: %s\n", status.command_link ? "up" : "down");
printf("Data link: %s\n", status.data_link ? "up" : "down");
printf("CBR link: %s\n", status.cbr_link ? "up" : "down");
} else {
fprintf(stderr, "Failed to get radio status (error %d)\n", rc);
}

Applications can use cube_radio_poll() to wait for new data, transmit readiness, or CBR updates. This function allows users to easily realize loops processing radio events.

Available polling flags:

#define CUBE_RADIO_POLL_TX 0x01 // Transmission ready
#define CUBE_RADIO_POLL_RX 0x02 // Data received
#define CUBE_RADIO_POLL_CBR 0x04 // CBR data available

Example — wait for new data or a CBR sample:

int events = 0;
cube_radio_ec rc = cube_radio_poll(radio, &events, 1000); // 1000 ms timeout
if (rc == CUBE_RADIO_SUCCESS) {
if (events & CUBE_RADIO_POLL_RX)
printf("Incoming frame detected\n");
if (events & CUBE_RADIO_POLL_CBR)
printf("New CBR sample available\n");
if (events & CUBE_RADIO_POLL_TX)
printf("Radio ready for transmission\n");
} else if (rc == CUBE_RADIO_EAGAIN) {
printf("No events detected within timeout\n");
} else {
fprintf(stderr, "Polling failed (error %d)\n", rc);
}

The polling interface allows event-driven designs to react immediately to received frames or radio state changes — without relying on busy-wait loops or delays.


6. Error Handling

error.h

The Cube Radio API functions return standardized error codes to indicate operation results or failure reasons. These codes are defined in the CubeRadioErrorCodes enumeration and used consistently across all API calls.

enum CubeRadioErrorCodes {
CUBE_RADIO_SUCCESS = 0, // Operation completed successfully
CUBE_RADIO_EUNSUPPORTED, // Feature or operation not supported by this radio
CUBE_RADIO_EINVALID, // Invalid argument or configuration
CUBE_RADIO_EAGAIN, // Temporary condition, retry later (non-blocking)
CUBE_RADIO_EBUFSIZE, // Provided buffer too small for operation
CUBE_RADIO_ESOCKET, // Low-level socket I/O error
CUBE_RADIO_EPEER, // Peer behaved unexpectedly or sent invalid data
CUBE_RADIO_EPROTO, // Protocol version or structure mismatch
CUBE_RADIO_EBUSY, // Radio or resource currently busy
CUBE_RADIO_ECALLBACK, // Callback reference invalid or failed
CUBE_RADIO_EPOLL, // Polling mechanism (epoll/select) failure
CUBE_RADIO_ETHREAD, // Thread or concurrency error
CUBE_RADIO_EINTERNAL, // Internal radio stack or firmware error
};

Typical Usage Example:

cube_radio_ec rc = cube_radio_transmit_g5(radio, &pdu, payload, len);
if (rc != CUBE_RADIO_SUCCESS) {
fprintf(stderr, "Transmission failed: error code %d\n", rc);
switch (rc) {
case CUBE_RADIO_EBUSY:
fprintf(stderr, "Radio is busy — retry later.\n");
break;
case CUBE_RADIO_EINVALID:
fprintf(stderr, "Invalid configuration or argument.\n");
break;
case CUBE_RADIO_EUNSUPPORTED:
fprintf(stderr, "Requested feature is not supported.\n");
break;
default:
fprintf(stderr, "Unknown or internal error occurred.\n");
break;
}
}

Developers should always check return values and handle recoverable conditions (CUBE_RADIO_EAGAIN, CUBE_RADIO_EBUSY) gracefully. Errors such as CUBE_RADIO_EPROTO or CUBE_RADIO_EINTERNAL typically indicate configuration mismatches or hardware-level problems.

All Cube Radio API functions return a CubeRadioErrorCodes value. A return code of CUBE_RADIO_SUCCESS means the call succeeded, while any other code indicates a recoverable or fatal condition that should be handled appropriately.


7. Summary

FunctionDescription
cube_radio_attach()Connect to the radio interface
cube_radio_configure()Apply radio configuration
cube_radio_transmit_g5() / cube_radio_transmit_cv2x()Send frame
cube_radio_receive_g5() / cube_radio_receive_cv2x()Receive frame
cube_radio_fetch_cbr()Get CBR measurement
cube_radio_status()Query link and tech state
cube_radio_detach()Close and clean up

The Cube Radio API provides a unified, C-based control layer for ITS-G5 and C-V2X radios, including configuration, transmission, reception, and monitoring capabilities.

Previous
APIs