diff --git a/include/nh_ctrl_api.h b/include/nh_ctrl_api.h index 6ed1c76..78a8da5 100644 --- a/include/nh_ctrl_api.h +++ b/include/nh_ctrl_api.h @@ -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 diff --git a/include/nh_shared_if.h b/include/nh_shared_if.h index 781db2f..61e6490 100644 --- a/include/nh_shared_if.h +++ b/include/nh_shared_if.h @@ -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 { diff --git a/src/nh_ctrl_api.c b/src/nh_ctrl_api.c index 8fc1eba..f972ea1 100644 --- a/src/nh_ctrl_api.c +++ b/src/nh_ctrl_api.c @@ -1,6 +1,7 @@ +#include + /* 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); +} \ No newline at end of file diff --git a/src/nh_shared_if.c b/src/nh_shared_if.c index c3546d9..a96d6ca 100644 --- a/src/nh_shared_if.c +++ b/src/nh_shared_if.c @@ -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 */