Added scan and connect commands.

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-01-17 23:03:26 +08:00
parent 9add7e515b
commit 60a5a9fb07
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
4 changed files with 145 additions and 37 deletions

View File

@ -71,15 +71,9 @@ typedef enum {
## Issues
Who owns the buffers? How many buffers should we allocate?
* Minimize the memory block operations (malloc and free)
* Control plane and data plane can be async
* Control API can be blocking until responded
* At least 2 full-sized buffers are required (for full duplex operations)
* To re-use the bus while a request is underway, control plane and data plane RX buffers should be copied
* Bus TX operation should be blocking, however the previous RX data (if any) can be received.
* The response for the request being transmitted will never arrive within the same transaction
* Only a subset of commands are implemented.
* Jumbo frames (larger than 1518 bytes) are not supported, since no `realloc` available.
* Just hope ESP won't send some frame larger than that.
## License
Not decided yet, please be patient. At least not before the project is usable.

View File

@ -3,6 +3,8 @@
#include "nh_shared_if.h"
#define NH_CTRL_API_MAC_LENGTH 17
typedef enum {
NH_CTRL_WIFI_MODE_NONE,
NH_CTRL_WIFI_MODE_STA,
@ -11,26 +13,45 @@ typedef enum {
} 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;
NH_CTRL_API_ENC_MODE_OPEN,
NH_CTRL_API_ENC_MODE_WEP,
NH_CTRL_API_ENC_MODE_WPA_PSK,
NH_CTRL_API_ENC_MODE_WPA2_PSK,
NH_CTRL_API_ENC_MODE_WPA_WPA2_PSK,
NH_CTRL_API_ENC_MODE_WPA2_ENT,
NH_CTRL_API_ENC_MODE_WPA3_PSK,
NH_CTRL_API_ENC_MODE_WPA2_WPA3_PSK,
} nh_ctrl_ap_enc_mode_t;
typedef enum {
NH_CTRL_CONNECT_SUCCESS = 0x00U,
NH_CTRL_CONNECT_NO_AP_FOUND = 0x02U,
NH_CTRL_CONNECT_INVALID_PASSWORD = 0x03U,
NH_CTRL_CONNECT_FAILURE = 0xFFU,
} nh_ctrl_conn_status_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;
char *ssid;
char *bssid;
int rssi;
uint32_t channel;
nh_ctrl_ap_enc_mode_t encryption_mode;
} nh_ctrl_ap_scan_item_t;
typedef void (*nh_ctrl_api_ap_scan_list_cb_t)(void *handle, nh_ctrl_api_wifi_scan_item_t);
typedef struct {
char *ssid;
char *bssid;
char *password;
bool wpa3_supported;
int32_t listen_interval;
} nh_ctrl_ap_conn_params_t;
typedef struct {
nh_ctrl_conn_status_t status;
char *mac_addr;
} nh_ctrl_ap_conn_result_t;
typedef void (*nh_ctrl_api_ap_scan_list_cb_t)(void *handle, nh_ctrl_ap_scan_item_t *item);
typedef void (*nh_ctrl_api_event_cb_init_t)(void *handle);
typedef struct {
@ -53,5 +74,7 @@ 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_ctrl_wifi_mode_t mode);
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 nh_ctrl_api_connect_ap(nh_ctrl_api_t *api, nh_ctrl_ap_conn_params_t *params, nh_ctrl_ap_conn_result_t *result);
#endif // NH_CTRL_API_H

View File

@ -86,6 +86,9 @@ nh_ret_t nh_ctrl_api_get_mac_address(nh_ctrl_api_t *api, uint8_t *mac_addr, nh_c
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;
/* Sanity check */
if (rx_msg->resp_get_mac_address->mac.len != NH_CTRL_API_MAC_LENGTH) goto free_msg_exit;
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';
@ -127,11 +130,38 @@ nh_ret_t nh_ctrl_api_get_ap_scan_list(nh_ctrl_api_t *api, nh_ctrl_api_ap_scan_li
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,
for (uint32_t i = 0; i < rx_msg->resp_scan_ap_list->count; i++) {
nh_ctrl_ap_scan_item_t item = {
.rssi = rx_msg->resp_scan_ap_list->entries[i]->rssi,
.channel = rx_msg->resp_scan_ap_list->entries[i]->chnl,
.encryption_mode = (nh_ctrl_ap_enc_mode_t)rx_msg->resp_scan_ap_list->entries[i]->sec_prot,
};
uint32_t ssid_len = rx_msg->resp_scan_ap_list->entries[i]->ssid.len;
uint32_t bssid_len = rx_msg->resp_scan_ap_list->entries[i]->bssid.len;
ret = NH_CTRL_API_ALLOC(api, (uint8_t **)&item.ssid, ssid_len + 1);
if (ret != NH_RET_SUCCESS) goto free_msg_exit;
ret = NH_CTRL_API_ALLOC(api, (uint8_t **)&item.bssid, bssid_len + 1);
if (ret != NH_RET_SUCCESS) {
NH_CTRL_API_FREE(api, (uint8_t *)item.ssid);
goto free_msg_exit;
}
memcpy(item.ssid, rx_msg->resp_scan_ap_list->entries[i]->ssid.data, ssid_len);
memcpy(item.bssid, rx_msg->resp_scan_ap_list->entries[i]->bssid.data, bssid_len);
item.ssid[ssid_len] = '\0';
item.bssid[bssid_len] = '\0';
if (cb) {
cb(api->user_data, &item);
}
NH_CTRL_API_FREE(api, (uint8_t *)item.ssid);
NH_CTRL_API_FREE(api, (uint8_t *)item.bssid);
}
free_msg_exit:
@ -146,6 +176,59 @@ give_sem_exit:
return ret;
}
nh_ret_t nh_ctrl_api_connect_ap(nh_ctrl_api_t *api, nh_ctrl_ap_conn_params_t *params,
nh_ctrl_ap_conn_result_t *result) {
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_ConnectAP;
tx_msg.payload_case = CTRL_MSG__PAYLOAD_REQ_CONNECT_AP;
ret = NH_CTRL_API_ALLOC(api, (uint8_t **)&tx_msg.req_connect_ap, sizeof(CtrlMsgReqConnectAP));
if (ret != NH_RET_SUCCESS) goto give_sem_exit;
ctrl_msg__req__connect_ap__init(tx_msg.req_connect_ap);
tx_msg.req_connect_ap->ssid = params->ssid;
tx_msg.req_connect_ap->bssid = params->bssid;
tx_msg.req_connect_ap->pwd = params->password;
tx_msg.req_connect_ap->is_wpa3_supported = params->wpa3_supported;
tx_msg.req_connect_ap->listen_interval = params->listen_interval;
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_ConnectAP) goto free_msg_exit;
uint32_t mac_len = rx_msg->resp_connect_ap->mac.len;
if (mac_len != NH_CTRL_API_MAC_LENGTH) goto free_msg_exit;
memcpy(result->mac_addr, rx_msg->resp_connect_ap->mac.data, mac_len);
result->mac_addr[mac_len] = '\0';
result->status = (nh_ctrl_conn_status_t)rx_msg->resp_connect_ap->resp;
free_msg_exit:
ctrl_msg__free_unpacked(rx_msg, &c_alloc);
free_payload_exit:
NH_CTRL_API_FREE(api, (uint8_t *)tx_msg.req_connect_ap);
give_sem_exit:
NH_CTRL_API_GIVE_SEM(api);
return ret;
}
void nh_ctrl_api_task(nh_ctrl_api_t *api) {
nh_ret_t ret = NH_RET_SUCCESS;

View File

@ -51,6 +51,8 @@ typedef struct __attribute__((packed)) {
}; /* Offset: 0x0B */
} nh_xfer_pkt_hdr_t; /* Size: 0x0C (12 bytes) */
static void nh_shared_if_dispatch_sta(nh_shared_if_t *shared_if, uint8_t *payload, uint16_t len);
static void nh_shared_if_dispatch_ap(nh_shared_if_t *shared_if, uint8_t *payload, uint16_t len);
static void nh_shared_if_dispatch_if_serial(nh_shared_if_t *shared_if, uint8_t *payload, uint16_t len);
static void nh_shared_if_dispatch_if_priv(nh_shared_if_t *shared_if, nh_xfer_priv_type_t type, uint8_t *payload);
@ -243,22 +245,28 @@ void nh_shared_if_task(nh_shared_if_t *shared_if) {
item.buf_len = LE16_TO_H(hdr->len);
item.buf = &shared_if->p_buf_frame_rx[LE16_TO_H(hdr->offset)]; /* DO NOT FREE THIS!! */
if (item.type == NH_SHARED_IF_TYPE_SERIAL) {
if (!item.buf_len) {
return;
}
if (!item.buf_len) {
return;
}
if (item.type == NH_SHARED_IF_TYPE_SERIAL) {
nh_shared_if_dispatch_if_serial(shared_if, item.buf, item.buf_len);
} else if (item.type == NH_SHARED_IF_TYPE_PRIV) {
if (!item.buf_len) {
return;
}
nh_shared_if_dispatch_if_priv(shared_if, hdr->priv_pkt_type, item.buf);
} else if (item.type == NH_SHARED_IF_TYPE_STA) {
nh_shared_if_dispatch_sta(shared_if, item.buf, item.buf_len);
} else if(item.type == NH_SHARED_IF_TYPE_AP) {
nh_shared_if_dispatch_ap(shared_if, item.buf, item.buf_len);
}
}
}
static void nh_shared_if_dispatch_sta(nh_shared_if_t *shared_if, uint8_t *payload, uint16_t len) {
}
static void nh_shared_if_dispatch_ap(nh_shared_if_t *shared_if, uint8_t *payload, uint16_t len) {
}
static void nh_shared_if_dispatch_if_priv(nh_shared_if_t *shared_if, nh_xfer_priv_type_t type, uint8_t *payload) {
if (type == NH_SHARED_IF_PRIV_TYPE_EVENT) {
/* Event is using PRIV interface. */