General updates, initial process for packet parsing.
Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
parent
35f33adb70
commit
a628889e74
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
#include "nh_event.h"
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue