General updates, initial process for packet parsing.

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-01-08 01:22:05 +08:00
parent 35f33adb70
commit a628889e74
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
8 changed files with 305 additions and 66 deletions

View File

@ -5,6 +5,7 @@ project(esp_nano_hosted)
set(NH_SOURCES
"proto/esp_hosted_config.pb.c"
"src/nh_ctrl_api.c"
"src/nh_event.c"
"src/nh_shared_if.c"
)

View File

@ -17,17 +17,31 @@ typedef nh_ret_t (*nh_osa_semaphore_take_t)(void *handle, nh_osa_semaphore_t sem
typedef nh_ret_t (*nh_osa_semaphore_give_t)(void *handle, nh_osa_semaphore_t sem);
typedef nh_ret_t (*nh_osa_semaphore_destroy_t)(void *handle, nh_osa_semaphore_t sem);
typedef void *nh_osa_queue_t;
typedef nh_ret_t (*nh_osa_queue_create_t)(void *handle, nh_osa_queue_t *queue, uint32_t item_size, uint32_t max_length);
typedef nh_ret_t (*nh_osa_queue_enqueue_t)(void *handle, nh_osa_queue_t queue, void *item, uint32_t timeout_msec);
typedef nh_ret_t (*nh_osa_queue_dequeue_t)(void *handle, nh_osa_queue_t queue, void *item, uint32_t timeout_msec);
typedef nh_ret_t (*nh_osa_queue_destroy_t)(void *handle, nh_osa_queue_t queue);
typedef nh_ret_t (*nh_osa_buf_allocate_t)(void *handle, uint8_t **buf, uint32_t buf_size);
typedef nh_ret_t (*nh_osa_buf_free_t)(void *handle, uint8_t *buf);
typedef struct {
nh_osa_buf_allocate_t buf_allocate;
nh_osa_buf_free_t buf_free;
nh_osa_buf_allocate_t buf_allocate;
nh_osa_buf_free_t buf_free;
/* Semaphore operations */
nh_osa_semaphore_create_t sem_create;
nh_osa_semaphore_take_t sem_take;
nh_osa_semaphore_give_t sem_give;
nh_osa_semaphore_destroy_t sem_destroy;
/* Queue operations */
nh_osa_queue_create_t queue_create;
nh_osa_queue_enqueue_t queue_enqueue;
nh_osa_queue_dequeue_t queue_dequeue;
nh_osa_queue_destroy_t queue_destroy;
void *user_data;
} nh_osa_t;

View File

@ -3,28 +3,15 @@
#include "nh_shared_if.h"
/* Event callbacks */
typedef void (*nh_cb_init_t)(void *handle);
typedef void (*nh_cb_heartbeat_t)(void *handle);
typedef void (*nh_cb_sta_disconn_from_ap_t)(void *handle);
typedef void (*nh_cb_sta_disconn_from_soft_ap_t)(void *handle);
typedef struct {
nh_cb_init_t init;
nh_cb_heartbeat_t heartbeat;
nh_cb_sta_disconn_from_ap_t sta_disconn_from_ap;
nh_cb_sta_disconn_from_soft_ap_t sta_disconn_from_soft_ap;
} nh_ctrl_api_cb_t;
typedef struct {
nh_shared_if_t *shared_if;
nh_osa_t *osa;
nh_ctrl_api_cb_t cb;
void *user_data;
/* Private states */
} nh_ctrl_api_t;
nh_ret_t nh_ctrl_api_init(nh_ctrl_api_t *api);
void nh_ctrl_api_task(nh_ctrl_api_t *api);
#endif // NH_CTRL_API_H

36
include/nh_event.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef NH_EVENT_H
#define NH_EVENT_H
#include "nh_common.h"
typedef enum {
NH_EVENT_TYPE_INIT,
} nh_event_type_t;
typedef enum {
NH_EVENT_INIT_CAP_WLAN_SDIO = (1U << 0U),
NH_EVENT_INIT_CAP_BT_UART = (1U << 1U),
NH_EVENT_INIT_CAP_BT_SDIO = (1U << 2U),
NH_EVENT_INIT_CAP_BLE_ONLY = (1U << 3U),
NH_EVENT_INIT_CAP_BR_EDR_ONLY = (1U << 4U),
NH_EVENT_INIT_CAP_WLAN_SPI = (1U << 5U),
NH_EVENT_INIT_CAP_BT_SPI = (1U << 6U),
NH_EVENT_INIT_CAP_CHECKSUM = (1U << 7U),
} nh_event_init_capability_t;
typedef enum {
NH_ESP_INIT_CHIP_UNRECOGNIZED = 0xFFU,
NH_ESP_INIT_CHIP_ESP32 = 0x00U,
NH_ESP_INIT_CHIP_ESP32S2 = 0x02U,
NH_ESP_INIT_CHIP_ESP32C3 = 0x05U,
NH_ESP_INIT_CHIP_ESP32S3 = 0x09U,
NH_ESP_INIT_CHIP_ESP32C2 = 0x0CU,
} nh_event_init_chip_id_t;
typedef struct {
nh_event_init_capability_t capabilities;
nh_event_init_chip_id_t chip_id;
uint8_t spi_freq;
} nh_event_init_t;
#endif // NH_EVENT_H

View File

@ -2,32 +2,41 @@
#define NH_SHARED_IF_H
#include "nh_common.h"
/* OPS */
typedef nh_ret_t (*nh_shared_if_ops_spi_xfer_t)(void *handle, uint8_t *tx_data, uint8_t *rx_data, uint32_t len);
typedef nh_ret_t (*nh_shared_if_ops_reset_t)(void *handle);
typedef nh_ret_t (*nh_shared_if_ops_hs_poll_t)(void *handle);
typedef nh_ret_t (*nh_shared_if_ops_drdy_read_t)(void *handle, bool *rdy);
/* Event callbacks */
typedef void (*nh_shared_if_cb_event_t)(void *handle, uint8_t *data);
typedef struct {
nh_shared_if_ops_spi_xfer_t xfer;
nh_shared_if_ops_reset_t reset;
nh_shared_if_ops_hs_poll_t handshake_poll;
nh_shared_if_ops_drdy_read_t data_ready_read;
void *user_data;
nh_shared_if_ops_drdy_read_t drdy_read;
} nh_shared_if_ops_t;
typedef struct {
nh_shared_if_cb_event_t event;
} nh_shared_if_cb_t;
typedef struct {
nh_shared_if_ops_t ops;
nh_osa_t *osa;
nh_shared_if_cb_t cb;
void *user_data;
nh_osa_t *osa;
/* Private states */
nh_osa_semaphore_t p_semaphore_xfer_req;
nh_osa_semaphore_t p_semaphore_tx;
uint8_t *p_buf_frame_tx; /* SPI TX frame, guarded */
uint8_t *p_buf_frame_rx; /* SPI RX frame, guarded */
uint8_t *p_buf_ctrl_tx; /* Control API TX payload */
uint8_t *p_buf_ctrl_rx; /* Control API RX payload */
nh_osa_queue_t p_queue_tx;
nh_osa_queue_t p_queue_rx_data;
nh_osa_queue_t p_queue_rx_ctrl;
uint8_t *p_buf_frame_tx; /* SPI TX frame */
uint8_t *p_buf_frame_rx; /* SPI RX frame */
} nh_shared_if_t;
nh_ret_t nh_shared_if_init(nh_shared_if_t *shared_if);
@ -36,6 +45,7 @@ void nh_shared_if_inject_data_ready(nh_shared_if_t *shared_if);
/* Internal APIs */
nh_ret_t nh_shared_if_ctrl_send(nh_shared_if_t *shared_if, uint8_t *tx_payload, uint32_t len, uint32_t timeout_ms);
nh_ret_t nh_shared_if_ctrl_recv(nh_shared_if_t *shared_if, uint8_t *rx_payload, uint32_t *len, uint32_t timeout_ms);
nh_ret_t nh_shared_if_ctrl_recv(nh_shared_if_t *shared_if, uint8_t **rx_payload, uint32_t *len, uint32_t timeout_ms);
nh_ret_t nh_shared_if_ctrl_free(nh_shared_if_t *shared_if, uint8_t *rx_payload);
#endif // NH_SHARED_IF_H

View File

@ -1,16 +1,15 @@
/* Private */
#include "nh_ctrl_api.h"
#include "pb_encode.h"
/* Nano-PB */
#include "pb_decode.h"
#include "pb_encode.h"
/* PB config */
#include "esp_hosted_config.pb.h"
#define NH_XFER_BUF_SIZE 1600
#define NH_SEMAPHORE_EVENT_TIMEOUT 1000
#define NH_SEMAPHORE_REQ_TIMEOUT 5000
static nh_ret_t nh_ctrl_api_general_request(nh_ctrl_api_t *api, CtrlMsg *msg);
#define NH_RECEIVE_TIMEOUT_MSEC 5000
#define NH_COMMAND_TIMEOUT_MSEC 30000
nh_ret_t nh_ctrl_api_init(nh_ctrl_api_t *api) {
nh_ret_t ret = NH_RET_SUCCESS;
@ -18,23 +17,17 @@ nh_ret_t nh_ctrl_api_init(nh_ctrl_api_t *api) {
return ret;
}
nh_ret_t nh_ctrl_api_get_mac(nh_ctrl_api_t *api, uint8_t *mac) {
nh_ret_t ret;
void nh_ctrl_api_task(nh_ctrl_api_t *api) {
nh_ret_t ret = NH_RET_SUCCESS;
/* TODO: Encode the request */
CtrlMsg req_msg = CtrlMsg_init_zero;
uint8_t *rx_payload;
uint32_t rx_payload_size;
req_msg.msg_type = CtrlMsgType_Req;
req_msg.msg_id = CtrlMsgId_Req_GetMACAddress;
req_msg.payload.req_get_mac_address.mode = Ctrl_WifiMode_STA;
ret = nh_shared_if_ctrl_recv(api->shared_if, &rx_payload, &rx_payload_size, NH_RECEIVE_TIMEOUT_MSEC);
if (ret != NH_RET_SUCCESS) {
return;
}
ret = nh_ctrl_api_general_request(api, &req_msg);
return ret;
}
static nh_ret_t nh_ctrl_api_general_request(nh_ctrl_api_t *api, CtrlMsg *msg) {
nh_ret_t ret;
pb_ostream_t ostream = pb_ostream_from_buffer(api->p_buf_tx, NH_XFER_BUF_SIZE);
pb_encode(&ostream, CtrlMsg_fields, msg);
/* TODO: process SERIAL data */
nh_shared_if_ctrl_free(api->shared_if, rx_payload);
}

1
src/nh_event.c Normal file
View File

@ -0,0 +1 @@
#include "nh_event.h"

View File

@ -1,8 +1,53 @@
#include "nh_shared_if.h"
#define NH_XFER_REQ_TIMEOUT 5000
#include "string.h"
#define NH_XFER_REQ_TIMEOUT 5000
#define NH_XFER_MAX_SIZE 1600
#define NH_XFER_QUEUE_SIZE 1
#ifdef __GNUC__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define H_TO_LE16(x) (x)
#define LE16_TO_H(x) (x)
#else
#define H_TO_LE16(x) (((x & 0xFFU) << 8U) | (x >> 8U))
#endif
#else
#warning "This code only supports GCC for now."
#endif
typedef enum {
NH_SHARED_IF_TYPE_STA = 0U,
NH_SHARED_IF_TYPE_AP = 1U,
NH_SHARED_IF_TYPE_SERIAL = 2U,
NH_SHARED_IF_TYPE_PRIV = 4U,
} nh_xfer_type_t;
typedef struct {
nh_xfer_type_t type;
uint8_t *buf;
uint32_t buf_len;
} nh_xfer_queue_item_t;
typedef struct __attribute__((packed)) {
uint8_t if_type : 4; /* Offset: 0x00 */
uint8_t if_num : 4; /* Offset: 0x00 */
uint8_t flags; /* Offset: 0x01 */
uint16_t len; /* Offset: 0x02 */
uint16_t offset; /* Offset: 0x04 */
uint16_t checksum; /* Offset: 0x06 */
uint16_t seq_num; /* Offset: 0x08 */
uint8_t reserved2; /* Offset: 0x0A */
union {
uint8_t reserved3;
uint8_t hci_pkt_type;
uint8_t priv_pkt_type;
}; /* Offset: 0x0B */
} nh_xfer_pkt_hdr_t; /* Size: 0x0C (12 bytes) */
static uint16_t nh_shared_if_checksum_calculate(nh_xfer_pkt_hdr_t *hdr);
static bool nh_shared_if_checksum_verify(nh_xfer_pkt_hdr_t *hdr);
nh_ret_t nh_shared_if_init(nh_shared_if_t *shared_if) {
nh_ret_t ret;
@ -12,11 +57,29 @@ nh_ret_t nh_shared_if_init(nh_shared_if_t *shared_if) {
return ret;
}
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &shared_if->p_buf_frame_tx, NH_XFER_MAX_SIZE);
ret = shared_if->osa->queue_create(shared_if->osa->user_data, &shared_if->p_queue_tx, sizeof(nh_xfer_queue_item_t),
NH_XFER_QUEUE_SIZE);
if (ret != NH_RET_SUCCESS) {
goto err_free_sem_xfer;
}
ret = shared_if->osa->queue_create(shared_if->osa->user_data, &shared_if->p_queue_rx_data,
sizeof(nh_xfer_queue_item_t), NH_XFER_QUEUE_SIZE);
if (ret != NH_RET_SUCCESS) {
goto err_free_queue_tx;
}
ret = shared_if->osa->queue_create(shared_if->osa->user_data, &shared_if->p_queue_rx_ctrl,
sizeof(nh_xfer_queue_item_t), NH_XFER_QUEUE_SIZE);
if (ret != NH_RET_SUCCESS) {
goto err_free_queue_rx_data;
}
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &shared_if->p_buf_frame_tx, NH_XFER_MAX_SIZE);
if (ret != NH_RET_SUCCESS) {
goto err_free_queue_rx_ctrl;
}
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &shared_if->p_buf_frame_rx, NH_XFER_MAX_SIZE);
if (ret != NH_RET_SUCCESS) {
goto err_free_tx_buf;
@ -27,12 +90,68 @@ nh_ret_t nh_shared_if_init(nh_shared_if_t *shared_if) {
err_free_tx_buf:
shared_if->osa->buf_free(shared_if->osa->user_data, shared_if->p_buf_frame_tx);
err_free_queue_rx_ctrl:
shared_if->osa->queue_destroy(shared_if->osa->user_data, shared_if->p_queue_rx_ctrl);
err_free_queue_rx_data:
shared_if->osa->queue_destroy(shared_if->osa->user_data, shared_if->p_queue_rx_data);
err_free_queue_tx:
shared_if->osa->queue_destroy(shared_if->osa->user_data, shared_if->p_queue_tx);
err_free_sem_xfer:
shared_if->osa->sem_destroy(shared_if->osa->user_data, shared_if->p_semaphore_xfer_req);
return ret;
}
void nh_shared_if_inject_data_ready(nh_shared_if_t *shared_if) {
shared_if->osa->sem_give(shared_if->osa->user_data, shared_if->p_semaphore_xfer_req);
}
nh_ret_t nh_shared_if_ctrl_send(nh_shared_if_t *shared_if, uint8_t *tx_payload, uint32_t len, uint32_t timeout_ms) {
nh_ret_t ret = NH_RET_SUCCESS;
nh_xfer_queue_item_t item = {
.type = NH_SHARED_IF_TYPE_SERIAL,
.buf_len = len,
};
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &item.buf, len);
if (ret != NH_RET_SUCCESS) {
return ret;
}
ret = shared_if->osa->queue_enqueue(shared_if->osa->user_data, shared_if->p_queue_tx, &item, timeout_ms);
if (ret != NH_RET_SUCCESS) {
shared_if->osa->buf_free(shared_if->osa->user_data, item.buf);
return ret;
}
return ret;
}
nh_ret_t nh_shared_if_ctrl_recv(nh_shared_if_t *shared_if, uint8_t **rx_payload, uint32_t *len, uint32_t timeout_ms) {
nh_ret_t ret = NH_RET_SUCCESS;
nh_xfer_queue_item_t item;
ret = shared_if->osa->queue_dequeue(shared_if->osa->user_data, shared_if->p_queue_rx_ctrl, &item, timeout_ms);
if (ret != NH_RET_SUCCESS) {
return ret;
}
*rx_payload = item.buf;
*len = item.buf_len;
return ret;
}
nh_ret_t nh_shared_if_ctrl_free(nh_shared_if_t *shared_if, uint8_t *rx_payload) {
return shared_if->osa->buf_free(shared_if->osa->user_data, rx_payload);
}
void nh_shared_if_task(nh_shared_if_t *shared_if) {
nh_ret_t ret;
@ -41,35 +160,113 @@ void nh_shared_if_task(nh_shared_if_t *shared_if) {
return;
}
/* Wait for device available */
ret = shared_if->ops.handshake_poll(shared_if->ops.user_data);
if(ret != NH_RET_SUCCESS) {
return;
}
/* Taken the xfer request semaphore. The possible reasons are:
* 1: Some data (could from any interfaces) needs to be sent
* 2: Data ready pin has been toggled, some data needs to be received
* 2: Data ready pin is high when HS at rising, some data needs to be received
*/
bool rx_available = false;
/* Check if new data is available */
ret = shared_if->ops.data_ready_read(shared_if->ops.user_data, &rx_available);
ret = shared_if->ops.drdy_read(shared_if->user_data, &rx_available);
if (ret != NH_RET_SUCCESS) {
return;
}
ret = shared_if->ops.xfer(shared_if->ops.user_data, shared_if->p_buf_frame_tx, shared_if->p_buf_frame_rx,
nh_xfer_queue_item_t item;
/* Clear TX header */
memset(shared_if->p_buf_frame_tx, 0U, sizeof(nh_xfer_pkt_hdr_t));
/* Check if we have data to send */
ret = shared_if->osa->queue_dequeue(shared_if->user_data, shared_if->p_queue_tx, &item, 0U);
if (ret == NH_RET_SUCCESS) {
/* Write header and payload since we have data to send */
nh_xfer_pkt_hdr_t *hdr = (nh_xfer_pkt_hdr_t *)shared_if->p_buf_frame_tx;
hdr->if_type = item.type;
hdr->offset = H_TO_LE16(sizeof(nh_xfer_pkt_hdr_t)); /* Payload follows header... */
hdr->len = H_TO_LE16(item.buf_len);
hdr->checksum = H_TO_LE16(nh_shared_if_checksum_calculate(hdr));
/* Copy payload */
memcpy(&shared_if->p_buf_frame_tx[sizeof(nh_xfer_pkt_hdr_t)], item.buf, item.buf_len);
/* Queue consumer owns the buffer. */
shared_if->osa->buf_free(shared_if->osa->user_data, item.buf);
}
/* Exchange buffers */
ret = shared_if->ops.xfer(shared_if->user_data, shared_if->p_buf_frame_tx, shared_if->p_buf_frame_rx,
NH_XFER_MAX_SIZE);
if (ret != NH_RET_SUCCESS) {
return;
}
/* If we do not have RX data... */
if (!rx_available) {
return;
/* If we have RX data... */
if (rx_available) {
nh_xfer_pkt_hdr_t *hdr = (nh_xfer_pkt_hdr_t *)shared_if->p_buf_frame_rx;
if (!nh_shared_if_checksum_verify(hdr)) {
return;
}
item.type = LE16_TO_H(hdr->if_type);
item.buf_len = LE16_TO_H(hdr->len);
uint16_t payload_offset = LE16_TO_H(hdr->offset);
if (item.type == NH_SHARED_IF_TYPE_SERIAL) {
if (item.buf_len) {
/* Allocate payload */
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &item.buf, item.buf_len);
if (ret != NH_RET_SUCCESS) {
return;
}
memcpy(item.buf, &shared_if->p_buf_frame_rx[payload_offset], item.buf_len);
}
/* Enqueue response */
ret = shared_if->osa->queue_enqueue(shared_if->osa->user_data, shared_if->p_queue_rx_ctrl, &item, 0);
if (ret != NH_RET_SUCCESS) {
/* Queue is full, maybe the ctrl interface is not active. */
shared_if->osa->buf_free(shared_if->osa->user_data, item.buf);
}
} else if (item.type == NH_SHARED_IF_TYPE_PRIV) {
/* Event is using PRIV interface. */
if (item.buf_len) {
if (shared_if->cb.event) {
/* Note: This is a blocking callback !! */
shared_if->cb.event(shared_if->user_data, &shared_if->p_buf_frame_rx[payload_offset]);
}
}
}
}
}
static uint16_t nh_shared_if_checksum_calculate(nh_xfer_pkt_hdr_t *hdr) {
uint16_t checksum = 0U;
uint16_t checksum_length = sizeof(nh_xfer_pkt_hdr_t) + LE16_TO_H(hdr->len);
for (size_t i = 0; i < checksum_length; i++) {
checksum += ((uint8_t *)hdr)[i];
}
/* TODO: Check interface type... */
return checksum;
}
static bool nh_shared_if_checksum_verify(nh_xfer_pkt_hdr_t *hdr) {
bool ret = true;
uint16_t checksum = LE16_TO_H(hdr->checksum);
hdr->checksum = 0U;
if (checksum != nh_shared_if_checksum_calculate(hdr)) {
return false;
}
hdr->checksum = H_TO_LE16(checksum);
return ret;
}