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 ## Issues
Who owns the buffers? How many buffers should we allocate? * Only a subset of commands are implemented.
* Jumbo frames (larger than 1518 bytes) are not supported, since no `realloc` available.
* Minimize the memory block operations (malloc and free) * Just hope ESP won't send some frame larger than that.
* 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
## License ## License
Not decided yet, please be patient. At least not before the project is usable. 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" #include "nh_shared_if.h"
#define NH_CTRL_API_MAC_LENGTH 17
typedef enum { typedef enum {
NH_CTRL_WIFI_MODE_NONE, NH_CTRL_WIFI_MODE_NONE,
NH_CTRL_WIFI_MODE_STA, NH_CTRL_WIFI_MODE_STA,
@ -11,26 +13,45 @@ typedef enum {
} nh_ctrl_wifi_mode_t; } nh_ctrl_wifi_mode_t;
typedef enum { typedef enum {
NH_CTRL_WIFI_ENC_MODE_OPEN, NH_CTRL_API_ENC_MODE_OPEN,
NH_CTRL_WIFI_ENC_MODE_WEP, NH_CTRL_API_ENC_MODE_WEP,
NH_CTRL_WIFI_ENC_MODE_WPA_PSK, NH_CTRL_API_ENC_MODE_WPA_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA2_PSK, NH_CTRL_API_ENC_MODE_WPA2_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA_WPA2_PSK, NH_CTRL_API_ENC_MODE_WPA_WPA2_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA2_ENT, NH_CTRL_API_ENC_MODE_WPA2_ENT,
NH_CTRL_WIFI_ENC_MODE_WPA3_PSK, NH_CTRL_API_ENC_MODE_WPA3_PSK,
NH_CTRL_WIFI_ENC_MODE_WPA2_WPA3_PSK, NH_CTRL_API_ENC_MODE_WPA2_WPA3_PSK,
} nh_ctrl_api_wifi_encryption_mode_t; } 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 { typedef struct {
char *ssid; char *ssid;
char *bssid; char *bssid;
int rssi; int rssi;
int channel; uint32_t channel;
nh_ctrl_api_wifi_encryption_mode_t encryption_mode; nh_ctrl_ap_enc_mode_t encryption_mode;
} nh_ctrl_api_wifi_scan_item_t; } 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 void (*nh_ctrl_api_event_cb_init_t)(void *handle);
typedef struct { typedef struct {
@ -53,5 +74,7 @@ typedef struct {
nh_ret_t nh_ctrl_api_init(nh_ctrl_api_t *api); nh_ret_t nh_ctrl_api_init(nh_ctrl_api_t *api);
void nh_ctrl_api_task(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_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 #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); 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; 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); 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'; 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); 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; 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++) {
for(uint32_t i = 0; i < rx_msg->resp_scan_ap_list->count; i++) { nh_ctrl_ap_scan_item_t item = {
nh_ctrl_api_wifi_scan_item_t item = { .rssi = rx_msg->resp_scan_ap_list->entries[i]->rssi,
.ssid = rx_msg->resp_scan_ap_list->entries[i]->ssid.data, .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: free_msg_exit:
@ -146,6 +176,59 @@ give_sem_exit:
return ret; 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) { void nh_ctrl_api_task(nh_ctrl_api_t *api) {
nh_ret_t ret = NH_RET_SUCCESS; nh_ret_t ret = NH_RET_SUCCESS;

View File

@ -51,6 +51,8 @@ typedef struct __attribute__((packed)) {
}; /* Offset: 0x0B */ }; /* Offset: 0x0B */
} nh_xfer_pkt_hdr_t; /* Size: 0x0C (12 bytes) */ } 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_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); 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_len = LE16_TO_H(hdr->len);
item.buf = &shared_if->p_buf_frame_rx[LE16_TO_H(hdr->offset)]; /* DO NOT FREE THIS!! */ 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) {
if (!item.buf_len) { return;
return; }
}
if (item.type == NH_SHARED_IF_TYPE_SERIAL) {
nh_shared_if_dispatch_if_serial(shared_if, item.buf, item.buf_len); nh_shared_if_dispatch_if_serial(shared_if, item.buf, item.buf_len);
} else if (item.type == NH_SHARED_IF_TYPE_PRIV) { } 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); 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) { 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) { if (type == NH_SHARED_IF_PRIV_TYPE_EVENT) {
/* Event is using PRIV interface. */ /* Event is using PRIV interface. */