Added CTRL interface parser and event dispatch, fixed proto for nanopb.

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-01-08 22:22:13 +08:00
parent 67a2ff8c3b
commit 624150181c
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
12 changed files with 440 additions and 88 deletions

View File

@ -5,7 +5,8 @@ project(esp_nano_hosted)
set(NH_SOURCES
"proto/esp_hosted_config.pb.c"
"src/nh_ctrl_api.c"
"src/nh_event_helpers.c"
"src/nh_helper_event.c"
"src/nh_helper_serial.c"
"src/nh_shared_if.c"
)

View File

@ -3,15 +3,27 @@
#include "nh_shared_if.h"
typedef void (*nh_ctrl_api_event_cb_init_t)(void *handle);
typedef struct {
nh_ctrl_api_event_cb_init_t init;
} 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_osa_semaphore_t p_sem_req;
nh_osa_semaphore_t p_sem_resp;
uint8_t *p_buf_rx;
uint32_t p_buf_rx_len;
} 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);
nh_ret_t nh_ctrl_api_get_mac_address(nh_ctrl_api_t *api, uint8_t *mac_addr);
#endif // NH_CTRL_API_H

View File

@ -0,0 +1,21 @@
#ifndef NH_HELPER_SERIAL_H
#define NH_HELPER_SERIAL_H
#include "nh_common.h"
typedef enum {
NH_SERIAL_TAG_EP_NAME = 1U,
NH_SERIAL_TAG_DATA = 2U,
} nh_serial_tag_t;
typedef enum {
NH_SERIAL_EP_RESP,
NH_SERIAL_EP_EVENT,
} nh_serial_ep_type_t;
nh_ret_t nh_serial_get_type(nh_serial_ep_type_t *type, uint8_t *buf);
nh_ret_t nh_serial_get_payload(uint8_t *buf, uint8_t **payload, uint16_t *length);
nh_ret_t nh_serial_header_length(nh_serial_ep_type_t type, uint16_t *header_length);
nh_ret_t nh_serial_write_header(nh_serial_ep_type_t type, uint8_t *buf, uint16_t data_len, uint8_t **data_start);
#endif // NH_HELPER_SERIAL_H

View File

@ -2,7 +2,8 @@
#define NH_SHARED_IF_H
#include "nh_common.h"
#include "nh_event_helpers.h"
#include "nh_helper_event.h"
#include "nh_helper_serial.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);
@ -34,7 +35,7 @@ typedef struct {
nh_osa_queue_t p_queue_tx;
nh_osa_queue_t p_queue_rx_data;
nh_osa_queue_t p_queue_rx_ctrl;
nh_osa_queue_t p_queue_rx_serial;
uint8_t *p_buf_frame_tx; /* SPI TX frame */
uint8_t *p_buf_frame_rx; /* SPI RX frame */
@ -45,8 +46,9 @@ void nh_shared_if_task(nh_shared_if_t *shared_if);
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_free(nh_shared_if_t *shared_if, uint8_t *rx_payload);
nh_ret_t nh_shared_if_serial_if_send(nh_shared_if_t *shared_if, uint8_t *tx_payload, uint32_t len, uint32_t timeout_ms);
nh_ret_t nh_shared_if_serial_if_recv(nh_shared_if_t *shared_if, nh_serial_ep_type_t *ep_type, uint8_t **rx_payload,
uint32_t *len, uint32_t timeout_ms);
nh_ret_t nh_shared_if_serial_if_free(nh_shared_if_t *shared_if, uint8_t *rx_payload);
#endif // NH_SHARED_IF_H

View File

@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.8-dev */
/* Generated by nanopb-0.4.7 */
#include "esp_hosted_config.pb.h"
#if PB_PROTO_HEADER_VERSION != 40

View File

@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.8-dev */
/* Generated by nanopb-0.4.7 */
#ifndef PB_ESP_HOSTED_CONFIG_PB_H_INCLUDED
#define PB_ESP_HOSTED_CONFIG_PB_H_INCLUDED
@ -365,6 +365,7 @@ typedef struct _CtrlMsg {
CtrlMsgType msg_type;
/* msg id */
CtrlMsgId msg_id;
pb_callback_t cb_payload;
pb_size_t which_payload;
union {
/* * Requests * */
@ -558,7 +559,7 @@ extern "C" {
#define CtrlMsg_Event_Heartbeat_init_default {0}
#define CtrlMsg_Event_StationDisconnectFromAP_init_default {0}
#define CtrlMsg_Event_StationDisconnectFromESPSoftAP_init_default {0, {{NULL}, NULL}}
#define CtrlMsg_init_default {_CtrlMsgType_MIN, _CtrlMsgId_MIN, 0, {CtrlMsg_Req_GetMacAddress_init_default}}
#define CtrlMsg_init_default {_CtrlMsgType_MIN, _CtrlMsgId_MIN, {{NULL}, NULL}, 0, {CtrlMsg_Req_GetMacAddress_init_default}}
#define ScanResult_init_zero {{{NULL}, NULL}, 0, 0, {{NULL}, NULL}, _Ctrl_WifiSecProt_MIN}
#define ConnectedSTAList_init_zero {{{NULL}, NULL}, 0}
#define CtrlMsg_Req_GetMacAddress_init_zero {0}
@ -602,7 +603,7 @@ extern "C" {
#define CtrlMsg_Event_Heartbeat_init_zero {0}
#define CtrlMsg_Event_StationDisconnectFromAP_init_zero {0}
#define CtrlMsg_Event_StationDisconnectFromESPSoftAP_init_zero {0, {{NULL}, NULL}}
#define CtrlMsg_init_zero {_CtrlMsgType_MIN, _CtrlMsgId_MIN, 0, {CtrlMsg_Req_GetMacAddress_init_zero}}
#define CtrlMsg_init_zero {_CtrlMsgType_MIN, _CtrlMsgId_MIN, {{NULL}, NULL}, 0, {CtrlMsg_Req_GetMacAddress_init_zero}}
/* Field tags (for use in manual encoding/decoding) */
#define ScanResult_ssid_tag 1
@ -1002,52 +1003,52 @@ X(a, CALLBACK, SINGULAR, BYTES, mac, 2)
#define CtrlMsg_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, msg_type, 1) \
X(a, STATIC, SINGULAR, UENUM, msg_id, 2) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_get_mac_address,payload.req_get_mac_address), 101) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_set_mac_address,payload.req_set_mac_address), 102) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_get_wifi_mode,payload.req_get_wifi_mode), 103) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_set_wifi_mode,payload.req_set_wifi_mode), 104) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_scan_ap_list,payload.req_scan_ap_list), 105) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_get_ap_config,payload.req_get_ap_config), 106) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_connect_ap,payload.req_connect_ap), 107) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_disconnect_ap,payload.req_disconnect_ap), 108) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_get_softap_config,payload.req_get_softap_config), 109) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_set_softap_vendor_specific_ie,payload.req_set_softap_vendor_specific_ie), 110) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_start_softap,payload.req_start_softap), 111) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_softap_connected_stas_list,payload.req_softap_connected_stas_list), 112) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_stop_softap,payload.req_stop_softap), 113) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_set_power_save_mode,payload.req_set_power_save_mode), 114) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_get_power_save_mode,payload.req_get_power_save_mode), 115) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_ota_begin,payload.req_ota_begin), 116) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_ota_write,payload.req_ota_write), 117) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_ota_end,payload.req_ota_end), 118) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_set_wifi_max_tx_power,payload.req_set_wifi_max_tx_power), 119) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_get_wifi_curr_tx_power,payload.req_get_wifi_curr_tx_power), 120) \
X(a, STATIC, ONEOF, MESSAGE, (payload,req_config_heartbeat,payload.req_config_heartbeat), 121) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_get_mac_address,payload.resp_get_mac_address), 201) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_set_mac_address,payload.resp_set_mac_address), 202) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_get_wifi_mode,payload.resp_get_wifi_mode), 203) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_set_wifi_mode,payload.resp_set_wifi_mode), 204) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_scan_ap_list,payload.resp_scan_ap_list), 205) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_get_ap_config,payload.resp_get_ap_config), 206) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_connect_ap,payload.resp_connect_ap), 207) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_disconnect_ap,payload.resp_disconnect_ap), 208) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_get_softap_config,payload.resp_get_softap_config), 209) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_set_softap_vendor_specific_ie,payload.resp_set_softap_vendor_specific_ie), 210) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_start_softap,payload.resp_start_softap), 211) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_softap_connected_stas_list,payload.resp_softap_connected_stas_list), 212) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_stop_softap,payload.resp_stop_softap), 213) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_set_power_save_mode,payload.resp_set_power_save_mode), 214) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_get_power_save_mode,payload.resp_get_power_save_mode), 215) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_ota_begin,payload.resp_ota_begin), 216) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_ota_write,payload.resp_ota_write), 217) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_ota_end,payload.resp_ota_end), 218) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_set_wifi_max_tx_power,payload.resp_set_wifi_max_tx_power), 219) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_get_wifi_curr_tx_power,payload.resp_get_wifi_curr_tx_power), 220) \
X(a, STATIC, ONEOF, MESSAGE, (payload,resp_config_heartbeat,payload.resp_config_heartbeat), 221) \
X(a, STATIC, ONEOF, MESSAGE, (payload,event_esp_init,payload.event_esp_init), 301) \
X(a, STATIC, ONEOF, MESSAGE, (payload,event_heartbeat,payload.event_heartbeat), 302) \
X(a, STATIC, ONEOF, MESSAGE, (payload,event_station_disconnect_from_AP,payload.event_station_disconnect_from_AP), 303) \
X(a, STATIC, ONEOF, MESSAGE, (payload,event_station_disconnect_from_ESP_SoftAP,payload.event_station_disconnect_from_ESP_SoftAP), 304)
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_get_mac_address,payload.req_get_mac_address), 101) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_set_mac_address,payload.req_set_mac_address), 102) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_get_wifi_mode,payload.req_get_wifi_mode), 103) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_set_wifi_mode,payload.req_set_wifi_mode), 104) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_scan_ap_list,payload.req_scan_ap_list), 105) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_get_ap_config,payload.req_get_ap_config), 106) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_connect_ap,payload.req_connect_ap), 107) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_disconnect_ap,payload.req_disconnect_ap), 108) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_get_softap_config,payload.req_get_softap_config), 109) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_set_softap_vendor_specific_ie,payload.req_set_softap_vendor_specific_ie), 110) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_start_softap,payload.req_start_softap), 111) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_softap_connected_stas_list,payload.req_softap_connected_stas_list), 112) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_stop_softap,payload.req_stop_softap), 113) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_set_power_save_mode,payload.req_set_power_save_mode), 114) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_get_power_save_mode,payload.req_get_power_save_mode), 115) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_ota_begin,payload.req_ota_begin), 116) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_ota_write,payload.req_ota_write), 117) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_ota_end,payload.req_ota_end), 118) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_set_wifi_max_tx_power,payload.req_set_wifi_max_tx_power), 119) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_get_wifi_curr_tx_power,payload.req_get_wifi_curr_tx_power), 120) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_config_heartbeat,payload.req_config_heartbeat), 121) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_get_mac_address,payload.resp_get_mac_address), 201) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_set_mac_address,payload.resp_set_mac_address), 202) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_get_wifi_mode,payload.resp_get_wifi_mode), 203) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_set_wifi_mode,payload.resp_set_wifi_mode), 204) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_scan_ap_list,payload.resp_scan_ap_list), 205) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_get_ap_config,payload.resp_get_ap_config), 206) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_connect_ap,payload.resp_connect_ap), 207) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_disconnect_ap,payload.resp_disconnect_ap), 208) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_get_softap_config,payload.resp_get_softap_config), 209) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_set_softap_vendor_specific_ie,payload.resp_set_softap_vendor_specific_ie), 210) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_start_softap,payload.resp_start_softap), 211) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_softap_connected_stas_list,payload.resp_softap_connected_stas_list), 212) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_stop_softap,payload.resp_stop_softap), 213) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_set_power_save_mode,payload.resp_set_power_save_mode), 214) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_get_power_save_mode,payload.resp_get_power_save_mode), 215) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_ota_begin,payload.resp_ota_begin), 216) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_ota_write,payload.resp_ota_write), 217) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_ota_end,payload.resp_ota_end), 218) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_set_wifi_max_tx_power,payload.resp_set_wifi_max_tx_power), 219) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_get_wifi_curr_tx_power,payload.resp_get_wifi_curr_tx_power), 220) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_config_heartbeat,payload.resp_config_heartbeat), 221) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,event_esp_init,payload.event_esp_init), 301) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,event_heartbeat,payload.event_heartbeat), 302) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,event_station_disconnect_from_AP,payload.event_station_disconnect_from_AP), 303) \
X(a, STATIC, ONEOF, MSG_W_CB, (payload,event_station_disconnect_from_ESP_SoftAP,payload.event_station_disconnect_from_ESP_SoftAP), 304)
#define CtrlMsg_CALLBACK NULL
#define CtrlMsg_DEFAULT NULL
#define CtrlMsg_payload_req_get_mac_address_MSGTYPE CtrlMsg_Req_GetMacAddress

View File

@ -1,5 +1,7 @@
syntax = "proto3";
import 'nanopb.proto';
/* Enums similar to ESP IDF */
enum Ctrl_VendorIEType {
Beacon = 0;
@ -360,6 +362,8 @@ message CtrlMsg_Event_StationDisconnectFromESPSoftAP {
}
message CtrlMsg {
option (nanopb_msgopt).submsg_callback = true;
/* msg_type could be req, resp or Event */
CtrlMsgType msg_type = 1;

View File

@ -8,26 +8,206 @@
/* PB config */
#include "esp_hosted_config.pb.h"
#define NH_RECEIVE_TIMEOUT_MSEC 5000
#define NH_COMMAND_TIMEOUT_MSEC 30000
#define NH_COMMAND_REQ_MEM_SIZE 256
static nh_ret_t nh_ctrl_api_parse_event(nh_ctrl_api_t *api, CtrlMsgId *event_id, uint8_t *buf, uint32_t buf_len);
static void nh_ctrl_api_dispatch_event(nh_ctrl_api_t *api, CtrlMsgId event_id);
static nh_ret_t nh_ctrl_api_general_request(nh_ctrl_api_t *api, CtrlMsg *tx_msg);
static nh_ret_t nh_ctrl_api_general_response(nh_ctrl_api_t *api, CtrlMsg *rx_msg);
static nh_ret_t nh_ctrl_api_general_response_free(nh_ctrl_api_t *api);
static bool nh_ctrl_api_payload_decode_cb(pb_istream_t *stream, const pb_field_t *field, void **arg);
nh_ret_t nh_ctrl_api_init(nh_ctrl_api_t *api) {
nh_ret_t ret = NH_RET_SUCCESS;
ret = api->osa->sem_create(api->osa->user_data, &api->p_sem_req);
if (ret != NH_RET_SUCCESS) {
return ret;
}
ret = api->osa->sem_create(api->osa->user_data, &api->p_sem_resp);
if (ret != NH_RET_SUCCESS) {
goto free_sem_req;
}
ret = api->osa->sem_give(api->osa->user_data, api->p_sem_req);
if (ret != NH_RET_SUCCESS) {
goto free_sem_resp;
}
return ret;
free_sem_resp:
api->osa->sem_destroy(api->osa->user_data, api->p_sem_resp);
free_sem_req:
api->osa->sem_destroy(api->osa->user_data, api->p_sem_req);
return ret;
}
nh_ret_t nh_ctrl_api_get_mac_address(nh_ctrl_api_t *api, uint8_t *mac_addr) {
nh_ret_t ret = NH_RET_SUCCESS;
ret = api->osa->sem_take(api->osa->user_data, api->p_sem_req, NH_COMMAND_TIMEOUT_MSEC);
if (ret != NH_RET_SUCCESS) {
return ret;
}
CtrlMsg tx_msg = CtrlMsg_init_zero;
tx_msg.msg_type = CtrlMsgType_Req;
tx_msg.msg_id = CtrlMsgId_Req_GetMACAddress;
tx_msg.which_payload = CtrlMsg_req_get_mac_address_tag;
tx_msg.payload.req_get_mac_address.mode = Ctrl_WifiMode_STA;
ret = nh_ctrl_api_general_request(api, &tx_msg);
if (ret != NH_RET_SUCCESS) {
goto give_sem_exit;
}
CtrlMsg rx_msg = CtrlMsg_init_zero;
rx_msg.cb_payload.arg = mac_addr;
ret = nh_ctrl_api_general_response(api, &rx_msg);
if (ret != NH_RET_SUCCESS) {
goto give_sem_exit;
}
nh_ctrl_api_general_response_free(api);
give_sem_exit:
api->osa->sem_give(api->osa->user_data, api->p_sem_req);
return ret;
}
void nh_ctrl_api_task(nh_ctrl_api_t *api) {
nh_ret_t ret = NH_RET_SUCCESS;
uint8_t *rx_payload;
uint32_t rx_payload_size;
uint8_t *payload;
uint32_t payload_size;
nh_serial_ep_type_t ep_type;
ret = nh_shared_if_ctrl_recv(api->shared_if, &rx_payload, &rx_payload_size, NH_RECEIVE_TIMEOUT_MSEC);
ret = nh_shared_if_serial_if_recv(api->shared_if, &ep_type, &payload, &payload_size, NH_COMMAND_TIMEOUT_MSEC);
if (ret != NH_RET_SUCCESS) {
return;
}
/* TODO: process SERIAL data */
nh_shared_if_ctrl_free(api->shared_if, rx_payload);
}
if (ep_type == NH_SERIAL_EP_RESP) {
api->p_buf_rx = payload;
api->p_buf_rx_len = payload_size;
ret = api->osa->sem_give(api->osa->user_data, api->p_sem_resp);
if (ret != NH_RET_SUCCESS) {
nh_shared_if_serial_if_free(api->shared_if, payload);
return;
}
} else if (ep_type == NH_SERIAL_EP_EVENT) {
CtrlMsgId event_id;
ret = nh_ctrl_api_parse_event(api, &event_id, payload, payload_size);
if (ret == NH_RET_SUCCESS) {
nh_ctrl_api_dispatch_event(api, event_id);
}
nh_shared_if_serial_if_free(api->shared_if, payload);
}
}
static nh_ret_t nh_ctrl_api_parse_event(nh_ctrl_api_t *api, CtrlMsgId *event_id, uint8_t *buf, uint32_t buf_len) {
pb_istream_t stream = pb_istream_from_buffer(buf, buf_len);
CtrlMsg event_msg = CtrlMsg_init_zero;
if (!pb_decode(&stream, CtrlMsg_fields, &event_msg)) {
return NH_RET_FAIL;
}
*event_id = event_msg.msg_id;
return NH_RET_SUCCESS;
}
static void nh_ctrl_api_dispatch_event(nh_ctrl_api_t *api, CtrlMsgId event_id) {
switch (event_id) {
case CtrlMsgId_Event_ESPInit: {
if (api->cb.init) {
api->cb.init(api->user_data);
}
break;
}
default:
break;
}
}
static nh_ret_t nh_ctrl_api_general_request(nh_ctrl_api_t *api, CtrlMsg *tx_msg) {
nh_ret_t ret = NH_RET_SUCCESS;
uint8_t *req_buf;
ret = api->osa->buf_allocate(api->osa->user_data, &req_buf, NH_COMMAND_REQ_MEM_SIZE);
if (ret != NH_RET_SUCCESS) {
return ret;
}
pb_ostream_t tx_stream = pb_ostream_from_buffer(req_buf, NH_COMMAND_REQ_MEM_SIZE);
if (!pb_encode(&tx_stream, CtrlMsg_fields, tx_msg)) {
/* False on error: */
ret = NH_RET_FAIL;
goto free_tx_exit;
}
ret = nh_shared_if_serial_if_send(api->shared_if, req_buf, tx_stream.bytes_written, NH_COMMAND_TIMEOUT_MSEC);
free_tx_exit:
api->osa->buf_free(api->osa->user_data, req_buf);
return ret;
}
static nh_ret_t nh_ctrl_api_general_response(nh_ctrl_api_t *api, CtrlMsg *rx_msg) {
nh_ret_t ret = NH_RET_SUCCESS;
ret = api->osa->sem_take(api->osa->user_data, api->p_sem_resp, NH_COMMAND_TIMEOUT_MSEC);
if (ret != NH_RET_SUCCESS) {
return ret;
}
pb_istream_t rx_stream = pb_istream_from_buffer(api->p_buf_rx, api->p_buf_rx_len);
rx_msg->cb_payload.funcs.decode = nh_ctrl_api_payload_decode_cb;
if (!pb_decode(&rx_stream, CtrlMsg_fields, rx_msg)) {
nh_shared_if_serial_if_free(api->shared_if, api->p_buf_rx);
return NH_RET_FAIL;
}
return ret;
}
static nh_ret_t nh_ctrl_api_general_response_free(nh_ctrl_api_t *api) {
return nh_shared_if_serial_if_free(api->shared_if, api->p_buf_rx);
}
static bool nh_ctrl_api_bytes_decode_cb(pb_istream_t *stream, const pb_field_t *field, void **arg) {
if (stream->bytes_left) {
return pb_read(stream, *arg, stream->bytes_left);
}
return true;
}
static bool nh_ctrl_api_payload_decode_cb(pb_istream_t *stream, const pb_field_t *field, void **arg) {
if (field->tag == CtrlMsg_resp_get_mac_address_tag) {
CtrlMsg_Resp_GetMacAddress *sub_msg = field->pData;
sub_msg->mac.funcs.decode = nh_ctrl_api_bytes_decode_cb;
sub_msg->mac.arg = *arg;
}
return true;
}

View File

@ -1,4 +1,4 @@
#include "nh_event_helpers.h"
#include "nh_helper_event.h"
/**
* Espressif wraps Tag-Length-Value(TLV) data in the packet for events

96
src/nh_helper_serial.c Normal file
View File

@ -0,0 +1,96 @@
#include "nh_helper_serial.h"
#include <string.h>
#define SERIAL_EP_NAME(x) (nh_serial_ep_names[x])
#define SERIAL_EP_SIZE(x) (strlen(nh_serial_ep_names[x]))
static const char *nh_serial_ep_names[] = {
[NH_SERIAL_EP_RESP] = "ctrlResp",
[NH_SERIAL_EP_EVENT] = "ctrlEvnt",
};
/* In the SERIAL I/F, a different TLV is used:
* | 1 | 2 | N |
* | Tag | Length | Value |
* Each TLV contains 2 fields, "EP name" and "Data"
*/
nh_ret_t nh_serial_get_type(nh_serial_ep_type_t *type, uint8_t *buf) {
uint8_t tag = buf[0];
uint8_t length = (buf[2] << 8U) | buf[1];
char *value = (char *)&buf[3];
if (tag != NH_SERIAL_TAG_EP_NAME) {
return NH_RET_FAIL;
}
if (length == 0) {
return NH_RET_FAIL;
}
if (strncmp(value, SERIAL_EP_NAME(NH_SERIAL_EP_RESP), SERIAL_EP_SIZE(NH_SERIAL_EP_RESP)) == 0) {
*type = NH_SERIAL_EP_RESP;
return NH_RET_SUCCESS;
}
if (strncmp(value, SERIAL_EP_NAME(NH_SERIAL_EP_EVENT), SERIAL_EP_SIZE(NH_SERIAL_EP_EVENT)) == 0) {
*type = NH_SERIAL_EP_EVENT;
return NH_RET_SUCCESS;
}
return NH_RET_FAIL;
}
nh_ret_t nh_serial_get_payload(uint8_t *buf, uint8_t **payload, uint16_t *length) {
uint8_t name_tag = buf[0];
uint8_t name_len = (buf[2] << 8U) | buf[1];
uint16_t data_tag_offset = 3 + name_len;
uint8_t data_tag = buf[data_tag_offset];
uint16_t data_len = (buf[data_tag_offset + 2] << 8U) | buf[data_tag_offset + 1];
uint8_t *data_value = &buf[data_tag_offset + 3];
if (name_tag != NH_SERIAL_TAG_EP_NAME) {
return NH_RET_FAIL;
}
if (data_tag != NH_SERIAL_TAG_DATA) {
return NH_RET_FAIL;
}
*payload = data_value;
*length = data_len;
return NH_RET_SUCCESS;
}
nh_ret_t nh_serial_header_length(nh_serial_ep_type_t type, uint16_t *header_length) {
*header_length = (6 + SERIAL_EP_SIZE(type));
return NH_RET_SUCCESS;
}
nh_ret_t nh_serial_write_header(nh_serial_ep_type_t type, uint8_t *buf, uint16_t data_len, uint8_t **data_start) {
uint16_t name_len = SERIAL_EP_SIZE(type);
uint8_t *name_buf = &buf[3];
buf[0] = NH_SERIAL_TAG_EP_NAME;
buf[1] = name_len & 0xFFU;
buf[2] = (name_len >> 8U) & 0xFFU;
memcpy(name_buf, SERIAL_EP_NAME(type), name_len);
uint8_t data_tag_offset = 3 + name_len;
uint8_t *data_buf = &buf[data_tag_offset + 3];
buf[data_tag_offset] = NH_SERIAL_TAG_DATA;
buf[data_tag_offset + 1] = data_len & 0xFFU;
buf[data_tag_offset + 2] = (data_len >> 8U) & 0xFFU;
*data_start = data_buf;
return NH_RET_SUCCESS;
}

View File

@ -2,9 +2,10 @@
#include "string.h"
#define NH_XFER_REQ_TIMEOUT 5000
#define NH_XFER_MAX_SIZE 1600
#define NH_XFER_QUEUE_SIZE 1
#define NH_XFER_REQ_TIMEOUT 5000
#define NH_XFER_BLOCKING_TIMEOUT 500
#define NH_XFER_MAX_SIZE 1600
#define NH_XFER_QUEUE_SIZE 1
#ifdef __GNUC__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
@ -29,9 +30,9 @@ typedef enum {
} nh_xfer_priv_type_t;
typedef struct {
nh_xfer_type_t type;
uint8_t *buf;
uint32_t buf_len;
uint32_t type;
uint8_t *buf;
uint32_t buf_len;
} nh_xfer_queue_item_t;
typedef struct __attribute__((packed)) {
@ -76,7 +77,7 @@ nh_ret_t nh_shared_if_init(nh_shared_if_t *shared_if) {
goto err_free_queue_tx;
}
ret = shared_if->osa->queue_create(shared_if->osa->user_data, &shared_if->p_queue_rx_ctrl,
ret = shared_if->osa->queue_create(shared_if->osa->user_data, &shared_if->p_queue_rx_serial,
sizeof(nh_xfer_queue_item_t), NH_XFER_QUEUE_SIZE);
if (ret != NH_RET_SUCCESS) {
goto err_free_queue_rx_data;
@ -98,7 +99,7 @@ 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);
shared_if->osa->queue_destroy(shared_if->osa->user_data, shared_if->p_queue_rx_serial);
err_free_queue_rx_data:
shared_if->osa->queue_destroy(shared_if->osa->user_data, shared_if->p_queue_rx_data);
@ -116,19 +117,28 @@ 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 nh_shared_if_serial_if_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;
uint16_t header_len;
nh_serial_header_length(NH_SERIAL_EP_RESP, &header_len);
nh_xfer_queue_item_t item = {
.type = NH_SHARED_IF_TYPE_SERIAL,
.buf_len = len,
.buf_len = len + header_len,
};
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &item.buf, len);
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &item.buf, item.buf_len);
if (ret != NH_RET_SUCCESS) {
return ret;
}
uint8_t *data_start;
nh_serial_write_header(NH_SERIAL_EP_RESP, item.buf, len, &data_start);
memcpy(data_start, tx_payload, len);
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);
@ -136,26 +146,29 @@ nh_ret_t nh_shared_if_ctrl_send(nh_shared_if_t *shared_if, uint8_t *tx_payload,
return ret;
}
ret = shared_if->osa->sem_give(shared_if->osa->user_data, shared_if->p_semaphore_xfer_req);
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 nh_shared_if_serial_if_recv(nh_shared_if_t *shared_if, nh_serial_ep_type_t *ep_type, 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);
ret = shared_if->osa->queue_dequeue(shared_if->osa->user_data, shared_if->p_queue_rx_serial, &item, timeout_ms);
if (ret != NH_RET_SUCCESS) {
return ret;
}
*rx_payload = item.buf;
*len = item.buf_len;
*ep_type = item.type;
return ret;
}
nh_ret_t nh_shared_if_ctrl_free(nh_shared_if_t *shared_if, uint8_t *rx_payload) {
nh_ret_t nh_shared_if_serial_if_free(nh_shared_if_t *shared_if, uint8_t *rx_payload) {
return shared_if->osa->buf_free(shared_if->osa->user_data, rx_payload);
}
@ -191,14 +204,15 @@ void nh_shared_if_task(nh_shared_if_t *shared_if) {
/* 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));
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);
/* Copy payload */
memcpy(&shared_if->p_buf_frame_tx[sizeof(nh_xfer_pkt_hdr_t)], item.buf, item.buf_len);
hdr->checksum = H_TO_LE16(nh_shared_if_checksum_calculate(hdr));
/* Queue consumer owns the buffer. */
shared_if->osa->buf_free(shared_if->osa->user_data, item.buf);
}
@ -261,10 +275,30 @@ static void nh_shared_if_dispatch_if_priv(nh_shared_if_t *shared_if, nh_xfer_pri
static void nh_shared_if_dispatch_if_serial(nh_shared_if_t *shared_if, uint8_t *payload, uint16_t len) {
nh_ret_t ret = NH_RET_SUCCESS;
/* Payload in SERIAL interface has two types, coded in TLV, event and response.
* Both payloads are wrapped in protobuf, so we don't need to distinguish them.
* Pass them to upper layer (CTRL).
*/
uint8_t *ctrl_data;
uint16_t ctrl_data_len;
nh_serial_ep_type_t ep_type;
ret = nh_serial_get_type(&ep_type, payload);
if (ret != NH_RET_SUCCESS) {
return;
}
/* Try to find data and length from TLV */
ret = nh_serial_get_payload(payload, &ctrl_data, &ctrl_data_len);
if (ret != NH_RET_SUCCESS) {
return;
}
nh_xfer_queue_item_t item;
item.type = NH_SHARED_IF_TYPE_SERIAL;
item.buf_len = len;
item.type = ep_type;
item.buf_len = ctrl_data_len;
/* Allocate payload */
ret = shared_if->osa->buf_allocate(shared_if->osa->user_data, &item.buf, item.buf_len);
@ -272,10 +306,11 @@ static void nh_shared_if_dispatch_if_serial(nh_shared_if_t *shared_if, uint8_t *
return;
}
memcpy(item.buf, payload, item.buf_len);
memcpy(item.buf, ctrl_data, item.buf_len);
/* Enqueue response */
ret = shared_if->osa->queue_enqueue(shared_if->osa->user_data, shared_if->p_queue_rx_ctrl, &item, 0);
ret = shared_if->osa->queue_enqueue(shared_if->osa->user_data, shared_if->p_queue_rx_serial, &item,
NH_XFER_BLOCKING_TIMEOUT);
if (ret != NH_RET_SUCCESS) {
/* Queue is full, maybe the ctrl interface is not active, drop the packet */
shared_if->osa->buf_free(shared_if->osa->user_data, item.buf);
@ -285,9 +320,9 @@ static void nh_shared_if_dispatch_if_serial(nh_shared_if_t *shared_if, uint8_t *
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);
uint16_t checksum_end = sizeof(nh_xfer_pkt_hdr_t) + LE16_TO_H(hdr->len);
for (size_t i = 0; i < checksum_length; i++) {
for (uint16_t i = 0; i < checksum_end; i++) {
checksum += ((uint8_t *)hdr)[i];
}