205 lines
5.7 KiB
C
205 lines
5.7 KiB
C
/* Private */
|
|
#include "nh_ctrl_api.h"
|
|
|
|
#include "protobuf-c/protobuf-c.h"
|
|
|
|
/* PB config */
|
|
#include "esp_hosted_config.pb-c.h"
|
|
|
|
#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;
|
|
|
|
ret = nh_ctrl_api_general_request(api, &tx_msg);
|
|
if (ret != NH_RET_SUCCESS) {
|
|
goto give_sem_exit;
|
|
}
|
|
|
|
CtrlMsg rx_msg;
|
|
|
|
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 *payload;
|
|
uint32_t payload_size;
|
|
nh_serial_ep_type_t ep_type;
|
|
|
|
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;
|
|
}
|
|
|
|
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 CTRL_MSG_ID__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;
|
|
}
|