Use protobuf-c instead of nanopb

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-01-14 18:37:22 +08:00
parent 59d47eb342
commit 9add7e515b
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
4 changed files with 161 additions and 56 deletions

View File

@ -3,6 +3,34 @@
#include "nh_shared_if.h"
typedef enum {
NH_CTRL_WIFI_MODE_NONE,
NH_CTRL_WIFI_MODE_STA,
NH_CTRL_WIFI_MODE_AP,
NH_CTRL_WIFI_MODE_APSTA,
} nh_ctrl_wifi_mode_t;
typedef enum {
NH_CTRL_WIFI_ENC_MODE_OPEN,
NH_CTRL_WIFI_ENC_MODE_WEP,
NH_CTRL_WIFI_ENC_MODE_WPA_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA2_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA_WPA2_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA2_ENT,
NH_CTRL_WIFI_ENC_MODE_WPA3_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA2_WPA3_PSK,
} nh_ctrl_api_wifi_encryption_mode_t;
typedef struct {
char *ssid;
char *bssid;
int rssi;
int channel;
nh_ctrl_api_wifi_encryption_mode_t encryption_mode;
} nh_ctrl_api_wifi_scan_item_t;
typedef void (*nh_ctrl_api_ap_scan_list_cb_t)(void *handle, nh_ctrl_api_wifi_scan_item_t);
typedef void (*nh_ctrl_api_event_cb_init_t)(void *handle);
typedef struct {
@ -24,6 +52,6 @@ typedef struct {
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);
nh_ret_t nh_ctrl_api_get_mac_address(nh_ctrl_api_t *api, uint8_t *mac_addr, nh_ctrl_wifi_mode_t mode);
#endif // NH_CTRL_API_H

View File

@ -9,6 +9,7 @@
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_drdy_read_t)(void *handle, bool *rdy);
typedef nh_ret_t (*nh_shared_if_ops_hs_poll_t)(void *handle, uint32_t timeout_ms);
/* Event callbacks */
typedef void (*nh_shared_if_cb_event_init_t)(void *handle, nh_event_init_t *init_event);
@ -17,6 +18,7 @@ typedef struct {
nh_shared_if_ops_spi_xfer_t xfer;
nh_shared_if_ops_reset_t reset;
nh_shared_if_ops_drdy_read_t drdy_read;
nh_shared_if_ops_hs_poll_t hs_poll;
} nh_shared_if_ops_t;
typedef struct {

View File

@ -1,6 +1,7 @@
#include <string.h>
/* Private */
#include "nh_ctrl_api.h"
#include "protobuf-c/protobuf-c.h"
/* PB config */
@ -9,12 +10,24 @@
#define NH_COMMAND_TIMEOUT_MSEC 30000
#define NH_COMMAND_REQ_MEM_SIZE 256
#define NH_CTRL_API_CREATE_ALLOCATOR(allocator_name) \
ProtobufCAllocator allocator_name = { \
.alloc = nh_ctrl_api_protobuf_allocate, \
.free = nh_ctrl_api_protobuf_free, \
.allocator_data = api, \
}
#define NH_CTRL_API_TAKE_SEM(s_api, timeout) s_api->osa->sem_take(s_api->osa->user_data, s_api->p_sem_req, timeout)
#define NH_CTRL_API_GIVE_SEM(s_api) s_api->osa->sem_give(api->osa->user_data, api->p_sem_req)
#define NH_CTRL_API_ALLOC(s_api, ptr, p_size) s_api->osa->buf_allocate(s_api->osa->user_data, ptr, p_size)
#define NH_CTRL_API_FREE(s_api, ptr) s_api->osa->buf_free(s_api->osa->user_data, ptr)
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);
static nh_ret_t nh_ctrl_api_general_response(nh_ctrl_api_t *api, CtrlMsg **rx_msg, ProtobufCAllocator *allocator);
static void *nh_ctrl_api_protobuf_allocate(void *handle, size_t size);
static void nh_ctrl_api_protobuf_free(void *handle, void *data);
nh_ret_t nh_ctrl_api_init(nh_ctrl_api_t *api) {
nh_ret_t ret = NH_RET_SUCCESS;
@ -45,32 +58,90 @@ free_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 nh_ctrl_api_get_mac_address(nh_ctrl_api_t *api, uint8_t *mac_addr, nh_ctrl_wifi_mode_t mode) {
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;
}
NH_CTRL_API_CREATE_ALLOCATOR(c_alloc);
ret = NH_CTRL_API_TAKE_SEM(api, NH_COMMAND_TIMEOUT_MSEC);
if (ret != NH_RET_SUCCESS) return ret;
CtrlMsg tx_msg;
ctrl_msg__init(&tx_msg);
tx_msg.msg_id = CTRL_MSG_ID__Req_GetMACAddress;
tx_msg.payload_case = CTRL_MSG__PAYLOAD_REQ_GET_MAC_ADDRESS;
ret = NH_CTRL_API_ALLOC(api, (uint8_t **)&tx_msg.req_get_mac_address, sizeof(CtrlMsgReqGetMacAddress));
if (ret != NH_RET_SUCCESS) goto give_sem_exit;
ctrl_msg__req__get_mac_address__init(tx_msg.req_get_mac_address);
tx_msg.req_get_mac_address->mode = (mode == NH_CTRL_WIFI_MODE_AP) ? CTRL__WIFI_MODE__AP : CTRL__WIFI_MODE__STA;
ret = nh_ctrl_api_general_request(api, &tx_msg);
if (ret != NH_RET_SUCCESS) {
goto give_sem_exit;
}
if (ret != NH_RET_SUCCESS) goto free_payload_exit;
CtrlMsg rx_msg;
CtrlMsg *rx_msg;
ret = nh_ctrl_api_general_response(api, &rx_msg);
if (ret != NH_RET_SUCCESS) {
goto give_sem_exit;
}
ret = nh_ctrl_api_general_response(api, &rx_msg, &c_alloc);
if (ret != NH_RET_SUCCESS || rx_msg->msg_id != CTRL_MSG_ID__Resp_GetMACAddress) goto free_msg_exit;
nh_ctrl_api_general_response_free(api);
memcpy(mac_addr, rx_msg->resp_get_mac_address->mac.data, rx_msg->resp_get_mac_address->mac.len);
mac_addr[rx_msg->resp_get_mac_address->mac.len] = '\0';
free_msg_exit:
ctrl_msg__free_unpacked(rx_msg, &c_alloc);
free_payload_exit:
NH_CTRL_API_FREE(api, (uint8_t *)tx_msg.req_get_mac_address);
give_sem_exit:
api->osa->sem_give(api->osa->user_data, api->p_sem_req);
NH_CTRL_API_GIVE_SEM(api);
return ret;
}
nh_ret_t nh_ctrl_api_get_ap_scan_list(nh_ctrl_api_t *api, nh_ctrl_api_ap_scan_list_cb_t cb) {
nh_ret_t ret = NH_RET_SUCCESS;
NH_CTRL_API_CREATE_ALLOCATOR(c_alloc);
ret = NH_CTRL_API_TAKE_SEM(api, NH_COMMAND_TIMEOUT_MSEC);
if (ret != NH_RET_SUCCESS) return ret;
CtrlMsg tx_msg;
ctrl_msg__init(&tx_msg);
tx_msg.msg_id = CTRL_MSG_ID__Req_GetAPScanList;
tx_msg.payload_case = CTRL_MSG__PAYLOAD_REQ_SCAN_AP_LIST;
ret = NH_CTRL_API_ALLOC(api, (uint8_t **)&tx_msg.req_scan_ap_list, sizeof(CtrlMsgReqScanResult));
if (ret != NH_RET_SUCCESS) goto give_sem_exit;
ctrl_msg__req__scan_result__init(tx_msg.req_scan_ap_list);
ret = nh_ctrl_api_general_request(api, &tx_msg);
if (ret != NH_RET_SUCCESS) goto free_payload_exit;
CtrlMsg *rx_msg;
ret = nh_ctrl_api_general_response(api, &rx_msg, &c_alloc);
if (ret != NH_RET_SUCCESS || rx_msg->msg_id != CTRL_MSG_ID__Resp_GetAPScanList) goto free_msg_exit;
for(uint32_t i = 0; i < rx_msg->resp_scan_ap_list->count; i++) {
nh_ctrl_api_wifi_scan_item_t item = {
.ssid = rx_msg->resp_scan_ap_list->entries[i]->ssid.data,
};
}
free_msg_exit:
ctrl_msg__free_unpacked(rx_msg, &c_alloc);
free_payload_exit:
NH_CTRL_API_FREE(api, (uint8_t *)tx_msg.req_get_mac_address);
give_sem_exit:
NH_CTRL_API_GIVE_SEM(api);
return ret;
}
@ -108,16 +179,16 @@ void nh_ctrl_api_task(nh_ctrl_api_t *api) {
}
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);
NH_CTRL_API_CREATE_ALLOCATOR(c_alloc);
CtrlMsg event_msg = CtrlMsg_init_zero;
if (!pb_decode(&stream, CtrlMsg_fields, &event_msg)) {
CtrlMsg *msg = ctrl_msg__unpack(&c_alloc, buf_len, buf);
if (msg == NULL) {
return NH_RET_FAIL;
}
*event_id = event_msg.msg_id;
*event_id = msg->msg_id;
ctrl_msg__free_unpacked(msg, &c_alloc);
return NH_RET_SUCCESS;
}
@ -139,28 +210,32 @@ 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) {
nh_ret_t ret = NH_RET_SUCCESS;
size_t packed_size = ctrl_msg__get_packed_size(tx_msg);
if (packed_size == 0) {
return NH_RET_FAIL;
}
uint8_t *req_buf;
ret = api->osa->buf_allocate(api->osa->user_data, &req_buf, NH_COMMAND_REQ_MEM_SIZE);
ret = NH_CTRL_API_ALLOC(api, &req_buf, packed_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: */
if (ctrl_msg__pack(tx_msg, req_buf) != packed_size) {
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);
ret = nh_shared_if_serial_if_send(api->shared_if, req_buf, packed_size, NH_COMMAND_TIMEOUT_MSEC);
free_tx_exit:
api->osa->buf_free(api->osa->user_data, req_buf);
NH_CTRL_API_FREE(api, req_buf);
return ret;
}
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(nh_ctrl_api_t *api, CtrlMsg **rx_msg, ProtobufCAllocator *allocator) {
nh_ret_t ret = NH_RET_SUCCESS;
ret = api->osa->sem_take(api->osa->user_data, api->p_sem_resp, NH_COMMAND_TIMEOUT_MSEC);
@ -168,37 +243,29 @@ static nh_ret_t nh_ctrl_api_general_response(nh_ctrl_api_t *api, CtrlMsg *rx_msg
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;
*rx_msg = ctrl_msg__unpack(allocator, api->p_buf_rx_len, api->p_buf_rx);
if (*rx_msg == NULL) {
ret = NH_RET_FAIL;
}
nh_shared_if_serial_if_free(api->shared_if, api->p_buf_rx);
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 void *nh_ctrl_api_protobuf_allocate(void *handle, size_t size) {
nh_ctrl_api_t *api = handle;
uint8_t *buf = NULL;
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);
if (NH_CTRL_API_ALLOC(api, &buf, size) != NH_RET_SUCCESS) {
return NULL;
}
return true;
return buf;
}
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;
static void nh_ctrl_api_protobuf_free(void *handle, void *data) {
nh_ctrl_api_t *api = handle;
sub_msg->mac.funcs.decode = nh_ctrl_api_bytes_decode_cb;
sub_msg->mac.arg = *arg;
}
return true;
}
NH_CTRL_API_FREE(api, data);
}

View File

@ -3,7 +3,7 @@
#include "string.h"
#define NH_XFER_REQ_TIMEOUT 5000
#define NH_XFER_BLOCKING_TIMEOUT 500
#define NH_XFER_BLOCKING_TIMEOUT 5000
#define NH_XFER_MAX_SIZE 1600
#define NH_XFER_QUEUE_SIZE 1
@ -185,6 +185,14 @@ void nh_shared_if_task(nh_shared_if_t *shared_if) {
* 2: Data ready pin is high when HS at rising, some data needs to be received
*/
ret = shared_if->ops.hs_poll(shared_if->user_data, NH_XFER_REQ_TIMEOUT);
if (ret != NH_RET_SUCCESS) {
/* HS is not ready, queue another transfer */
shared_if->osa->sem_give(shared_if->osa->user_data, shared_if->p_semaphore_xfer_req);
return;
}
bool rx_available = false;
/* Check if new data is available */