51#include "esp_hosted_host_fw_ver.h"
52#include "esp_hosted_interface.h"
53#include "esp_hosted_os_abstraction.h"
54#include "esp_hosted_rpc.pb-c.h"
55#include "esp_hosted_transport.h"
56#include "protobuf-c/protobuf-c.h"
57#include "transport_drv.h"
77typedef enum : uint16_t {
151 (void)allocator_data;
152 return g_h.funcs->_h_malloc(size);
170 (void)allocator_data;
171 if (pointer !=
nullptr) {
172 g_h.funcs->_h_free(pointer);
190 .allocator_data =
nullptr,
219 if ((out ==
nullptr) || (out_len ==
nullptr)) {
224 RpcReqGetCoprocessorFwVersion body;
225 rpc__req__get_coprocessor_fw_version__init(&body);
229 req.msg_type = RPC_TYPE__Req;
230 req.msg_id = RPC_ID__Req_GetCoprocessorFwVersion;
232 req.payload_case = RPC__PAYLOAD_REQ_GET_COPROCESSOR_FWVERSION;
233 req.req_get_coprocessor_fwversion = &body;
235 const size_t proto_len = rpc__get_packed_size(&req);
243 out[at + i] = (uint8_t)RPC_EP_NAME_RSP[i];
248 if (rpc__pack(&req, &out[at]) != proto_len) {
251 *out_len = (uint16_t)(at + (uint16_t)proto_len);
273static const uint8_t*
c6_fwver_tlv_body(
const uint8_t* payload, uint16_t len, uint16_t* proto_len)
284 const uint16_t seen_ep =
287 if (seen_ep != ep_len) {
291 for (uint16_t i = 0U; i < ep_len; i++) {
293 if ((got != (uint8_t)RPC_EP_NAME_RSP[i]) && (got != (uint8_t)RPC_EP_NAME_EVT[i])) {
325 if ((target ==
nullptr) || (target->data ==
nullptr)) {
330 for (
size_t i = 0U; i < take; i++) {
352 if ((msg->msg_type != RPC_TYPE__Resp) || (msg->msg_id != RPC_ID__Resp_GetCoprocessorFwVersion) ||
353 (msg->payload_case != RPC__PAYLOAD_RESP_GET_COPROCESSOR_FWVERSION) ||
354 (msg->resp_get_coprocessor_fwversion ==
nullptr)) {
357 const RpcRespGetCoprocessorFwVersion* body = msg->resp_get_coprocessor_fwversion;
372 if ((if_type != (uint8_t)ESP_SERIAL_IF) || (payload ==
nullptr) ||
s_c6_fwver_rsp.seen) {
376 uint16_t proto_len = 0U;
378 if (proto ==
nullptr) {
379 c6_fwver_puts(
"c6_fwver: serial frame is not an RPC envelope, len=");
386 if (msg ==
nullptr) {
455 c6_fwver_puts(
"absent -- either the co-processor has not been power-cycled since its "
456 "last drain, or its INIT event was dropped (read ifnum_defect on the "
457 "caps pump line)\r\n");
465 const bool agrees = (ESP_HOSTED_VERSION_MAJOR(seen) ==
s_c6_fwver_rsp.major) &&
468 c6_fwver_puts(agrees ?
" agrees with the RPC answer\r\n" :
" DISAGREES with the RPC answer\r\n");
494 c6_fwver_puts(
" (the vendored host driver's own version) chip_id=0x");
504 c6_fwver_puts(
"c6_fwver: FAIL no RPC response -- the co-processor never answered\r\n");
511 c6_fwver_puts(
"c6_fwver: FAIL response UID does not match the request\r\n");
515 c6_fwver_puts(
"c6_fwver: FAIL co-processor reported an error result\r\n");
518 if ((
s_c6_fwver_rsp.major != (uint32_t)ESP_HOSTED_VERSION_MAJOR_1) ||
521 c6_fwver_puts(
"c6_fwver: FAIL co-processor firmware version is not the one this host "
522 "was built against\r\n");
525 if (
s_c6_fwver_rsp.chip_id != (uint32_t)ESP_PRIV_FIRMWARE_CHIP_ESP32C6) {
526 c6_fwver_puts(
"c6_fwver: FAIL the answering co-processor is not an ESP32-C6\r\n");
529 c6_fwver_puts(
"c6_fwver: PASS esp-hosted RPC round-trip, co-processor firmware ");
549 if (if_type == (uint8_t)ESP_PRIV_IF) {
552 if (if_type == (uint8_t)ESP_SERIAL_IF) {
555 c6_fwver_puts(
"c6_fwver: frame on an interface this app does not use\r\n");
Shared contract for the esp-hosted RPC round-trip application.
@ k_c6_fwver_rpc_uid
UID stamped on the request; the response must carry it back unchanged.
void c6_fwver_put_i32(int32_t value)
Emit a signed 32-bit value in decimal.
void c6_fwver_put_hex(uint32_t value, uint8_t digits)
Emit a value as a fixed-width lower-case hexadecimal field.
bool c6_fwver_priv_consume(uint8_t if_type, uint8_t if_num, const uint8_t *payload, uint16_t len)
Decode an ESP_PRIV_IF frame and report what it announced.
@ k_c6_fwver_hex_byte
Hex digits printed for a byte-wide field.
@ k_c6_fwver_text_max
Longest co-processor-supplied string echoed to the console; anything longer is truncated rather than ...
void c6_fwver_put_text(const uint8_t *text, size_t len)
Emit a length-counted byte range as printable text.
uint32_t c6_fwver_priv_init_version(void)
Report the version the boot INIT event announced, if one arrived.
void c6_fwver_put_u32(uint32_t value)
Emit an unsigned 32-bit value in decimal.
void c6_fwver_puts(const char *text)
Write a NUL-terminated string to the board console.
static void c6_fwver_rpc_take_target(const ProtobufCBinaryData *target)
Copy the response's target string into the record, bounded.
static bool c6_fwver_rpc_take(const Rpc *msg)
Record a decoded message if it is the awaited response.
static const uint8_t * c6_fwver_tlv_body(const uint8_t *payload, uint16_t len, uint16_t *proto_len)
Strip the TLV envelope off a received serial payload.
bool c6_fwver_rpc_consume(uint8_t if_type, uint8_t if_num, const uint8_t *payload, uint16_t len)
Decode an ESP_SERIAL_IF frame as the awaited RPC response.
static void c6_fwver_rpc_print_crosscheck(void)
Report the boot event's version reading beside the RPC's.
bool c6_fwver_dispatch(uint8_t if_type, uint8_t if_num, const uint8_t *payload, uint16_t len)
Route a received frame to the module that understands it.
static void * c6_fwver_rpc_pool_alloc(void *allocator_data, size_t size)
Allocate through the esp-hosted port's fixed byte pool.
static void c6_fwver_rpc_print_expectation(void)
Print what this host expects, before it says what it got.
c6_fwver_tlv_t
The serial endpoint's TLV envelope, tag by tag.
@ k_c6_fwver_tlv_overhead
Bytes the envelope costs on top of the protobuf payload.
@ k_c6_fwver_tlv_type
Offset of a tag's type byte.
@ k_c6_fwver_tlv_len_lo
Offset of a tag's length, low byte.
@ k_c6_fwver_tlv_value
Offset of a tag's value.
@ k_c6_fwver_tlv_t_epname
Tag introducing the endpoint name.
@ k_c6_fwver_tlv_len_hi
Offset of a tag's length, high byte.
@ k_c6_fwver_tlv_shift
Shift between the two length bytes.
@ k_c6_fwver_tlv_mask
Byte mask for the low length byte.
@ k_c6_fwver_tlv_t_data
Tag introducing the protobuf payload.
@ k_c6_fwver_tlv_ep_len
Endpoint-name length; both endpoint names share it.
static uint16_t c6_fwver_tlv_head(uint8_t *out, uint16_t at, uint8_t type, uint16_t len)
Write one TLV tag header at a cursor.
static void c6_fwver_rpc_print_response(void)
Print the decoded response, field by field.
static ProtobufCAllocator s_c6_fwver_allocator
The allocator the generated protobuf decoder is handed.
static c6_fwver_rsp_t s_c6_fwver_rsp
The one response this application is waiting for.
struct c6_fwver_rsp c6_fwver_rsp_t
ra8_err_t c6_fwver_rpc_request(uint8_t *out, uint16_t cap, uint16_t *out_len)
Build the TLV-wrapped RPC firmware-version request.
static void c6_fwver_rpc_pool_free(void *allocator_data, void *pointer)
Return a block to the esp-hosted port's fixed byte pool.
bool c6_fwver_rpc_report(void)
Print the recorded response and decide the run's verdict.
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
struct hosted_config_t g_h
The handle the vendored core dereferences to reach the vtable.
Every field this application read out of the RPC response.
uint32_t minor
Firmware minor version.
uint32_t major
Firmware major version.
uint8_t target_len
Bytes held in target.
uint8_t target[k_c6_fwver_text_max]
CONFIG_IDF_TARGET, truncated.
uint32_t patch
Firmware patch version.
bool seen
A matching response was decoded.
uint32_t uid
UID echoed back by the co-processor.
int32_t resp
Co-processor result code; 0 is ok.
uint32_t chip_id
CONFIG_IDF_FIRMWARE_CHIP_ID.