Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "SclSTAInterface.h"
|
||||
#include "nsapi.h"
|
||||
#include "lwipopts.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "rtos.h"
|
||||
#include "scl_emac.h"
|
||||
#include "scl_ipc.h"
|
||||
#include "mbed_wait_api.h"
|
||||
|
||||
|
||||
/** @file
|
||||
* Provides SCL interface functions to be used with WiFiInterface or NetworkInterface Objects
|
||||
*/
|
||||
#define MIN_SSID_LENGTH (0)
|
||||
#define MIN_PASSWORD_LENGTH (0)
|
||||
|
||||
struct scl_tx_net_credentials {
|
||||
nsapi_security_t network_security_type;
|
||||
int ssid_len;
|
||||
int pass_len;
|
||||
const char *network_ssid;
|
||||
const char *network_passphrase;
|
||||
} scl_tx_network_credentials;
|
||||
|
||||
network_params_t network_parameter;
|
||||
|
||||
int scl_toerror(scl_result_t res)
|
||||
{
|
||||
switch (res) {
|
||||
case SCL_SUCCESS:
|
||||
return NSAPI_ERROR_OK;
|
||||
case SCL_UNSUPPORTED:
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
case SCL_BADARG:
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
case SCL_INVALID_JOIN_STATUS:
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
case SCL_BUFFER_UNAVAILABLE_PERMANENT:
|
||||
case SCL_BUFFER_UNAVAILABLE_TEMPORARY:
|
||||
case SCL_RX_BUFFER_ALLOC_FAIL:
|
||||
case SCL_BUFFER_ALLOC_FAIL:
|
||||
case SCL_MALLOC_FAILURE:
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
case SCL_ACCESS_POINT_NOT_FOUND:
|
||||
case SCL_NETWORK_NOT_FOUND:
|
||||
return NSAPI_ERROR_NO_SSID;
|
||||
case SCL_NOT_AUTHENTICATED:
|
||||
case SCL_INVALID_KEY:
|
||||
case SCL_NOT_KEYED:
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
case SCL_PENDING:
|
||||
case SCL_JOIN_IN_PROGRESS:
|
||||
return NSAPI_ERROR_IN_PROGRESS;
|
||||
case SCL_CONNECTION_LOST:
|
||||
return NSAPI_ERROR_CONNECTION_LOST;
|
||||
case SCL_TIMEOUT:
|
||||
case SCL_EAPOL_KEY_PACKET_M1_TIMEOUT:
|
||||
case SCL_EAPOL_KEY_PACKET_M3_TIMEOUT:
|
||||
case SCL_EAPOL_KEY_PACKET_G1_TIMEOUT:
|
||||
return NSAPI_ERROR_CONNECTION_TIMEOUT;
|
||||
default:
|
||||
return -res;
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_security_t scl_tosecurity(scl_security_t sec)
|
||||
{
|
||||
switch (sec) {
|
||||
case SCL_SECURITY_OPEN:
|
||||
return NSAPI_SECURITY_NONE;
|
||||
case SCL_SECURITY_WEP_PSK:
|
||||
case SCL_SECURITY_WEP_SHARED:
|
||||
return NSAPI_SECURITY_WEP;
|
||||
case SCL_SECURITY_WPA_TKIP_PSK:
|
||||
case SCL_SECURITY_WPA_TKIP_ENT:
|
||||
return NSAPI_SECURITY_WPA;
|
||||
case SCL_SECURITY_WPA2_MIXED_PSK:
|
||||
return NSAPI_SECURITY_WPA_WPA2;
|
||||
case SCL_SECURITY_WPA2_AES_PSK:
|
||||
case SCL_SECURITY_WPA2_AES_ENT:
|
||||
case SCL_SECURITY_WPA2_FBT_PSK:
|
||||
case SCL_SECURITY_WPA2_FBT_ENT:
|
||||
return NSAPI_SECURITY_WPA2;
|
||||
default:
|
||||
return NSAPI_SECURITY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
scl_security_t scl_fromsecurity(nsapi_security_t sec)
|
||||
{
|
||||
switch (sec) {
|
||||
case NSAPI_SECURITY_NONE:
|
||||
return SCL_SECURITY_OPEN;
|
||||
case NSAPI_SECURITY_WEP:
|
||||
return SCL_SECURITY_WEP_PSK;
|
||||
case NSAPI_SECURITY_WPA:
|
||||
return SCL_SECURITY_WPA_MIXED_PSK;
|
||||
case NSAPI_SECURITY_WPA2:
|
||||
return SCL_SECURITY_WPA2_AES_PSK;
|
||||
case NSAPI_SECURITY_WPA_WPA2:
|
||||
return SCL_SECURITY_WPA2_MIXED_PSK;
|
||||
default:
|
||||
return SCL_SECURITY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
SclSTAInterface::SclSTAInterface(SCL_EMAC &emac, OnboardNetworkStack &stack)
|
||||
: EMACInterface(emac, stack),
|
||||
_ssid("\0"),
|
||||
_pass("\0"),
|
||||
_security(NSAPI_SECURITY_NONE),
|
||||
_scl_emac(emac)
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t SclSTAInterface::connect(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel)
|
||||
{
|
||||
int err = set_channel(channel);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = set_credentials(ssid, pass, security);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return connect();
|
||||
}
|
||||
|
||||
nsapi_error_t SclSTAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
|
||||
{
|
||||
if ((ssid == NULL) ||
|
||||
(strlen(ssid) == 0) ||
|
||||
(pass == NULL && (security != NSAPI_SECURITY_NONE)) ||
|
||||
(strlen(pass) == 0 && (security != NSAPI_SECURITY_NONE)) ||
|
||||
(strlen(pass) > 63 && (security == NSAPI_SECURITY_WPA2 || security == NSAPI_SECURITY_WPA || security == NSAPI_SECURITY_WPA_WPA2))
|
||||
) {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
memset(_ssid, 0, sizeof(_ssid));
|
||||
strncpy(_ssid, ssid, sizeof(_ssid));
|
||||
|
||||
memset(_pass, 0, sizeof(_pass));
|
||||
strncpy(_pass, pass, sizeof(_pass));
|
||||
|
||||
_security = security;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t SclSTAInterface::connect()
|
||||
{
|
||||
|
||||
uint32_t delay_timeout = 0;
|
||||
scl_result_t ret_val;
|
||||
nsapi_error_t interface_status;
|
||||
uint32_t connection_status = 0;
|
||||
|
||||
scl_tx_network_credentials.network_ssid = _ssid;
|
||||
if ((strlen(_ssid) < MAX_SSID_LENGTH) && (strlen(_ssid) > MIN_SSID_LENGTH)) {
|
||||
scl_tx_network_credentials.ssid_len = strlen(_ssid);
|
||||
} else {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
scl_tx_network_credentials.network_passphrase = _pass;
|
||||
if (((strlen(_pass) < MAX_PASSWORD_LENGTH) && (strlen(_pass) > MIN_PASSWORD_LENGTH)) || (_security == NSAPI_SECURITY_NONE)) {
|
||||
scl_tx_network_credentials.pass_len = strlen(_pass);
|
||||
} else {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
scl_tx_network_credentials.network_security_type = _security;
|
||||
|
||||
ret_val = scl_send_data(SCL_TX_CONNECT, (char *)&scl_tx_network_credentials, TIMER_DEFAULT_VALUE);
|
||||
|
||||
if (ret_val == SCL_SUCCESS) {
|
||||
SCL_LOG(("wifi provisioning in progress\r\n"));
|
||||
}
|
||||
|
||||
network_parameter.connection_status = NSAPI_STATUS_DISCONNECTED;
|
||||
|
||||
|
||||
//Get the network parameter from NP
|
||||
while ((network_parameter.connection_status != NSAPI_STATUS_GLOBAL_UP) && delay_timeout < NW_CONNECT_TIMEOUT) {
|
||||
ret_val = scl_get_nw_parameters(&network_parameter);
|
||||
wait_us(NW_DELAY_TIME_US);
|
||||
delay_timeout++;
|
||||
}
|
||||
|
||||
if (delay_timeout >= NW_CONNECT_TIMEOUT || ret_val != SCL_SUCCESS) {
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
|
||||
if (!_scl_emac.powered_up) {
|
||||
_scl_emac.power_up();
|
||||
}
|
||||
|
||||
if (!_interface) {
|
||||
nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_interface = NULL;
|
||||
return err;
|
||||
}
|
||||
_interface->attach(_connection_status_cb);
|
||||
}
|
||||
|
||||
if (!scl_wifi_is_ready_to_transceive()) {
|
||||
scl_emac_wifi_link_state_changed(true);
|
||||
}
|
||||
|
||||
interface_status = _interface->bringup(false,
|
||||
network_parameter.ip_address,
|
||||
network_parameter.netmask,
|
||||
network_parameter.gateway,
|
||||
DEFAULT_STACK);
|
||||
|
||||
if (interface_status == NSAPI_ERROR_OK) {
|
||||
scl_send_data(SCL_TX_CONNECTION_STATUS, (char *)&connection_status, TIMER_DEFAULT_VALUE);
|
||||
}
|
||||
|
||||
return interface_status;
|
||||
}
|
||||
|
||||
void SclSTAInterface::wifi_on()
|
||||
{
|
||||
if (!_scl_emac.powered_up) {
|
||||
_scl_emac.power_up();
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t SclSTAInterface::disconnect()
|
||||
{
|
||||
scl_result_t ret_val;
|
||||
nsapi_error_t disconnect_status;
|
||||
uint32_t delay_timeout = 0;
|
||||
|
||||
ret_val = scl_send_data(SCL_TX_DISCONNECT, (char *)&disconnect_status, TIMER_DEFAULT_VALUE);
|
||||
|
||||
if (ret_val == SCL_ERROR) {
|
||||
return NSAPI_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (!_interface) {
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
|
||||
// block till disconnected from network
|
||||
while ((network_parameter.connection_status != NSAPI_STATUS_DISCONNECTED) && delay_timeout < NW_DISCONNECT_TIMEOUT) {
|
||||
ret_val = scl_get_nw_parameters(&network_parameter);
|
||||
wait_us(NW_DELAY_TIME_US);
|
||||
delay_timeout++;
|
||||
}
|
||||
|
||||
if (delay_timeout >= NW_DISCONNECT_TIMEOUT) {
|
||||
return NSAPI_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
// bring down
|
||||
int err = _interface->bringdown();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
scl_emac_wifi_link_state_changed(false);
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
int SclSTAInterface::scan(WiFiAccessPoint *res, unsigned count)
|
||||
{
|
||||
/* To Do */
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int8_t SclSTAInterface::get_rssi()
|
||||
{
|
||||
int32_t rssi;
|
||||
scl_result_t res;
|
||||
|
||||
if (!_scl_emac.powered_up) {
|
||||
_scl_emac.power_up();
|
||||
}
|
||||
|
||||
res = (scl_result_t) scl_wifi_get_rssi(&rssi);
|
||||
if (res == SCL_ERROR) {
|
||||
return SCL_ERROR;
|
||||
}
|
||||
|
||||
return (int8_t)rssi;
|
||||
}
|
||||
|
||||
int SclSTAInterface::is_interface_connected(void)
|
||||
{
|
||||
if (scl_wifi_is_ready_to_transceive() == SCL_SUCCESS) {
|
||||
return SCL_SUCCESS;
|
||||
} else {
|
||||
return SCL_CONNECTION_LOST;
|
||||
}
|
||||
}
|
||||
|
||||
int SclSTAInterface::get_bssid(uint8_t *bssid)
|
||||
{
|
||||
scl_mac_t ap_mac;
|
||||
scl_result_t res = SCL_SUCCESS;
|
||||
|
||||
if (bssid == NULL) {
|
||||
return SCL_BADARG;
|
||||
}
|
||||
|
||||
memset(&ap_mac, 0, sizeof(ap_mac));
|
||||
if (scl_wifi_is_ready_to_transceive() == SCL_SUCCESS) {
|
||||
res = (scl_result_t) scl_wifi_get_bssid(&ap_mac);
|
||||
if (res == SCL_SUCCESS) {
|
||||
memcpy(bssid, ap_mac.octet, sizeof(ap_mac.octet));
|
||||
}
|
||||
} else {
|
||||
return SCL_CONNECTION_LOST;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int SclSTAInterface::wifi_set_up(void)
|
||||
{
|
||||
int res = SCL_SUCCESS;
|
||||
res = scl_wifi_set_up();
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SCL_STA_INTERFACE_H
|
||||
#define SCL_STA_INTERFACE_H
|
||||
|
||||
|
||||
/** @file
|
||||
* Provides SCL interface functions to be used with WiFiInterface or NetworkInterface Objects
|
||||
*/
|
||||
|
||||
#include "netsocket/WiFiInterface.h"
|
||||
#include "netsocket/EMACInterface.h"
|
||||
#include "netsocket/OnboardNetworkStack.h"
|
||||
#include "scl_emac.h"
|
||||
#include "scl_wifi_api.h"
|
||||
#include "scl_types.h"
|
||||
#define MAX_SSID_LENGTH (33) /**< Maximum ssid length */
|
||||
#define MAX_PASSWORD_LENGTH (64) /**< Maximum password length */
|
||||
|
||||
/** SclSTAInterface class
|
||||
* Implementation of the Network Stack for the SCL
|
||||
*/
|
||||
class SclSTAInterface : public WiFiInterface, public EMACInterface {
|
||||
public:
|
||||
|
||||
SclSTAInterface(
|
||||
SCL_EMAC &emac = SCL_EMAC::get_instance(),
|
||||
OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance());
|
||||
|
||||
/** Gets the current instance of the SclSTAInterface
|
||||
*
|
||||
* @return Pointer to the object of class SclSTAInterface.
|
||||
*/
|
||||
static SclSTAInterface *get_default_instance();
|
||||
|
||||
/** Turns on the Wi-Fi device
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void wifi_on();
|
||||
|
||||
/** Starts the interface
|
||||
*
|
||||
* Attempts to connect to a Wi-Fi network. Requires ssid and passphrase to be set.
|
||||
* If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
|
||||
*
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*/
|
||||
nsapi_error_t connect();
|
||||
|
||||
/** Starts the interface
|
||||
*
|
||||
* Attempts to connect to a Wi-Fi network.
|
||||
*
|
||||
* @param ssid Name of the network to connect to.
|
||||
* @param pass Security passphrase to connect to the network.
|
||||
* @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE).
|
||||
* @param channel This parameter is not supported, setting it to a value other than 0 will result in NSAPI_ERROR_UNSUPPORTED.
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*/
|
||||
nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0);
|
||||
|
||||
/** Disconnects the interface
|
||||
*
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*/
|
||||
nsapi_error_t disconnect();
|
||||
|
||||
/** Set the Wi-Fi network credentials
|
||||
*
|
||||
* @param ssid Name of the network to connect to.
|
||||
* @param pass Security passphrase to connect to the network.
|
||||
* @param security Type of encryption for connection.
|
||||
* (defaults to NSAPI_SECURITY_NONE)
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*/
|
||||
nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
|
||||
|
||||
/** Sets the Wi-Fi network channel - NOT SUPPORTED
|
||||
*
|
||||
* This function is not supported and will return NSAPI_ERROR_UNSUPPORTED.
|
||||
*
|
||||
* @param channel Channel on which the connection is to be made (Default: 0).
|
||||
* @return Not supported, returns NSAPI_ERROR_UNSUPPORTED.
|
||||
*/
|
||||
nsapi_error_t set_channel(uint8_t channel)
|
||||
{
|
||||
if (channel != 0) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Set blocking status of interface.
|
||||
* Nonblocking mode is not supported.
|
||||
*
|
||||
* @param blocking True if connect is blocking
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
nsapi_error_t set_blocking(bool blocking)
|
||||
{
|
||||
if (blocking) {
|
||||
_blocking = blocking;
|
||||
return NSAPI_ERROR_OK;
|
||||
} else {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
/** Gets the current radio signal strength for active connection
|
||||
*
|
||||
* @return Connection strength in dBm (negative value).
|
||||
*/
|
||||
int8_t get_rssi();
|
||||
|
||||
/** Scans for available networks - NOT SUPPORTED
|
||||
*
|
||||
* @return NSAPI_ERROR_UNSUPPORTED
|
||||
*/
|
||||
int scan(WiFiAccessPoint *res, unsigned count);
|
||||
|
||||
/** This function is used to indicate if the device is connected to the network.
|
||||
*
|
||||
* @return SCL_SUCCESS if device is connected.
|
||||
*/
|
||||
int is_interface_connected();
|
||||
|
||||
/** Gets the BSSID (MAC address of device connected to).
|
||||
*
|
||||
* @param bssid Pointer to the BSSID value.
|
||||
* @return SCL_SUCCESS if BSSID is obtained successfully.
|
||||
* @return SCL_BADARG if input parameter is NULL.
|
||||
* @return SCL_ERROR if unable to fetch BSSID.
|
||||
*/
|
||||
int get_bssid(uint8_t *bssid);
|
||||
|
||||
/** This function is used to set up the Wi-Fi interface.
|
||||
* This function should be used after the wifi_on.
|
||||
*
|
||||
* @return SCL_SUCCESS if the Wi-Fi interface is set up successfully.
|
||||
*/
|
||||
int wifi_set_up(void);
|
||||
|
||||
private:
|
||||
|
||||
char _ssid[MAX_SSID_LENGTH]; /**< The longest possible name (defined in 802.11) +1 for the \0 */
|
||||
char _pass[MAX_PASSWORD_LENGTH]; /**< The longest allowed passphrase + 1 */
|
||||
nsapi_security_t _security; /**< Security type */
|
||||
SCL_EMAC &_scl_emac; /**< SCL_EMAC object */
|
||||
};
|
||||
#endif /* ifndef SCL_STA_INTERFACE_H */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "SclSTAInterface.h"
|
||||
|
||||
/** @file
|
||||
* Provides function definition to override get_target_default_intance of WiFiInterface and NetworkInterface classes
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the WiFiInterface Object
|
||||
* This function can be called using WiFiInterface or NetworkInterface objects
|
||||
*
|
||||
* @return pointer to WiFiInterface object.
|
||||
*/
|
||||
|
||||
WiFiInterface *WiFiInterface::get_target_default_instance()
|
||||
{
|
||||
static SclSTAInterface wifi;
|
||||
return &wifi;
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cmsis_os.h"
|
||||
#include "scl_emac.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "events/mbed_shared_queues.h"
|
||||
#include "scl_buffer_api.h"
|
||||
#include "cy_result.h"
|
||||
#include "cy_pdl.h"
|
||||
#include "scl_ipc.h"
|
||||
|
||||
/** @file
|
||||
* Provides EMAC interface functions to be used with the SCL_EMAC object
|
||||
*/
|
||||
|
||||
SCL_EMAC::SCL_EMAC(scl_interface_role_t role)
|
||||
: interface_type(role)
|
||||
{
|
||||
}
|
||||
|
||||
SCL_EMAC::SCL_EMAC()
|
||||
: interface_type(SCL_STA_ROLE)
|
||||
{
|
||||
}
|
||||
|
||||
SCL_EMAC &SCL_EMAC::get_instance()
|
||||
{
|
||||
return get_instance(SCL_STA_ROLE);
|
||||
}
|
||||
|
||||
SCL_EMAC &SCL_EMAC::get_instance(scl_interface_role_t role)
|
||||
{
|
||||
static SCL_EMAC emac_sta(SCL_STA_ROLE);
|
||||
static SCL_EMAC emac_ap(SCL_AP_ROLE);
|
||||
return role == SCL_AP_ROLE ? emac_ap : emac_sta;
|
||||
}
|
||||
|
||||
uint32_t SCL_EMAC::get_mtu_size() const
|
||||
{
|
||||
return SCL_PAYLOAD_MTU;
|
||||
}
|
||||
|
||||
uint32_t SCL_EMAC::get_align_preference() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SCL_EMAC::add_multicast_group(const uint8_t *addr)
|
||||
{
|
||||
memcpy(multicast_addr.octet, addr, sizeof(multicast_addr.octet));
|
||||
scl_wifi_register_multicast_address(&multicast_addr);
|
||||
}
|
||||
|
||||
void SCL_EMAC::remove_multicast_group(const uint8_t *address)
|
||||
{
|
||||
/* To Do */
|
||||
}
|
||||
void SCL_EMAC::set_all_multicast(bool all)
|
||||
{
|
||||
/* No-op at this stage */
|
||||
}
|
||||
|
||||
void SCL_EMAC::power_down()
|
||||
{
|
||||
/* No-op at this stage */
|
||||
}
|
||||
|
||||
bool SCL_EMAC::power_up()
|
||||
{
|
||||
if (!powered_up) {
|
||||
#ifdef MBED_TEST_MODE
|
||||
scl_init();
|
||||
#endif
|
||||
if (!scl_wifi_on()) {
|
||||
SCL_LOG(("WiFi failed to turn on\r\n"));
|
||||
return false;
|
||||
}
|
||||
powered_up = true;
|
||||
if (link_state && emac_link_state_cb) {
|
||||
emac_link_state_cb(link_state);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SCL_EMAC::get_hwaddr(uint8_t *addr) const
|
||||
{
|
||||
scl_mac_t mac;
|
||||
scl_result_t res = scl_wifi_get_mac_address(&mac);
|
||||
if (res == SCL_SUCCESS) {
|
||||
memcpy(addr, mac.octet, sizeof(mac.octet));
|
||||
return true;
|
||||
} else {
|
||||
SCL_LOG(("Unable to get MAC address\r\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SCL_EMAC::set_hwaddr(const uint8_t *addr)
|
||||
{
|
||||
/* No-op at this stage */
|
||||
}
|
||||
|
||||
uint8_t SCL_EMAC::get_hwaddr_size() const
|
||||
{
|
||||
scl_mac_t mac;
|
||||
return sizeof(mac.octet);
|
||||
}
|
||||
|
||||
void SCL_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
|
||||
{
|
||||
emac_link_input_cb = input_cb;
|
||||
}
|
||||
|
||||
void SCL_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
|
||||
{
|
||||
emac_link_state_cb = state_cb;
|
||||
}
|
||||
|
||||
void SCL_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
|
||||
{
|
||||
memory_manager = &mem_mngr;
|
||||
}
|
||||
|
||||
bool SCL_EMAC::link_out(emac_mem_buf_t *buf)
|
||||
{
|
||||
scl_result_t retval;
|
||||
scl_tx_buf_t scl_tx_data;
|
||||
scl_tx_data.size = memory_manager->get_total_len(buf);
|
||||
scl_tx_data.buffer = buf;
|
||||
if (buf == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
retval = scl_network_send_ethernet_data(scl_tx_data); //Buffer is copied on Network Processor
|
||||
if (retval != SCL_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
memory_manager->free(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SCL_EMAC::get_ifname(char *name, uint8_t size) const
|
||||
{
|
||||
if (name != NULL) {
|
||||
memcpy(name, "scl", size);
|
||||
}
|
||||
}
|
||||
|
||||
void SCL_EMAC::set_activity_cb(mbed::Callback<void(bool)> cb)
|
||||
{
|
||||
activity_cb = cb;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void scl_network_process_ethernet_data(scl_buffer_t buffer)
|
||||
{
|
||||
emac_mem_buf_t *mem_buf = NULL;
|
||||
|
||||
SCL_EMAC &emac = SCL_EMAC::get_instance(SCL_STA_ROLE);
|
||||
|
||||
if (!emac.powered_up && !emac.emac_link_input_cb) {
|
||||
scl_buffer_release(buffer, SCL_NETWORK_RX);
|
||||
return;
|
||||
}
|
||||
mem_buf = buffer;
|
||||
if (emac.activity_cb) {
|
||||
emac.activity_cb(false);
|
||||
}
|
||||
emac.emac_link_input_cb(mem_buf);
|
||||
}
|
||||
|
||||
void scl_emac_wifi_link_state_changed(bool state_up)
|
||||
{
|
||||
SCL_EMAC &emac = SCL_EMAC::get_instance(SCL_STA_ROLE);
|
||||
|
||||
emac.link_state = state_up;
|
||||
if (emac.emac_link_state_cb) {
|
||||
emac.emac_link_state_cb(state_up);
|
||||
}
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2018-2020 Cypress Semiconductor Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SCL_EMAC_H_
|
||||
#define SCL_EMAC_H_
|
||||
|
||||
/** @file
|
||||
* Provides EMAC interface functions to be used with the SCL_EMAC object
|
||||
*
|
||||
*/
|
||||
#include "EMAC.h"
|
||||
#include "EMACInterface.h"
|
||||
#include "WiFiInterface.h"
|
||||
#include "scl_common.h"
|
||||
#include "rtos/Semaphore.h"
|
||||
#include "rtos/Mutex.h"
|
||||
#include "scl_wifi_api.h"
|
||||
class SCL_EMAC : public EMAC {
|
||||
public:
|
||||
SCL_EMAC();
|
||||
SCL_EMAC(scl_interface_role_t itype);
|
||||
|
||||
/**
|
||||
* Get the EMAC instance
|
||||
*
|
||||
* @return Reference to SCL_EMAC object.
|
||||
*/
|
||||
static SCL_EMAC &get_instance();
|
||||
|
||||
/**
|
||||
* Get the EMAC instance
|
||||
*
|
||||
* @param role Interface type.
|
||||
*
|
||||
* @return Reference to SCL_EMAC object.
|
||||
*/
|
||||
static SCL_EMAC &get_instance(scl_interface_role_t role);
|
||||
|
||||
/**
|
||||
* Returns the maximum transmission unit
|
||||
*
|
||||
* @return MTU in bytes.
|
||||
*/
|
||||
virtual uint32_t get_mtu_size() const;
|
||||
|
||||
/**
|
||||
* Gets the memory buffer alignment preference
|
||||
*
|
||||
* Gets the preferred memory buffer alignment of the EMAC device. IP stack may or may not
|
||||
* align with the link out memory buffer chains using the alignment.
|
||||
*
|
||||
* @return Memory alignment requirement in bytes.
|
||||
*/
|
||||
virtual uint32_t get_align_preference() const;
|
||||
|
||||
/**
|
||||
* Returns the interface name
|
||||
*
|
||||
* @param name Pointer to the location where the name should be written.
|
||||
* @param size Maximum number of characters to copy.
|
||||
*/
|
||||
virtual void get_ifname(char *name, uint8_t size) const;
|
||||
|
||||
/**
|
||||
* Returns the size of the underlying interface HW address size.
|
||||
*
|
||||
* @return HW address size in bytes.
|
||||
*/
|
||||
virtual uint8_t get_hwaddr_size() const;
|
||||
|
||||
/**
|
||||
* Returns the interface supplied HW address
|
||||
* Copies the HW address to the provided memory
|
||||
* @param addr HW address of the underlying interface. It must be of correct size. See @a get_hwaddr_size.
|
||||
* @return True if HW address is available.
|
||||
*/
|
||||
virtual bool get_hwaddr(uint8_t *addr) const;
|
||||
|
||||
/**
|
||||
* Set HW address for the interface
|
||||
*
|
||||
* Provided address must be of correct size. See @a get_hwaddr_size.
|
||||
*
|
||||
* Called to set the MAC address to be used - if @a get_hwaddr is provided
|
||||
* the stack would normally use that, but it could be overridden for test
|
||||
* purposes.
|
||||
*
|
||||
* @param addr Address to be set
|
||||
*/
|
||||
virtual void set_hwaddr(const uint8_t *addr);
|
||||
|
||||
/**
|
||||
* Sends the packet over the link
|
||||
*
|
||||
* This cannot be called from an interrupt context.
|
||||
*
|
||||
* @param buf Packet to be sent.
|
||||
* @return True if the packet was sent successfully. False otherwise.
|
||||
*/
|
||||
virtual bool link_out(emac_mem_buf_t *buf);
|
||||
|
||||
/**
|
||||
* Initializes the HW
|
||||
*
|
||||
* @return True on success. False in case of an error.
|
||||
*/
|
||||
virtual bool power_up();
|
||||
|
||||
/**
|
||||
* De-initializes the HW
|
||||
*/
|
||||
virtual void power_down();
|
||||
|
||||
/**
|
||||
* Sets a callback that is called for packets received for a given interface
|
||||
*
|
||||
* @param input_cb Function to be registered as a callback.
|
||||
*/
|
||||
virtual void set_link_input_cb(emac_link_input_cb_t input_cb);
|
||||
|
||||
/**
|
||||
* Sets a callback that is called on changes in the link status for a given interface
|
||||
*
|
||||
* @param state_cb Function to be registered as a callback.
|
||||
*/
|
||||
virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb);
|
||||
|
||||
/** Adds a device to a multicast group
|
||||
*
|
||||
* @param address A multicast group hardware address.
|
||||
*/
|
||||
virtual void add_multicast_group(const uint8_t *address);
|
||||
|
||||
/** Removes a device from a multicast group
|
||||
*
|
||||
* @param address A multicast group hardware address.
|
||||
*/
|
||||
virtual void remove_multicast_group(const uint8_t *address);
|
||||
|
||||
/** Requests reception of all multicast packets
|
||||
*
|
||||
* @param all True to receive all multicasts.
|
||||
* False to receive only multicasts addressed to specified groups.
|
||||
*/
|
||||
virtual void set_all_multicast(bool all);
|
||||
|
||||
/** Sets memory manager used to handle memory buffers
|
||||
*
|
||||
* @param mem_mngr Pointer to memory manager.
|
||||
*/
|
||||
virtual void set_memory_manager(EMACMemoryManager &mem_mngr);
|
||||
|
||||
/** Sets callback to receive EMAC activity events
|
||||
*
|
||||
* @param activity_cb The callback for activity events.
|
||||
*/
|
||||
virtual void set_activity_cb(mbed::Callback<void(bool is_tx_activity)> activity_cb);
|
||||
|
||||
emac_link_input_cb_t emac_link_input_cb = NULL; /**< Callback for incoming data */
|
||||
emac_link_state_change_cb_t emac_link_state_cb = NULL; /**< Callback for network connection status */
|
||||
EMACMemoryManager *memory_manager; /**< Pointer to hold memory manager object */
|
||||
bool powered_up = false; /**< Flag for Wi-Fi power on status */
|
||||
bool link_state = false; /**< Flag for network connection status */
|
||||
scl_interface_role_t interface_type; /**< Type of the interface */
|
||||
scl_mac_t multicast_addr; /**< Multicast address */
|
||||
mbed::Callback<void(bool)> activity_cb; /**< Callback for activity on network */
|
||||
|
||||
};
|
||||
/** Sends the change in network connection state to network stack
|
||||
*
|
||||
* @param state_up Connection status.
|
||||
*/
|
||||
extern "C" void scl_emac_wifi_link_state_changed(bool state_up);
|
||||
|
||||
#endif /* SCL_EMAC_H_ */
|
||||
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "CyDhcpServer.h"
|
||||
#include "cy_utils.h"
|
||||
#include "Callback.h"
|
||||
#include "def.h"
|
||||
#include "whd_types.h"
|
||||
|
||||
#ifdef DHCP_EXTENSIVE_DEBUG
|
||||
extern "C" void dhcp_server_print_header_info(dhcp_packet_t *header, uint32_t datalen, const char *title);
|
||||
#endif
|
||||
|
||||
/* UDP port numbers for DHCP server and client */
|
||||
#define IP_PORT_DHCP_SERVER (67)
|
||||
#define IP_PORT_DHCP_CLIENT (68)
|
||||
|
||||
/* BOOTP operations */
|
||||
#define BOOTP_OP_REQUEST (1)
|
||||
#define BOOTP_OP_REPLY (2)
|
||||
|
||||
/* DCHP message types */
|
||||
#define DHCP_MSG_TYPE_DISCOVER (1)
|
||||
#define DHCP_MSG_TYPE_OFFER (2)
|
||||
#define DHCP_MSG_TYPE_REQUEST (3)
|
||||
#define DHCP_MSG_TYPE_DECLINE (4)
|
||||
#define DHCP_MSG_TYPE_ACK (5)
|
||||
#define DHCP_MSG_TYPE_NACK (6)
|
||||
#define DHCP_MSG_TYPE_RELEASE (7)
|
||||
#define DHCP_MSG_TYPE_INFORM (8)
|
||||
#define DHCP_MSG_TYPE_INVALID (255)
|
||||
|
||||
#define DHCP_MSG_MAGIC_COOKIE (0x63825363)
|
||||
|
||||
#define DHCP_STACK_SIZE (8*1024)
|
||||
|
||||
/********************* Options manipulation functions ***********************************/
|
||||
static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype)
|
||||
{
|
||||
if (index + sizeof(dhcp_packet_t) - 1 + 1 >= DHCP_PACKET_SIZE) {
|
||||
printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp->Options[index++] = optype;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint8_t value)
|
||||
{
|
||||
if (index + sizeof(dhcp_packet_t) - 1 + 3 >= DHCP_PACKET_SIZE) {
|
||||
printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp->Options[index++] = optype;
|
||||
dhcp->Options[index++] = 0x01;
|
||||
dhcp->Options[index++] = value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint16_t value)
|
||||
{
|
||||
if (index + sizeof(dhcp_packet_t) - 1 + 4 >= DHCP_PACKET_SIZE) {
|
||||
printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp->Options[index++] = optype;
|
||||
dhcp->Options[index++] = 0x02;
|
||||
dhcp->Options[index++] = static_cast<uint8_t>((value >> 0) & 0xFF);
|
||||
dhcp->Options[index++] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint32_t value)
|
||||
{
|
||||
if (index + sizeof(dhcp_packet_t) - 1 + 6 >= DHCP_PACKET_SIZE) {
|
||||
printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp->Options[index++] = optype;
|
||||
dhcp->Options[index++] = 0x04;
|
||||
dhcp->Options[index++] = static_cast<uint8_t>((value >> 0) & 0xFF);
|
||||
dhcp->Options[index++] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||
dhcp->Options[index++] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||
dhcp->Options[index++] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint8_t *value, uint32_t size)
|
||||
{
|
||||
if (index + sizeof(dhcp_packet_t) - 1 + 2 + size >= DHCP_PACKET_SIZE) {
|
||||
printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp->Options[index++] = optype;
|
||||
dhcp->Options[index++] = size;
|
||||
memcpy(&dhcp->Options[index], value, size);
|
||||
index += size;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static const uint8_t *findOption(const dhcp_packet_t *request, uint8_t option_num)
|
||||
{
|
||||
const uint8_t *option_ptr = request->Options;
|
||||
while ((option_ptr[0] != DHCP_END_OPTION_CODE) &&
|
||||
(option_ptr[0] != option_num) &&
|
||||
(option_ptr < ((const uint8_t *)request) + DHCP_PACKET_SIZE)) {
|
||||
option_ptr += option_ptr[1] + 2;
|
||||
}
|
||||
|
||||
/* Was the option found? */
|
||||
if (option_ptr[0] == option_num) {
|
||||
return &option_ptr[2];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void addCommonOptions(dhcp_packet_t *dhcp, uint32_t &index, const uint32_t server_addr, const uint32_t netmask)
|
||||
{
|
||||
/* Prepare the Web proxy auto discovery URL */
|
||||
char wpad_sample_url[] = "http://xxx.xxx.xxx.xxx/wpad.dat";
|
||||
char ip_str[16];
|
||||
ipv4_to_string(ip_str, htonl(server_addr));
|
||||
memcpy(&wpad_sample_url[7], &ip_str[0], 15);
|
||||
|
||||
/* Server identifier */
|
||||
addOption(dhcp, index, DHCP_SERVER_IDENTIFIER_OPTION_CODE, server_addr);
|
||||
/* Lease Time */
|
||||
addOption(dhcp, index, DHCP_LEASETIME_OPTION_CODE, static_cast<uint32_t>(0x00015180));
|
||||
/* Subnet Mask */
|
||||
addOption(dhcp, index, DHCP_SUBNETMASK_OPTION_CODE, htonl(netmask));
|
||||
/* Web proxy auto discovery URL */
|
||||
addOption(dhcp, index, DHCP_WPAD_OPTION_CODE, (uint8_t *)&wpad_sample_url[0], strlen(wpad_sample_url));
|
||||
/* Router (gateway) */
|
||||
addOption(dhcp, index, DHCP_ROUTER_OPTION_CODE, htonl(server_addr));
|
||||
/* DNS server */
|
||||
addOption(dhcp, index, DHCP_DNS_SERVER_OPTION_CODE, htonl(server_addr));
|
||||
/* Interface MTU */
|
||||
addOption(dhcp, index, DHCP_MTU_OPTION_CODE, static_cast<uint16_t>(WHD_PAYLOAD_MTU));
|
||||
}
|
||||
|
||||
static void sendPacket(UDPSocket *socket, dhcp_packet_t *dhcp, uint32_t size)
|
||||
{
|
||||
nsapi_size_or_error_t err;
|
||||
uint32_t broadcast_ip = 0xFFFFFFFF;
|
||||
char string_addr[16];
|
||||
ipv4_to_string(string_addr, htonl(broadcast_ip));
|
||||
SocketAddress sock_addr(string_addr, IP_PORT_DHCP_CLIENT);
|
||||
|
||||
err = socket->sendto(sock_addr, reinterpret_cast<uint8_t *>(dhcp), size);
|
||||
if (err < 0) {
|
||||
printf("DHCP ERROR: Packet send failure with error %d.", err);
|
||||
} else if (err != (int)size) {
|
||||
printf("DHCP ERROR: Could not send entire packet. Only %d bytes were sent.", err);
|
||||
}
|
||||
}
|
||||
|
||||
/********************* Cache utility functions ***********************************/
|
||||
void CyDhcpServer::setAddress(const cy_mac_addr_t &mac_id, const cy_ip_addr_t &addr)
|
||||
{
|
||||
uint32_t a;
|
||||
uint32_t first_empty_slot;
|
||||
uint32_t cached_slot;
|
||||
char empty_cache[NSAPI_IPv6_SIZE] = "";
|
||||
|
||||
/* Search for empty slot in cache */
|
||||
for (a = 0, first_empty_slot = DHCP_IP_ADDRESS_CACHE_MAX, cached_slot = DHCP_IP_ADDRESS_CACHE_MAX; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) {
|
||||
/* Check for matching MAC address */
|
||||
if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) {
|
||||
/* Cached device found */
|
||||
cached_slot = a;
|
||||
break;
|
||||
} else if (first_empty_slot == DHCP_IP_ADDRESS_CACHE_MAX && memcmp(&_mac_addr_cache[a], &empty_cache, sizeof(cy_mac_addr_t)) == 0) {
|
||||
/* Device not found in cache. Return the first empty slot */
|
||||
first_empty_slot = a;
|
||||
}
|
||||
}
|
||||
|
||||
if (cached_slot != DHCP_IP_ADDRESS_CACHE_MAX) {
|
||||
/* Update IP address of cached device */
|
||||
_ip_addr_cache[cached_slot] = addr;
|
||||
} else if (first_empty_slot != DHCP_IP_ADDRESS_CACHE_MAX) {
|
||||
/* Add device to the first empty slot */
|
||||
_mac_addr_cache[first_empty_slot] = mac_id;
|
||||
_ip_addr_cache[first_empty_slot] = addr;
|
||||
} else {
|
||||
/* Cache is full. Add device to slot 0 */
|
||||
_mac_addr_cache[0] = mac_id;
|
||||
_ip_addr_cache [0] = addr;
|
||||
}
|
||||
}
|
||||
|
||||
bool CyDhcpServer::lookupAddress(const cy_mac_addr_t &mac_id, cy_ip_addr_t &addr)
|
||||
{
|
||||
/* Check whether device is already cached */
|
||||
for (uint32_t a = 0; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) {
|
||||
if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) {
|
||||
addr = _ip_addr_cache[a];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CyDhcpServer::freeAddress(const cy_mac_addr_t &mac_id)
|
||||
{
|
||||
/* Check whether device is already cached */
|
||||
for (uint32_t a = 0; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) {
|
||||
if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) {
|
||||
memset(&_mac_addr_cache[a], 0, sizeof(_mac_addr_cache[a]));
|
||||
memset(&_ip_addr_cache[a], 0, sizeof(_ip_addr_cache[a]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CyDhcpServer::handleDiscover(dhcp_packet_t *dhcp)
|
||||
{
|
||||
#ifdef DHCP_EXTENSIVE_DEBUG
|
||||
dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP DISCOVER RECEIVED");
|
||||
#endif
|
||||
|
||||
uint32_t index;
|
||||
cy_mac_addr_t client_mac;
|
||||
cy_ip_addr_t client_ip;
|
||||
|
||||
memcpy(&client_mac, dhcp->ClientHwAddr, sizeof(client_mac));
|
||||
if (!lookupAddress(client_mac, client_ip)) {
|
||||
client_ip = _available_addr;
|
||||
}
|
||||
|
||||
memset(&dhcp->Legacy, 0, sizeof(dhcp->Legacy));
|
||||
memset(&dhcp->Options[0], 0, DHCP_PACKET_SIZE - sizeof(dhcp_packet_t) + 3);
|
||||
|
||||
dhcp->Opcode = BOOTP_OP_REPLY;
|
||||
dhcp->YourIpAddr = htonl(client_ip.addrv4.addr);
|
||||
dhcp->MagicCookie = htonl(static_cast<uint32_t>(DHCP_MSG_MAGIC_COOKIE));
|
||||
|
||||
/* Add options */
|
||||
index = 0;
|
||||
addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast<uint8_t>(DHCP_MSG_TYPE_OFFER));
|
||||
addCommonOptions(dhcp, index, _server_addr.addrv4.addr, _netmask.addrv4.addr);
|
||||
addOption(dhcp, index, static_cast<uint8_t>(DHCP_END_OPTION_CODE));
|
||||
|
||||
uint32_t size = sizeof(dhcp_packet_t) + index - 1;
|
||||
CY_ASSERT(size <= DHCP_PACKET_SIZE);
|
||||
|
||||
#ifdef DHCP_EXTENSIVE_DEBUG
|
||||
dhcp_server_print_header_info(dhcp, size, "\n\nDHCP OFFER SENT");
|
||||
#endif
|
||||
sendPacket(&_socket, dhcp, size);
|
||||
}
|
||||
|
||||
void CyDhcpServer::handleRequest(dhcp_packet_t *dhcp)
|
||||
{
|
||||
#ifdef DHCP_EXTENSIVE_DEBUG
|
||||
dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP REQUEST RECEIVED");
|
||||
#endif
|
||||
|
||||
cy_mac_addr_t client_mac;
|
||||
cy_ip_addr_t client_ip;
|
||||
cy_ip_addr_t req_ip;
|
||||
bool increment = false;
|
||||
uint32_t index;
|
||||
|
||||
/* Check that the REQUEST is for this server */
|
||||
uint32_t *server_id_req = (uint32_t *)findOption(dhcp, DHCP_SERVER_IDENTIFIER_OPTION_CODE);
|
||||
if ((server_id_req == NULL) || ((server_id_req != NULL) && (_server_addr.addrv4.addr != *server_id_req))) {
|
||||
return; /* Server ID was not found or does not match local IP address */
|
||||
}
|
||||
|
||||
/* Locate the requested address in the options and keep requested address */
|
||||
req_ip.addrv4.addr = ntohl(*(uint32_t *)findOption(dhcp, DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE));
|
||||
|
||||
memcpy(&client_mac, dhcp->ClientHwAddr, sizeof(client_mac));
|
||||
if (!lookupAddress(client_mac, client_ip)) {
|
||||
client_ip = _available_addr;
|
||||
increment = true;
|
||||
}
|
||||
|
||||
memset(&dhcp->Legacy, 0, sizeof(dhcp->Legacy));
|
||||
memset(&dhcp->Options[0], 0, DHCP_PACKET_SIZE - sizeof(dhcp_packet_t) + 3);
|
||||
|
||||
dhcp->Opcode = BOOTP_OP_REPLY;
|
||||
dhcp->MagicCookie = htonl(static_cast<uint32_t>(DHCP_MSG_MAGIC_COOKIE));
|
||||
|
||||
index = 0;
|
||||
/* Check if the requested IP address matches one we have assigned */
|
||||
if (req_ip.addrv4.addr != client_ip.addrv4.addr) {
|
||||
/* Request is not for the assigned IP - force client to take next available IP by sending NAK */
|
||||
addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast<uint8_t>(DHCP_MSG_TYPE_NACK));
|
||||
addOption(dhcp, index, DHCP_SERVER_IDENTIFIER_OPTION_CODE, _server_addr.addrv4.addr);
|
||||
printf("\n\nDHCP_THREAD: %d REQUEST NAK\n", __LINE__);
|
||||
} else {
|
||||
dhcp->YourIpAddr = htonl(client_ip.addrv4.addr);
|
||||
|
||||
addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast<uint8_t>(DHCP_MSG_TYPE_ACK));
|
||||
addCommonOptions(dhcp, index, _server_addr.addrv4.addr, _netmask.addrv4.addr);
|
||||
|
||||
if (increment) {
|
||||
uint32_t ip_mask = ~(_netmask.addrv4.addr);
|
||||
uint32_t subnet = _server_addr.addrv4.addr & _netmask.addrv4.addr;
|
||||
do {
|
||||
_available_addr.addrv4.addr = subnet | ((_available_addr.addrv4.addr + 1) & ip_mask);
|
||||
} while (_available_addr.addrv4.addr == _server_addr.addrv4.addr);
|
||||
}
|
||||
setAddress(client_mac, client_ip);
|
||||
}
|
||||
addOption(dhcp, index, static_cast<uint8_t>(DHCP_END_OPTION_CODE));
|
||||
|
||||
uint32_t size = sizeof(dhcp_packet_t) + index - 1;
|
||||
CY_ASSERT(size <= DHCP_PACKET_SIZE);
|
||||
|
||||
#ifdef DHCP_EXTENSIVE_DEBUG
|
||||
dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP REQUEST REPLY SENT");
|
||||
#endif
|
||||
sendPacket(&_socket, dhcp, size);
|
||||
}
|
||||
|
||||
void CyDhcpServer::runServer(void)
|
||||
{
|
||||
nsapi_size_or_error_t err_or_size;
|
||||
|
||||
_running = true;
|
||||
|
||||
/* Create receive DHCP socket */
|
||||
_socket.open(_nstack);
|
||||
char iface_name[8] = {0};
|
||||
_niface->get_interface_name(iface_name);
|
||||
_socket.setsockopt(NSAPI_SOCKET, NSAPI_BIND_TO_DEVICE, iface_name, strlen(iface_name));
|
||||
_socket.bind((uint16_t)IP_PORT_DHCP_SERVER);
|
||||
|
||||
/* Save the current netmask to be sent in DHCP packets as the 'subnet mask option' */
|
||||
SocketAddress sock_addr;
|
||||
_niface->get_ip_address(&sock_addr);
|
||||
_server_addr.addrv4.addr = string_to_ipv4(sock_addr.get_ip_address());
|
||||
_niface->get_netmask(&sock_addr);
|
||||
_netmask.addrv4.addr = string_to_ipv4(sock_addr.get_ip_address());
|
||||
|
||||
#ifdef DHCP_EXTENSIVE_DEBUG
|
||||
printf("DHCP Server started.\n");
|
||||
printf("DHCP Server: IP : %s\n", _niface->get_ip_address());
|
||||
printf("DHCP Server: Netmask: %s\n", _niface->get_netmask());
|
||||
printf("DHCP Server: Gateway: %s\n", _niface->get_gateway());
|
||||
printf("DHCP Server: MAC : %s\n\n", _niface->get_mac_address());
|
||||
#endif
|
||||
|
||||
/* Calculate the first available IP address which will be served - based on the netmask and the local IP */
|
||||
uint32_t ip_mask = ~(_netmask.addrv4.addr);
|
||||
uint32_t subnet = _server_addr.addrv4.addr & _netmask.addrv4.addr;
|
||||
_available_addr.addrv4.addr = subnet | ((_server_addr.addrv4.addr + 1) & ip_mask);
|
||||
|
||||
while (_running) {
|
||||
/* Sleep until data is received from socket. */
|
||||
err_or_size = _socket.recv(_buff, DHCP_PACKET_SIZE);
|
||||
/* Options field in DHCP header is variable length. We are looking for option "DHCP Message Type" that is 3 octets in size (code, length and type) */
|
||||
/* If the return value is <0, it is an error; if it is >=0, it is the received length */
|
||||
if (err_or_size < 0 || err_or_size < (int32_t)sizeof(dhcp_packet_t)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dhcp_packet_t *dhcp = reinterpret_cast<dhcp_packet_t *>(_buff);
|
||||
/* Check if the option in the dhcp header is "DHCP Message Type", code value for option "DHCP Message Type" is 53 as per rfc2132 */
|
||||
if (dhcp->Options[0] != DHCP_MESSAGETYPE_OPTION_CODE) {
|
||||
printf("%d: %s received option code wrong: %d != %d\n", __LINE__, __func__, dhcp->Options[0], DHCP_MESSAGETYPE_OPTION_CODE);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t msg_type = dhcp->Options[2];
|
||||
switch (msg_type) {
|
||||
case DHCP_MSG_TYPE_DISCOVER:
|
||||
handleDiscover(dhcp);
|
||||
break;
|
||||
case DHCP_MSG_TYPE_REQUEST:
|
||||
handleRequest(dhcp);
|
||||
break;
|
||||
default:
|
||||
printf("DHCP ERROR: Unhandled dhcp packet type, %d", msg_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CyDhcpServer::threadWrapper(CyDhcpServer *obj)
|
||||
{
|
||||
obj->runServer();
|
||||
}
|
||||
|
||||
CyDhcpServer::CyDhcpServer(NetworkStack *nstack, NetworkInterface *niface)
|
||||
: _nstack(nstack),
|
||||
_niface(niface),
|
||||
_thread(osPriorityNormal, DHCP_STACK_SIZE, NULL, "DHCPserver") {}
|
||||
|
||||
CyDhcpServer::~CyDhcpServer()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
cy_rslt_t CyDhcpServer::start(void)
|
||||
{
|
||||
cy_rslt_t result = CY_RSLT_SUCCESS;
|
||||
if (!_running) {
|
||||
CY_ASSERT(_nstack != NULL);
|
||||
|
||||
/* Clear cache */
|
||||
memset(_mac_addr_cache, 0, sizeof(_mac_addr_cache));
|
||||
memset(_ip_addr_cache, 0, sizeof(_ip_addr_cache));
|
||||
|
||||
/* Start DHCP server */
|
||||
if (osOK != _thread.start(mbed::callback(threadWrapper, this))) {
|
||||
result = CY_DHCP_THREAD_CREATION_FAILED;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
cy_rslt_t CyDhcpServer::stop(void)
|
||||
{
|
||||
cy_rslt_t result = CY_RSLT_SUCCESS;
|
||||
if (_running) {
|
||||
_running = false;
|
||||
if (NSAPI_ERROR_OK != _socket.close()) {
|
||||
printf("DHCP ERROR: DHCP socket closure failed.\n");
|
||||
result = CY_DHCP_STOP_FAILED;
|
||||
}
|
||||
if (osOK != _thread.join()) {
|
||||
printf("DHCP ERROR: DHCP thread join failed.\n");
|
||||
result = CY_DHCP_STOP_FAILED;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WHD_DHCP_SERVER_H
|
||||
#define WHD_DHCP_SERVER_H
|
||||
|
||||
#include "cy_result.h"
|
||||
#include "cy_syslib.h"
|
||||
#include "cynetwork_utils.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "netsocket/NetworkInterface.h"
|
||||
#include "netsocket/NetworkStack.h"
|
||||
#include "rtos.h"
|
||||
|
||||
/* DHCP data structure */
|
||||
typedef struct {
|
||||
uint8_t Opcode; /* packet opcode type */
|
||||
uint8_t HwType; /* hardware addr type */
|
||||
uint8_t HwLen; /* hardware addr length */
|
||||
uint8_t Hops; /* gateway hops */
|
||||
uint32_t TransactionId; /* transaction ID */
|
||||
uint16_t SecsElapsed; /* seconds since boot began */
|
||||
uint16_t Flags;
|
||||
uint32_t ClientIpAddr; /* client IP address */
|
||||
uint32_t YourIpAddr; /* 'your' IP address */
|
||||
uint32_t ServerIpAddr; /* server IP address */
|
||||
uint32_t GatewayIpAddr; /* gateway IP address */
|
||||
uint8_t ClientHwAddr[16]; /* client hardware address */
|
||||
uint8_t Legacy[192]; /* SName, File */
|
||||
uint32_t MagicCookie;
|
||||
uint8_t Options[3]; /* options area */
|
||||
/* as of RFC2131 it is variable length */
|
||||
} dhcp_packet_t;
|
||||
|
||||
#define DHCP_SUBNETMASK_OPTION_CODE (1)
|
||||
#define DHCP_ROUTER_OPTION_CODE (3)
|
||||
#define DHCP_DNS_SERVER_OPTION_CODE (6)
|
||||
#define DHCP_HOST_NAME_OPTION_CODE (12)
|
||||
#define DHCP_MTU_OPTION_CODE (26)
|
||||
#define DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE (50)
|
||||
#define DHCP_LEASETIME_OPTION_CODE (51)
|
||||
#define DHCP_MESSAGETYPE_OPTION_CODE (53)
|
||||
#define DHCP_SERVER_IDENTIFIER_OPTION_CODE (54)
|
||||
#define DHCP_PARAM_REQUEST_LIST_OPTION_CODE (55)
|
||||
#define DHCP_WPAD_OPTION_CODE (252)
|
||||
#define DHCP_END_OPTION_CODE (255)
|
||||
|
||||
#define DHCP_IP_ADDRESS_CACHE_MAX (5)
|
||||
#define ADDITIONAL_OPTION_BYTES (272)
|
||||
#define DHCP_PACKET_SIZE (sizeof(dhcp_packet_t) + ADDITIONAL_OPTION_BYTES)
|
||||
|
||||
/** DHCP thread could not be started */
|
||||
#define CY_DHCP_THREAD_CREATION_FAILED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_BASE, 0)
|
||||
|
||||
/** Error while trying to stop the DHCP server */
|
||||
#define CY_DHCP_STOP_FAILED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_BASE, 1)
|
||||
|
||||
/**
|
||||
* Implementation of a DHCP sever
|
||||
*/
|
||||
class CyDhcpServer {
|
||||
public:
|
||||
/**
|
||||
* Create a DHCP server.
|
||||
*/
|
||||
CyDhcpServer(NetworkStack *nstack, NetworkInterface *niface);
|
||||
|
||||
/**
|
||||
* Delete the DHCP server.
|
||||
*/
|
||||
virtual ~CyDhcpServer();
|
||||
|
||||
/**
|
||||
* Start a DHCP server instance.
|
||||
* @return CY_RSLT_SUCCESS on success otherwise error.
|
||||
*/
|
||||
cy_rslt_t start(void);
|
||||
|
||||
/**
|
||||
* Stop a DHCP server instance.
|
||||
* @return CY_RSLT_SUCCESS on success otherwise error.
|
||||
*/
|
||||
cy_rslt_t stop(void);
|
||||
|
||||
private:
|
||||
NetworkStack *_nstack = NULL;
|
||||
NetworkInterface *_niface = NULL;
|
||||
UDPSocket _socket;
|
||||
Thread _thread;
|
||||
bool _running = false;
|
||||
|
||||
cy_ip_addr_t _available_addr;
|
||||
cy_ip_addr_t _server_addr;
|
||||
cy_ip_addr_t _netmask;
|
||||
|
||||
cy_mac_addr_t _mac_addr_cache[DHCP_IP_ADDRESS_CACHE_MAX];
|
||||
cy_ip_addr_t _ip_addr_cache[DHCP_IP_ADDRESS_CACHE_MAX];
|
||||
uint8_t _buff[DHCP_PACKET_SIZE];
|
||||
|
||||
static void threadWrapper(CyDhcpServer *obj);
|
||||
void runServer(void);
|
||||
|
||||
void setAddress(const cy_mac_addr_t &mac_id, const cy_ip_addr_t &addr);
|
||||
bool lookupAddress(const cy_mac_addr_t &mac_id, cy_ip_addr_t &addr);
|
||||
void freeAddress(const cy_mac_addr_t &mac_id);
|
||||
|
||||
void handleDiscover(dhcp_packet_t *dhcp);
|
||||
void handleRequest(dhcp_packet_t *dhcp);
|
||||
};
|
||||
|
||||
#endif /* WHD_DHCP_SERVER_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* WHD Access Point Interface Implementation
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include "WhdAccessPoint.h"
|
||||
|
||||
WhdAccessPoint::WhdAccessPoint(nsapi_wifi_ap_t ap, whd_bss_type_t bss_type, uint8_t *ie_ptr, uint32_t ie_len) :
|
||||
WiFiAccessPoint(ap), _bss_type(bss_type)
|
||||
{
|
||||
_ie_ptr = (uint8_t *)malloc(ie_len * sizeof(uint8_t));
|
||||
if (_ie_ptr != NULL) {
|
||||
_ie_len = ie_len;
|
||||
memcpy(_ie_ptr, ie_ptr, ie_len * sizeof(uint8_t));
|
||||
}
|
||||
}
|
||||
|
||||
WhdAccessPoint &WhdAccessPoint::operator=(WhdAccessPoint &&rhs)
|
||||
{
|
||||
if (this != &rhs) {
|
||||
WiFiAccessPoint::operator=(rhs);
|
||||
_bss_type = rhs._bss_type;
|
||||
_ie_ptr = rhs._ie_ptr;
|
||||
_ie_len = rhs._ie_len;
|
||||
rhs._ie_ptr = NULL;
|
||||
rhs._ie_len = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
whd_bss_type_t WhdAccessPoint::get_bss_type() const
|
||||
{
|
||||
return _bss_type;
|
||||
}
|
||||
|
||||
uint8_t *WhdAccessPoint::get_ie_data() const
|
||||
{
|
||||
return _ie_ptr;
|
||||
}
|
||||
|
||||
uint32_t WhdAccessPoint::get_ie_len() const
|
||||
{
|
||||
return _ie_len;
|
||||
}
|
||||
|
||||
WhdAccessPoint::~WhdAccessPoint()
|
||||
{
|
||||
if (_ie_ptr != NULL) {
|
||||
free(_ie_ptr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* WHD Access Point Interface
|
||||
* Copyright (c) 2017-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WHD_ACCESS_POINT_H
|
||||
#define WHD_ACCESS_POINT_H
|
||||
|
||||
#include "netsocket/WiFiAccessPoint.h"
|
||||
#include "whd_types.h"
|
||||
|
||||
/* Enum for scan result type */
|
||||
enum scan_result_type {
|
||||
SRES_TYPE_WIFI_ACCESS_POINT,
|
||||
SRES_TYPE_WHD_ACCESS_POINT
|
||||
};
|
||||
|
||||
/** WhdAccessPoint class
|
||||
*
|
||||
* Class that represents a Whd Access Point
|
||||
* which contains additional Whd specific information
|
||||
*/
|
||||
class WhdAccessPoint : public WiFiAccessPoint {
|
||||
public:
|
||||
WhdAccessPoint() : WiFiAccessPoint() {};
|
||||
WhdAccessPoint(nsapi_wifi_ap_t ap, whd_bss_type_t bss_type, uint8_t *ie_ptr, uint32_t ie_len);
|
||||
|
||||
/** Define move assignment and prevent copy-assignment
|
||||
*
|
||||
* Due to IE element data could have large memory footprint,
|
||||
* only move assignment is allowed.
|
||||
*/
|
||||
WhdAccessPoint &operator=(WhdAccessPoint &&rhs);
|
||||
WhdAccessPoint &operator=(const WhdAccessPoint &rhs) = delete;
|
||||
|
||||
/** Get WHD access point's bss type
|
||||
*
|
||||
* @return The whd_bss_type_t of the access point
|
||||
*/
|
||||
whd_bss_type_t get_bss_type() const;
|
||||
|
||||
/** Get WHD access point's IE data
|
||||
*
|
||||
* @return The pointer to ie data buffer
|
||||
*/
|
||||
uint8_t *get_ie_data() const;
|
||||
|
||||
/** Get WHD access point's IE length
|
||||
*
|
||||
* @return The ie data length
|
||||
*/
|
||||
uint32_t get_ie_len() const;
|
||||
|
||||
virtual ~WhdAccessPoint();
|
||||
|
||||
private:
|
||||
whd_bss_type_t _bss_type;
|
||||
uint8_t *_ie_ptr; /**< Pointer to received Beacon/Probe Response IE(Information Element) */
|
||||
uint32_t _ie_len; /**< Length of IE(Information Element) */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,665 @@
|
||||
/* WHD STAION implementation of NetworkInterfaceAPI
|
||||
* Copyright (c) 2017-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "WhdSTAInterface.h"
|
||||
#include "nsapi.h"
|
||||
#include "lwipopts.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "rtos.h"
|
||||
#include "whd_emac.h"
|
||||
#include "whd_wifi_api.h"
|
||||
#include "whd_wlioctl.h"
|
||||
|
||||
#define CMP_MAC( a, b ) (((((unsigned char*)a)[0])==(((unsigned char*)b)[0]))&& \
|
||||
((((unsigned char*)a)[1])==(((unsigned char*)b)[1]))&& \
|
||||
((((unsigned char*)a)[2])==(((unsigned char*)b)[2]))&& \
|
||||
((((unsigned char*)a)[3])==(((unsigned char*)b)[3]))&& \
|
||||
((((unsigned char*)a)[4])==(((unsigned char*)b)[4]))&& \
|
||||
((((unsigned char*)a)[5])==(((unsigned char*)b)[5])))
|
||||
|
||||
struct whd_scan_userdata {
|
||||
rtos::Semaphore *sema;
|
||||
scan_result_type sres_type;
|
||||
WiFiAccessPoint *aps;
|
||||
std::vector<whd_scan_result_t> *result_buff;
|
||||
unsigned count;
|
||||
unsigned offset;
|
||||
bool scan_in_progress;
|
||||
};
|
||||
|
||||
static whd_scan_userdata interal_scan_data;
|
||||
static whd_scan_result_t internal_scan_result;
|
||||
static uint16_t sta_link_update_entry = 0xFF;
|
||||
static const whd_event_num_t sta_link_change_events[] = {
|
||||
WLC_E_SET_SSID, WLC_E_LINK, WLC_E_AUTH, WLC_E_ASSOC, WLC_E_DEAUTH_IND, WLC_E_DISASSOC_IND, WLC_E_DISASSOC,
|
||||
WLC_E_REASSOC, WLC_E_PSK_SUP, WLC_E_ACTION_FRAME_COMPLETE, WLC_E_NONE
|
||||
};
|
||||
|
||||
|
||||
extern "C" void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up);
|
||||
|
||||
|
||||
int whd_toerror(whd_result_t res)
|
||||
{
|
||||
switch (res) {
|
||||
case WHD_SUCCESS:
|
||||
return NSAPI_ERROR_OK;
|
||||
case WHD_UNSUPPORTED:
|
||||
case WHD_WLAN_UNSUPPORTED:
|
||||
case WHD_WLAN_ACM_NOTSUPPORTED:
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
case WHD_BADARG:
|
||||
case WHD_WLAN_BADARG:
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
case WHD_WLAN_NOTASSOCIATED:
|
||||
case WHD_INVALID_JOIN_STATUS:
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
case WHD_BUFFER_UNAVAILABLE_PERMANENT:
|
||||
case WHD_BUFFER_UNAVAILABLE_TEMPORARY:
|
||||
case WHD_RX_BUFFER_ALLOC_FAIL:
|
||||
case WHD_BUFFER_ALLOC_FAIL:
|
||||
case WHD_WLAN_NOMEM:
|
||||
case WHD_MALLOC_FAILURE:
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
case WHD_ACCESS_POINT_NOT_FOUND:
|
||||
case WHD_NETWORK_NOT_FOUND:
|
||||
return NSAPI_ERROR_NO_SSID;
|
||||
case WHD_NOT_AUTHENTICATED:
|
||||
case WHD_INVALID_KEY:
|
||||
case WHD_NOT_KEYED:
|
||||
return NSAPI_ERROR_AUTH_FAILURE;
|
||||
case WHD_PENDING:
|
||||
case WHD_JOIN_IN_PROGRESS:
|
||||
return NSAPI_ERROR_IN_PROGRESS;
|
||||
case WHD_CONNECTION_LOST:
|
||||
return NSAPI_ERROR_CONNECTION_LOST;
|
||||
case WHD_TIMEOUT:
|
||||
case WHD_EAPOL_KEY_PACKET_M1_TIMEOUT:
|
||||
case WHD_EAPOL_KEY_PACKET_M3_TIMEOUT:
|
||||
case WHD_EAPOL_KEY_PACKET_G1_TIMEOUT:
|
||||
return NSAPI_ERROR_CONNECTION_TIMEOUT;
|
||||
case WHD_WLAN_BUSY:
|
||||
return NSAPI_ERROR_BUSY;
|
||||
case WHD_WLAN_NODEVICE:
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
default:
|
||||
return -res;
|
||||
}
|
||||
}
|
||||
|
||||
static nsapi_security_t whd_tosecurity(whd_security_t sec)
|
||||
{
|
||||
switch (sec) {
|
||||
case WHD_SECURITY_OPEN:
|
||||
return NSAPI_SECURITY_NONE;
|
||||
case WHD_SECURITY_WEP_PSK:
|
||||
case WHD_SECURITY_WEP_SHARED:
|
||||
return NSAPI_SECURITY_WEP;
|
||||
case WHD_SECURITY_WPA_MIXED_PSK:
|
||||
case WHD_SECURITY_WPA_TKIP_PSK:
|
||||
case WHD_SECURITY_WPA_TKIP_ENT:
|
||||
return NSAPI_SECURITY_WPA;
|
||||
case WHD_SECURITY_WPA2_WPA_AES_PSK:
|
||||
case WHD_SECURITY_WPA2_WPA_MIXED_PSK:
|
||||
return NSAPI_SECURITY_WPA_WPA2;
|
||||
case WHD_SECURITY_WPA2_MIXED_ENT:
|
||||
return NSAPI_SECURITY_WPA2_ENT;
|
||||
case WHD_SECURITY_WPA2_MIXED_PSK:
|
||||
case WHD_SECURITY_WPA2_AES_PSK:
|
||||
case WHD_SECURITY_WPA2_AES_ENT:
|
||||
case WHD_SECURITY_WPA2_FBT_PSK:
|
||||
case WHD_SECURITY_WPA2_FBT_ENT:
|
||||
return NSAPI_SECURITY_WPA2;
|
||||
case WHD_SECURITY_WPA3_SAE:
|
||||
return NSAPI_SECURITY_WPA3;
|
||||
case WHD_SECURITY_WPA3_WPA2_PSK:
|
||||
return NSAPI_SECURITY_WPA3_WPA2;
|
||||
default:
|
||||
return NSAPI_SECURITY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
whd_security_t whd_fromsecurity(nsapi_security_t sec)
|
||||
{
|
||||
switch (sec) {
|
||||
case NSAPI_SECURITY_NONE:
|
||||
return WHD_SECURITY_OPEN;
|
||||
case NSAPI_SECURITY_WEP:
|
||||
return WHD_SECURITY_WEP_PSK;
|
||||
case NSAPI_SECURITY_WPA:
|
||||
return WHD_SECURITY_WPA_MIXED_PSK;
|
||||
case NSAPI_SECURITY_WPA2:
|
||||
return WHD_SECURITY_WPA2_AES_PSK;
|
||||
case NSAPI_SECURITY_WPA_WPA2:
|
||||
return WHD_SECURITY_WPA2_MIXED_PSK;
|
||||
case NSAPI_SECURITY_WPA2_ENT:
|
||||
return WHD_SECURITY_WPA2_MIXED_ENT;
|
||||
case NSAPI_SECURITY_WPA3:
|
||||
return WHD_SECURITY_WPA3_SAE;
|
||||
case NSAPI_SECURITY_WPA3_WPA2:
|
||||
return WHD_SECURITY_WPA3_WPA2_PSK;
|
||||
default:
|
||||
return WHD_SECURITY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void *whd_wifi_link_state_change_handler(whd_interface_t ifp,
|
||||
const whd_event_header_t *event_header,
|
||||
const uint8_t *event_data,
|
||||
void *handler_user_data)
|
||||
{
|
||||
UNUSED_PARAMETER(event_data);
|
||||
|
||||
if (event_header->bsscfgidx >= WHD_INTERFACE_MAX) {
|
||||
WPRINT_WHD_DEBUG(("%s: event_header: Bad interface\n", __FUNCTION__));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((event_header->event_type == WLC_E_DEAUTH_IND) ||
|
||||
(event_header->event_type == WLC_E_DISASSOC_IND) ||
|
||||
((event_header->event_type == WLC_E_PSK_SUP) &&
|
||||
(event_header->status == WLC_SUP_KEYED) &&
|
||||
(event_header->reason == WLC_E_SUP_DEAUTH))) {
|
||||
whd_emac_wifi_link_state_changed(ifp, WHD_FALSE);
|
||||
return handler_user_data;
|
||||
}
|
||||
|
||||
if (((event_header->event_type == WLC_E_PSK_SUP) &&
|
||||
(event_header->status == WLC_SUP_KEYED) &&
|
||||
(event_header->reason == WLC_E_SUP_OTHER)) ||
|
||||
(whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS)) {
|
||||
whd_emac_wifi_link_state_changed(ifp, WHD_TRUE);
|
||||
return handler_user_data;
|
||||
}
|
||||
|
||||
return handler_user_data;
|
||||
}
|
||||
|
||||
|
||||
MBED_WEAK WhdSTAInterface::OlmInterface &WhdSTAInterface::OlmInterface::get_default_instance()
|
||||
{
|
||||
static OlmInterface olm;
|
||||
return olm;
|
||||
}
|
||||
|
||||
WhdSTAInterface::WhdSTAInterface(WHD_EMAC &emac, OnboardNetworkStack &stack, OlmInterface &olm, whd_interface_shared_info_t &shared)
|
||||
: EMACInterface(emac, stack),
|
||||
_ssid("\0"),
|
||||
_pass("\0"),
|
||||
_security(NSAPI_SECURITY_NONE),
|
||||
_whd_emac(emac),
|
||||
_olm(&olm),
|
||||
_iface_shared(shared)
|
||||
{
|
||||
}
|
||||
|
||||
nsapi_error_t WhdSTAInterface::connect(
|
||||
const char *ssid, const char *pass,
|
||||
nsapi_security_t security,
|
||||
uint8_t channel)
|
||||
{
|
||||
int err = set_channel(channel);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = set_credentials(ssid, pass, security);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return connect();
|
||||
}
|
||||
|
||||
nsapi_error_t WhdSTAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
|
||||
{
|
||||
if ((ssid == NULL) ||
|
||||
(strlen(ssid) == 0) ||
|
||||
(pass == NULL && (security != NSAPI_SECURITY_NONE && security != NSAPI_SECURITY_WPA2_ENT)) ||
|
||||
(strlen(pass) == 0 && (security != NSAPI_SECURITY_NONE && security != NSAPI_SECURITY_WPA2_ENT)) ||
|
||||
(strlen(pass) > 63 && (security == NSAPI_SECURITY_WPA2 || security == NSAPI_SECURITY_WPA ||
|
||||
security == NSAPI_SECURITY_WPA_WPA2 || security == NSAPI_SECURITY_WPA3 || security == NSAPI_SECURITY_WPA3_WPA2))
|
||||
) {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
memset(_ssid, 0, sizeof(_ssid));
|
||||
strncpy(_ssid, ssid, sizeof(_ssid));
|
||||
|
||||
memset(_pass, 0, sizeof(_pass));
|
||||
strncpy(_pass, pass, sizeof(_pass));
|
||||
|
||||
_security = security;
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t WhdSTAInterface::connect()
|
||||
{
|
||||
ScopedMutexLock lock(_iface_shared.mutex);
|
||||
|
||||
#define MAX_RETRY_COUNT ( 5 )
|
||||
int i;
|
||||
whd_result_t res;
|
||||
|
||||
// initialize wiced, this is noop if already init
|
||||
if (!_whd_emac.powered_up) {
|
||||
if(!_whd_emac.power_up()) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
res = whd_management_set_event_handler(_whd_emac.ifp, sta_link_change_events,
|
||||
whd_wifi_link_state_change_handler, NULL, &sta_link_update_entry);
|
||||
if (res != WHD_SUCCESS) {
|
||||
return whd_toerror(res);
|
||||
}
|
||||
|
||||
_iface_shared.if_status_flags |= IF_STATUS_STA_UP;
|
||||
_iface_shared.default_if_cfg = DEFAULT_IF_STA;
|
||||
if (!_interface) {
|
||||
nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_interface = NULL;
|
||||
return err;
|
||||
}
|
||||
_interface->attach(_connection_status_cb);
|
||||
_iface_shared.iface_sta = _interface;
|
||||
} else {
|
||||
_stack.set_default_interface(_interface);
|
||||
}
|
||||
|
||||
// Initialize the Offload Manager
|
||||
if (_olm != NULL) {
|
||||
_olm->init_ols(_whd_emac.ifp, this);
|
||||
}
|
||||
|
||||
if ((_ssid == NULL) ||
|
||||
(strlen(_ssid) == 0)) {
|
||||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
// setup ssid
|
||||
whd_ssid_t ssid;
|
||||
strncpy((char *)ssid.value, _ssid, SSID_NAME_SIZE);
|
||||
ssid.value[SSID_NAME_SIZE - 1] = '\0';
|
||||
ssid.length = strlen((char *)ssid.value);
|
||||
|
||||
// choose network security
|
||||
whd_security_t security = whd_fromsecurity(_security);
|
||||
|
||||
#if defined MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK
|
||||
/* Set PSK password for WPA3_WPA2 */
|
||||
if (security == WHD_SECURITY_WPA3_WPA2_PSK) {
|
||||
res = (whd_result_t)whd_wifi_enable_sup_set_passphrase( _whd_emac.ifp, (const uint8_t *)MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK,
|
||||
strlen(MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK), WHD_SECURITY_WPA3_WPA2_PSK );
|
||||
}
|
||||
#else
|
||||
/* Set PSK password for WPA3_WPA2 */
|
||||
if (security == WHD_SECURITY_WPA3_WPA2_PSK) {
|
||||
res = (whd_result_t)whd_wifi_enable_sup_set_passphrase( _whd_emac.ifp, (const uint8_t *)_pass,
|
||||
strlen(_pass), WHD_SECURITY_WPA3_WPA2_PSK );
|
||||
}
|
||||
#endif
|
||||
// join the network
|
||||
for (i = 0; i < MAX_RETRY_COUNT; i++) {
|
||||
res = (whd_result_t)whd_wifi_join(_whd_emac.ifp,
|
||||
&ssid,
|
||||
security,
|
||||
(const uint8_t *)_pass, strlen(_pass));
|
||||
if (res == WHD_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != WHD_SUCCESS) {
|
||||
return whd_toerror(res);
|
||||
}
|
||||
|
||||
if (whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS) {
|
||||
whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_TRUE);
|
||||
}
|
||||
|
||||
// bring up
|
||||
return _interface->bringup(_dhcp,
|
||||
_ip_address[0] ? _ip_address : 0,
|
||||
_netmask[0] ? _netmask : 0,
|
||||
_gateway[0] ? _gateway : 0,
|
||||
DEFAULT_STACK);
|
||||
}
|
||||
|
||||
void WhdSTAInterface::wifi_on()
|
||||
{
|
||||
if (!_whd_emac.powered_up) {
|
||||
if(!_whd_emac.power_up()) {
|
||||
CY_ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t WhdSTAInterface::disconnect()
|
||||
{
|
||||
ScopedMutexLock lock(_iface_shared.mutex);
|
||||
|
||||
if (!_interface) {
|
||||
return NSAPI_STATUS_DISCONNECTED;
|
||||
}
|
||||
|
||||
// bring down
|
||||
int err = _interface->bringdown();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
_iface_shared.if_status_flags &= ~IF_STATUS_STA_UP;
|
||||
if (_iface_shared.if_status_flags & IF_STATUS_SOFT_AP_UP) {
|
||||
_iface_shared.default_if_cfg = DEFAULT_IF_SOFT_AP;
|
||||
_stack.set_default_interface(_iface_shared.iface_softap);
|
||||
} else {
|
||||
_iface_shared.default_if_cfg = DEFAULT_IF_NOT_SET;
|
||||
}
|
||||
|
||||
// leave network
|
||||
whd_result_t res = whd_wifi_leave(_whd_emac.ifp);
|
||||
if (res != WHD_SUCCESS) {
|
||||
return whd_toerror(res);
|
||||
}
|
||||
whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_FALSE);
|
||||
|
||||
// remove the interface added in connect
|
||||
if (_interface) {
|
||||
nsapi_error_t err = _stack.remove_ethernet_interface(&_interface);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return err;
|
||||
}
|
||||
_iface_shared.iface_sta = NULL;
|
||||
}
|
||||
|
||||
res = whd_wifi_deregister_event_handler(_whd_emac.ifp, sta_link_update_entry);
|
||||
if (res != WHD_SUCCESS) {
|
||||
return whd_toerror(res);
|
||||
}
|
||||
|
||||
// de-init Offload Manager
|
||||
if (_olm != NULL) {
|
||||
_olm->deinit_ols();
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
int8_t WhdSTAInterface::get_rssi()
|
||||
{
|
||||
int32_t rssi;
|
||||
whd_result_t res;
|
||||
|
||||
if (!_whd_emac.powered_up) {
|
||||
if(!_whd_emac.power_up()) {
|
||||
CY_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
res = (whd_result_t)whd_wifi_get_rssi(_whd_emac.ifp, &rssi);
|
||||
if (res != 0) {
|
||||
/* The network GT tests expect that this function should return 0 in case of an error and not assert */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int8_t)rssi;
|
||||
}
|
||||
|
||||
static void whd_scan_handler(whd_scan_result_t **result_ptr,
|
||||
void *user_data, whd_scan_status_t status)
|
||||
{
|
||||
|
||||
whd_scan_userdata *data = (whd_scan_userdata *)user_data;
|
||||
|
||||
/* Even after stopping scan, some results will still come as results are already present in the queue */
|
||||
if (data->scan_in_progress == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// finished scan, either succesfully or through an abort
|
||||
if (status != WHD_SCAN_INCOMPLETE) {
|
||||
data->scan_in_progress = false;
|
||||
data->sema->release();
|
||||
return;
|
||||
}
|
||||
|
||||
// can't really keep anymore scan results
|
||||
if (data->count > 0 && data->offset >= data->count) {
|
||||
/* We can not abort the scan as this function is getting executed in WHD context,
|
||||
Note that to call any WHD API, caller function should not in WHD context */
|
||||
return;
|
||||
}
|
||||
|
||||
whd_scan_result_t *record = *result_ptr;
|
||||
|
||||
for (unsigned int i = 0; i < data->result_buff->size(); i++) {
|
||||
if (CMP_MAC((*data->result_buff)[i].BSSID.octet, record->BSSID.octet)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->count > 0 && data->aps != NULL) {
|
||||
// get ap stats
|
||||
nsapi_wifi_ap ap;
|
||||
uint8_t length = record->SSID.length;
|
||||
if (length < sizeof(ap.ssid) - 1) {
|
||||
length = sizeof(ap.ssid) - 1;
|
||||
}
|
||||
memcpy(ap.ssid, record->SSID.value, length);
|
||||
ap.ssid[length] = '\0';
|
||||
|
||||
memcpy(ap.bssid, record->BSSID.octet, sizeof(ap.bssid));
|
||||
|
||||
ap.security = whd_tosecurity(record->security);
|
||||
ap.rssi = record->signal_strength;
|
||||
ap.channel = record->channel;
|
||||
if (data->sres_type == SRES_TYPE_WIFI_ACCESS_POINT) {
|
||||
data->aps[data->offset] = WiFiAccessPoint(ap);
|
||||
} else if (data->sres_type == SRES_TYPE_WHD_ACCESS_POINT) {
|
||||
WhdAccessPoint *aps_sres = static_cast<WhdAccessPoint *>(data->aps);
|
||||
aps_sres[data->offset] = std::move(WhdAccessPoint(ap, record->bss_type,
|
||||
record->ie_ptr, record->ie_len));
|
||||
}
|
||||
}
|
||||
|
||||
// store to result_buff for future duplication removal
|
||||
data->result_buff->push_back(*record);
|
||||
data->offset = data->result_buff->size();
|
||||
}
|
||||
|
||||
int WhdSTAInterface::internal_scan(WiFiAccessPoint *aps, unsigned count, scan_result_type sres_type)
|
||||
{
|
||||
ScopedMutexLock lock(_iface_shared.mutex);
|
||||
|
||||
// initialize wiced, this is noop if already init
|
||||
if (!_whd_emac.powered_up) {
|
||||
if(!_whd_emac.power_up()) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
interal_scan_data.sema = new Semaphore();
|
||||
interal_scan_data.sres_type = sres_type;
|
||||
interal_scan_data.aps = aps;
|
||||
interal_scan_data.count = count;
|
||||
interal_scan_data.offset = 0;
|
||||
interal_scan_data.scan_in_progress = true;
|
||||
interal_scan_data.result_buff = new std::vector<whd_scan_result_t>();
|
||||
whd_result_t whd_res;
|
||||
int res;
|
||||
|
||||
whd_res = (whd_result_t)whd_wifi_scan(_whd_emac.ifp, WHD_SCAN_TYPE_ACTIVE, WHD_BSS_TYPE_ANY,
|
||||
NULL, NULL, NULL, NULL, whd_scan_handler, &internal_scan_result, &interal_scan_data);
|
||||
if (whd_res != WHD_SUCCESS) {
|
||||
res = whd_toerror(whd_res);
|
||||
} else {
|
||||
interal_scan_data.sema->acquire();
|
||||
res = interal_scan_data.offset;
|
||||
}
|
||||
|
||||
delete interal_scan_data.sema;
|
||||
delete interal_scan_data.result_buff;
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::scan(WiFiAccessPoint *aps, unsigned count)
|
||||
{
|
||||
return internal_scan(aps, count, SRES_TYPE_WIFI_ACCESS_POINT);
|
||||
}
|
||||
|
||||
int WhdSTAInterface::scan_whd(WhdAccessPoint *aps, unsigned count)
|
||||
{
|
||||
return internal_scan(aps, count, SRES_TYPE_WHD_ACCESS_POINT);
|
||||
}
|
||||
|
||||
int WhdSTAInterface::is_interface_connected(void)
|
||||
{
|
||||
if (!_whd_emac.ifp) {
|
||||
return WHD_INTERFACE_NOT_UP;
|
||||
}
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
if ((whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS)) {
|
||||
return WHD_SUCCESS;
|
||||
} else {
|
||||
return WHD_CONNECTION_LOST;
|
||||
}
|
||||
}
|
||||
|
||||
int WhdSTAInterface::get_bssid(uint8_t *bssid)
|
||||
{
|
||||
whd_mac_t ap_mac;
|
||||
whd_result_t res = WHD_SUCCESS;
|
||||
|
||||
memset(&ap_mac, 0, sizeof(ap_mac));
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
if ((whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS)) {
|
||||
res = whd_wifi_get_bssid(_whd_emac.ifp, &ap_mac);
|
||||
|
||||
if (res == WHD_SUCCESS) {
|
||||
memcpy(bssid, ap_mac.octet, sizeof(ap_mac.octet));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::whd_log_print(void)
|
||||
{
|
||||
return whd_wifi_print_whd_log(_whd_emac.drvp);
|
||||
}
|
||||
|
||||
int WhdSTAInterface::whd_log_read(char *buffer, int buffer_size)
|
||||
{
|
||||
whd_result_t res = WHD_SUCCESS;
|
||||
if (buffer != NULL) {
|
||||
res = whd_wifi_read_wlan_log(_whd_emac.drvp, buffer, buffer_size);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsapi_error_t WhdSTAInterface::wifi_get_ac_params_sta(void *acp)
|
||||
{
|
||||
whd_result_t res = WHD_SUCCESS;
|
||||
edcf_acparam_t *ac_param = (edcf_acparam_t *)acp;
|
||||
|
||||
res = whd_wifi_get_acparams(_whd_emac.ifp, ac_param);
|
||||
if (res != WHD_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_set_iovar_value(const char *iovar, uint32_t value)
|
||||
{
|
||||
whd_result_t res = WHD_SUCCESS;
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
res = whd_wifi_set_iovar_value(_whd_emac.ifp, iovar, value);
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_get_iovar_value(const char *iovar, uint32_t *value)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
res = whd_wifi_get_iovar_value(_whd_emac.ifp, iovar, value);
|
||||
return res;
|
||||
}
|
||||
int WhdSTAInterface::wifi_set_ioctl_value(uint32_t ioctl, uint32_t value)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
res = whd_wifi_set_ioctl_value(_whd_emac.ifp, ioctl, value);
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_get_ioctl_value(uint32_t ioctl, uint32_t *value )
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
res = whd_wifi_get_ioctl_value(_whd_emac.ifp, ioctl, value);
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_get_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
res = whd_wifi_get_ioctl_buffer(_whd_emac.ifp, ioctl, buffer, len);
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_set_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
_whd_emac.ifp->role = WHD_STA_ROLE;
|
||||
res = whd_wifi_set_ioctl_buffer(_whd_emac.ifp, ioctl, buffer, len);
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_get_ifp(whd_interface_t *ifp)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
*ifp = _whd_emac.ifp;
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_set_up(void)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
res = whd_wifi_set_up(_whd_emac.ifp);
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_set_down(void)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
res = whd_wifi_set_down(_whd_emac.ifp);
|
||||
return res;
|
||||
}
|
||||
|
||||
int WhdSTAInterface::wifi_set_coex_config(whd_coex_config_t *coex_config)
|
||||
{
|
||||
int res = WHD_SUCCESS;
|
||||
res = whd_wifi_set_coex_config(_whd_emac.ifp, coex_config);
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/* WHD implementation of NetworkInterfaceAPI
|
||||
* Copyright (c) 2017-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WHD_STA_INTERFACE_H
|
||||
#define WHD_STA_INTERFACE_H
|
||||
|
||||
#include "netsocket/WiFiInterface.h"
|
||||
#include "netsocket/EMACInterface.h"
|
||||
#include "netsocket/OnboardNetworkStack.h"
|
||||
#include "WhdAccessPoint.h"
|
||||
#include "whd_emac.h"
|
||||
#include "whd_interface.h"
|
||||
#include "whd_types_int.h"
|
||||
|
||||
struct ol_desc;
|
||||
|
||||
/** WhdSTAInterface class
|
||||
* Implementation of the NetworkStack for the WHD
|
||||
*/
|
||||
class WhdSTAInterface : public WiFiInterface, public EMACInterface {
|
||||
public:
|
||||
class OlmInterface {
|
||||
public:
|
||||
/** Get the default OLM interface. */
|
||||
static OlmInterface &get_default_instance();
|
||||
|
||||
OlmInterface(struct ol_desc *list = NULL) {}
|
||||
|
||||
virtual int init_ols(void *whd, void *ip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual int sleep()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual int wake()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void deinit_ols(void) {}
|
||||
};
|
||||
|
||||
WhdSTAInterface(
|
||||
WHD_EMAC &emac = WHD_EMAC::get_instance(),
|
||||
OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance(),
|
||||
OlmInterface &olm = OlmInterface::get_default_instance(),
|
||||
whd_interface_shared_info_t &shared = whd_iface_shared);
|
||||
|
||||
static WhdSTAInterface *get_default_instance();
|
||||
|
||||
/* Turn on the wifi device*/
|
||||
void wifi_on();
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
|
||||
* If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
|
||||
*
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
nsapi_error_t connect();
|
||||
|
||||
/** Start the interface
|
||||
*
|
||||
* Attempts to connect to a WiFi network.
|
||||
*
|
||||
* @param ssid Name of the network to connect to
|
||||
* @param pass Security passphrase to connect to the network
|
||||
* @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
|
||||
* @param channel This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
|
||||
* @return 0 on success, or error code on failure
|
||||
*/
|
||||
nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0);
|
||||
|
||||
/** Stop the interface
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
nsapi_error_t disconnect();
|
||||
|
||||
/** Set the WiFi network credentials
|
||||
*
|
||||
* @param ssid Name of the network to connect to
|
||||
* @param pass Security passphrase to connect to the network
|
||||
* @param security Type of encryption for connection
|
||||
* (defaults to NSAPI_SECURITY_NONE)
|
||||
* @return 0 on success, or error code on failure
|
||||
*/
|
||||
nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
|
||||
|
||||
/** Set the WiFi network channel - NOT SUPPORTED
|
||||
*
|
||||
* This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
|
||||
*
|
||||
* @param channel Channel on which the connection is to be made, or 0 for any (Default: 0)
|
||||
* @return Not supported, returns NSAPI_ERROR_UNSUPPORTED
|
||||
*/
|
||||
nsapi_error_t set_channel(uint8_t channel)
|
||||
{
|
||||
if (channel != 0) {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Set blocking status of interface.
|
||||
* Nonblocking mode unsupported.
|
||||
*
|
||||
* @param blocking true if connect is blocking
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
nsapi_error_t set_blocking(bool blocking)
|
||||
{
|
||||
if (blocking) {
|
||||
_blocking = blocking;
|
||||
return NSAPI_ERROR_OK;
|
||||
} else {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the current radio signal strength for active connection
|
||||
*
|
||||
* @return Connection strength in dBm (negative value)
|
||||
*/
|
||||
int8_t get_rssi();
|
||||
|
||||
/** Scan for available networks in WiFiAccessPoint format
|
||||
*
|
||||
* This function will block.
|
||||
*
|
||||
* @param ap Pointer to allocated array of WiFiAccessPoint format for discovered AP
|
||||
* @param count Size of allocated @a res array, or 0 to only count available AP
|
||||
* @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0)
|
||||
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int scan(WiFiAccessPoint *res, unsigned count);
|
||||
|
||||
/** Scan for available networks in WhdAccessPoint format
|
||||
*
|
||||
* This function will block.
|
||||
*
|
||||
* @param ap Pointer to allocated array of WhdAccessPoint format for discovered AP
|
||||
* @param count Size of allocated @a res array, or 0 to only count available AP
|
||||
* @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0)
|
||||
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int scan_whd(WhdAccessPoint *res, unsigned count);
|
||||
|
||||
/* is interface connected, if yes return WICED_SUCCESS else WICED_NOT_CONNECTED */
|
||||
int is_interface_connected();
|
||||
|
||||
/* get bssid of the AP if success return WICED_SUCCESS else WICED_ERROR */
|
||||
int get_bssid(uint8_t *bssid);
|
||||
|
||||
/* print WHD log (this routine will malloc/free a buffer
|
||||
* You need to enable printing with WHD_LOGGING_BUFFER_ENABLE
|
||||
*/
|
||||
int whd_log_print(void);
|
||||
|
||||
/* read WHD log */
|
||||
int whd_log_read(char *buffer, int buffer_size);
|
||||
|
||||
/* Get EDCF AC params */
|
||||
nsapi_error_t wifi_get_ac_params_sta(void *ac_param);
|
||||
|
||||
/* get iovar value */
|
||||
int wifi_get_iovar_value(const char *iovar, uint32_t *value);
|
||||
|
||||
/* set iovar value */
|
||||
int wifi_set_iovar_value(const char *iovar, uint32_t value);
|
||||
|
||||
/* set ioctl value */
|
||||
int wifi_set_ioctl_value(uint32_t ioctl, uint32_t value) ;
|
||||
|
||||
/* get ioctl value */
|
||||
int wifi_get_ioctl_value(uint32_t ioctl, uint32_t *value);
|
||||
|
||||
/* get ioctl buffer */
|
||||
int wifi_get_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len);
|
||||
|
||||
/* set ioctl buffer */
|
||||
int wifi_set_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len);
|
||||
|
||||
/* get WHD ifp value */
|
||||
int wifi_get_ifp(whd_interface_t *ifp);
|
||||
|
||||
/* set wifi interface up */
|
||||
int wifi_set_up(void);
|
||||
|
||||
/* set wifi interface down */
|
||||
int wifi_set_down(void);
|
||||
|
||||
/* set wifi coex configuration */
|
||||
int wifi_set_coex_config(whd_coex_config_t *coex_config);
|
||||
|
||||
/** Set Offload Manager Information
|
||||
* NOTE: Only allowed while disconnected
|
||||
*
|
||||
* @param olm Offload Manager info structure
|
||||
* @return true if completed successfully
|
||||
* false if Interface is connected
|
||||
*/
|
||||
int set_olm(OlmInterface *olm)
|
||||
{
|
||||
if (get_connection_status() == NSAPI_STATUS_DISCONNECTED) {
|
||||
_olm = olm;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Network stack is suspended
|
||||
*
|
||||
* @return 0 if successful
|
||||
*/
|
||||
int net_suspended()
|
||||
{
|
||||
int ret = _olm->sleep();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Network stack is resuming
|
||||
*
|
||||
* @return 0 if successful
|
||||
*/
|
||||
int net_resuming()
|
||||
{
|
||||
int ret = _olm->wake();
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected:
|
||||
int internal_scan(WiFiAccessPoint *aps, unsigned count, scan_result_type sres_type);
|
||||
|
||||
private:
|
||||
char _ssid[33]; /* The longest possible name (defined in 802.11) +1 for the \0 */
|
||||
char _pass[64]; /* The longest allowed passphrase + 1 */
|
||||
nsapi_security_t _security;
|
||||
WHD_EMAC &_whd_emac;
|
||||
OlmInterface *_olm;
|
||||
whd_interface_shared_info_t &_iface_shared;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nsapi.h"
|
||||
#include "lwipopts.h"
|
||||
#include "WhdSoftAPInterface.h"
|
||||
#include "nsapi.h"
|
||||
#include "lwipopts.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "rtos.h"
|
||||
#include "whd_emac.h"
|
||||
#include "whd_wifi_api.h"
|
||||
|
||||
|
||||
extern int whd_toerror(whd_result_t res);
|
||||
extern nsapi_security_t whd_tosecurity(whd_security_t sec);
|
||||
extern whd_security_t whd_fromsecurity(nsapi_security_t sec);
|
||||
extern "C" void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up);
|
||||
|
||||
static const whd_event_num_t ap_events[] = { WLC_E_LINK, WLC_E_IF, WLC_E_DEAUTH, WLC_E_DEAUTH_IND, WLC_E_DISASSOC, WLC_E_DISASSOC_IND, WLC_E_ASSOC_IND, WLC_E_REASSOC_IND, WLC_E_NONE };
|
||||
|
||||
static void *whd_default_handle_softap_events(whd_interface_t ifp, const whd_event_header_t *event_header,
|
||||
const uint8_t *event_data, void *handler_user_data)
|
||||
{
|
||||
whd_driver_t whd_driver = ifp->whd_driver;
|
||||
|
||||
UNUSED_PARAMETER(event_header);
|
||||
UNUSED_PARAMETER(event_data);
|
||||
UNUSED_PARAMETER(handler_user_data);
|
||||
|
||||
WHD_IOCTL_LOG_ADD_EVENT(whd_driver, event_header->event_type, event_header->flags, event_header->reason);
|
||||
|
||||
if ((event_header->event_type == (whd_event_num_t)WLC_E_LINK) ||
|
||||
(event_header->event_type == WLC_E_IF)) {
|
||||
if (osSemaphoreGetCount(whd_driver->ap_info.whd_wifi_sleep_flag) < 1) {
|
||||
osStatus_t result = osSemaphoreRelease(whd_driver->ap_info.whd_wifi_sleep_flag);
|
||||
if (result != osOK) {
|
||||
printf("Release whd_wifi_sleep_flag ERROR: %d", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return handler_user_data;
|
||||
}
|
||||
|
||||
|
||||
WhdSoftAPInterface::WhdSoftAPInterface(WHD_EMAC &emac, OnboardNetworkStack &stack, whd_interface_shared_info_t &shared)
|
||||
: EMACInterface(emac, stack),
|
||||
_whd_emac(emac),
|
||||
_iface_shared(shared)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
int WhdSoftAPInterface::start(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel,
|
||||
bool start_dhcp_server, const whd_custom_ie_info_t *ie_info, bool ap_sta_concur)
|
||||
{
|
||||
ScopedMutexLock lock(_iface_shared.mutex);
|
||||
|
||||
nsapi_error_t err;
|
||||
// power up primary emac interface first
|
||||
if (ap_sta_concur) {
|
||||
WHD_EMAC &emac_prime = WHD_EMAC::get_instance(WHD_STA_ROLE);
|
||||
if (!emac_prime.power_up()) {
|
||||
printf("Primary interface power up ERROR!\n");
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// set concurrency mode and power up secondary, the bsp init is done by primary emac
|
||||
_whd_emac.ap_sta_concur = ap_sta_concur;
|
||||
if (!_whd_emac.power_up()) {
|
||||
printf("Secondary interface power up ERROR!\n");
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
// setup ssid
|
||||
whd_ssid_t whd_ssid;
|
||||
strncpy((char *)whd_ssid.value, ssid, SSID_NAME_SIZE);
|
||||
whd_ssid.value[SSID_NAME_SIZE - 1] = '\0';
|
||||
whd_ssid.length = strlen((char *)whd_ssid.value);
|
||||
|
||||
// choose network security
|
||||
whd_security_t whd_security = whd_fromsecurity(security);
|
||||
|
||||
/* set up the AP info */
|
||||
err = whd_wifi_init_ap(_whd_emac.ifp, &whd_ssid, whd_security, (const uint8_t *)pass,
|
||||
strlen(pass), channel);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
printf("whd_wifi_init_ap() ERROR: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// update default softap interface event handler
|
||||
err = unregister_event_handler();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
printf("unregister_event_handler() ERROR: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
err = register_event_handler(whd_default_handle_softap_events);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
printf("register_event_handler() ERROR: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
_iface_shared.if_status_flags |= IF_STATUS_SOFT_AP_UP;
|
||||
if (!ap_sta_concur || (_iface_shared.default_if_cfg == DEFAULT_IF_NOT_SET)) {
|
||||
_iface_shared.default_if_cfg = DEFAULT_IF_SOFT_AP;
|
||||
}
|
||||
if (!_interface) {
|
||||
nsapi_error_t err = _stack.add_ethernet_interface(_whd_emac, _iface_shared.default_if_cfg == DEFAULT_IF_SOFT_AP, &_interface);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
_interface = NULL;
|
||||
return err;
|
||||
}
|
||||
_interface->attach(_connection_status_cb);
|
||||
_iface_shared.iface_softap = _interface;
|
||||
} else if (_iface_shared.default_if_cfg == DEFAULT_IF_SOFT_AP) {
|
||||
_stack.set_default_interface(_interface);
|
||||
}
|
||||
|
||||
if (ie_info) {
|
||||
err = whd_wifi_manage_custom_ie(_whd_emac.ifp, WHD_ADD_CUSTOM_IE, (const uint8_t *)ie_info->oui,
|
||||
ie_info->subtype, (const void *)ie_info->data, ie_info->length, ie_info->which_packets);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
printf("whd_wifi_manage_custom_ie() ERROR: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = whd_wifi_start_ap(_whd_emac.ifp);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
printf("whd_wifi_start_ap() ERROR: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// Set static IP address for SoftAP and bring up
|
||||
set_dhcp(false);
|
||||
|
||||
if (whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS) {
|
||||
whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_TRUE);
|
||||
}
|
||||
|
||||
err = _interface->bringup(_dhcp,
|
||||
_ip_address[0] ? _ip_address : 0,
|
||||
_netmask[0] ? _netmask : 0,
|
||||
_gateway[0] ? _gateway : 0,
|
||||
DEFAULT_STACK);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
printf("bringup() ERROR: %d\n", err);
|
||||
}
|
||||
|
||||
if (start_dhcp_server) {
|
||||
_dhcp_server = std::make_unique<CyDhcpServer>(get_stack(), this);
|
||||
if (CY_RSLT_SUCCESS != _dhcp_server->start()) {
|
||||
err = NSAPI_ERROR_DHCP_FAILURE;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int WhdSoftAPInterface::stop(void)
|
||||
{
|
||||
ScopedMutexLock lock(_iface_shared.mutex);
|
||||
|
||||
if (_dhcp_server && CY_RSLT_SUCCESS != _dhcp_server->stop()) {
|
||||
return NSAPI_ERROR_DHCP_FAILURE;
|
||||
}
|
||||
_dhcp_server.reset();
|
||||
|
||||
// bring down
|
||||
int err = _interface->bringdown();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
_iface_shared.if_status_flags &= ~IF_STATUS_SOFT_AP_UP;
|
||||
if ((_iface_shared.if_status_flags & IF_STATUS_STA_UP) == 0) {
|
||||
_iface_shared.default_if_cfg = DEFAULT_IF_NOT_SET;
|
||||
}
|
||||
|
||||
// stop softap
|
||||
whd_result_t res = whd_wifi_stop_ap(_whd_emac.ifp);
|
||||
if (res != WHD_SUCCESS) {
|
||||
return whd_toerror(res);
|
||||
}
|
||||
|
||||
// remove the interface added in start
|
||||
if (_interface) {
|
||||
nsapi_error_t err = _stack.remove_ethernet_interface(&_interface);
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return err;
|
||||
}
|
||||
_iface_shared.iface_softap = NULL;
|
||||
}
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
int WhdSoftAPInterface::remove_custom_ie(const whd_custom_ie_info_t *ie_info)
|
||||
{
|
||||
return whd_wifi_manage_custom_ie(_whd_emac.ifp, WHD_REMOVE_CUSTOM_IE, (const uint8_t *)ie_info->oui,
|
||||
ie_info->subtype, (const void *)ie_info->data, ie_info->length, ie_info->which_packets);
|
||||
}
|
||||
|
||||
int WhdSoftAPInterface::get_associated_client_list(void *client_list_buffer, uint16_t buffer_length)
|
||||
{
|
||||
|
||||
return whd_wifi_get_associated_client_list(_whd_emac.ifp, client_list_buffer, buffer_length);
|
||||
}
|
||||
|
||||
int WhdSoftAPInterface::register_event_handler(whd_event_handler_t softap_event_handler)
|
||||
{
|
||||
uint16_t ap_events_entry = _whd_emac.ifp->event_reg_list[WHD_AP_EVENT_ENTRY];
|
||||
return whd_management_set_event_handler(_whd_emac.ifp, ap_events, softap_event_handler, NULL, &ap_events_entry);
|
||||
}
|
||||
|
||||
int WhdSoftAPInterface::unregister_event_handler(void)
|
||||
{
|
||||
return whd_wifi_deregister_event_handler(_whd_emac.ifp, _whd_emac.ifp->event_reg_list[WHD_AP_EVENT_ENTRY]);
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WHD_SOFTAP_INTERFACE_H
|
||||
#define WHD_SOFTAP_INTERFACE_H
|
||||
|
||||
#include "netsocket/EMACInterface.h"
|
||||
#include "netsocket/OnboardNetworkStack.h"
|
||||
#include "whd_emac.h"
|
||||
#include "CyDhcpServer.h"
|
||||
#include "whd_interface.h"
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* Vendor IE details
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t oui[WIFI_IE_OUI_LENGTH]; /**< Unique identifier for the IE */
|
||||
uint8_t subtype; /**< Sub-type of the IE */
|
||||
void *data; /**< Pointer to IE data */
|
||||
uint16_t length; /**< IE data length */
|
||||
uint16_t which_packets; /**< Mask of the packet in which this IE details to be included */
|
||||
} whd_custom_ie_info_t;
|
||||
|
||||
|
||||
|
||||
/** WhdSoftAPInterface class
|
||||
* Implementation of the SoftAPInterface for the Whd
|
||||
*/
|
||||
class WhdSoftAPInterface : public EMACInterface {
|
||||
public:
|
||||
/** Construct SoftAP interface
|
||||
* @return pointer to default WhdSoftAPInterface instance
|
||||
*/
|
||||
WhdSoftAPInterface(WHD_EMAC &emac = WHD_EMAC::get_instance(WHD_AP_ROLE),
|
||||
OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance(),
|
||||
whd_interface_shared_info_t &shared = whd_iface_shared);
|
||||
|
||||
/** Get the default WhdSoftAPInterface instance.
|
||||
* @return pointer to default WhdSoftAPInterface instance
|
||||
*/
|
||||
static WhdSoftAPInterface *get_default_instance();
|
||||
|
||||
/** Set static IP address for SoftAP
|
||||
*
|
||||
* Configures the static IP address of SoftAP
|
||||
* Requires that the network is stopped.
|
||||
*
|
||||
* @param ip_address Null-terminated representation of the local IP address
|
||||
* @param netmask Null-terminated representation of the local network mask
|
||||
* @param gateway Null-terminated representation of the local gateway
|
||||
* @return 0 on success, negative error code on failure
|
||||
* int set_network(const char *ip_address, const char *netmask, const char *gateway);
|
||||
*/
|
||||
|
||||
/** Start a SoftAP
|
||||
*
|
||||
* @param ssid Name of the SoftAP to create
|
||||
* @param pass Security passphrase for connection to SoftAP
|
||||
* @param security Type of encryption for connection
|
||||
* @param channel Channel for SoftAP
|
||||
* @param start_dhcp_server Start dhcp server for connection
|
||||
* @param whd_custom_ie Optional Custom IE
|
||||
* @param ap_sta_concur Enable STA+AP concurrency mode
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int start(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel,
|
||||
bool start_dhcp_server = true, const whd_custom_ie_info_t *ie_info = NULL, bool ap_sta_concur = false);
|
||||
|
||||
/**
|
||||
* Remove Wi-Fi custom IE
|
||||
*
|
||||
* @param[in] ie_info : Pointer to the structure which contains custom IE information
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int remove_custom_ie(const whd_custom_ie_info_t *ie_info);
|
||||
|
||||
/** Stop the Software Access Point
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int stop(void);
|
||||
|
||||
/**
|
||||
* Gets information about associated clients.
|
||||
*
|
||||
* @note Only applicable if softAP interface is up
|
||||
*
|
||||
* @param[out] client_list_buffer : pointer to a buffer that will be populated with a variable length structure defined by @ref whd_maclist_t
|
||||
* @param[in] buffer_length : length of the buffer
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int get_associated_client_list(void *client_list_buffer, uint16_t buffer_length);
|
||||
|
||||
|
||||
/**
|
||||
* Register soft AP event handler
|
||||
*
|
||||
* @param[in] softap_event_handler : A function pointer to the event handler
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int register_event_handler(whd_event_handler_t softap_event_handler);
|
||||
|
||||
/**
|
||||
* Unregister soft AP event handler
|
||||
*
|
||||
* @return 0 on success, or error code on failure
|
||||
* see @a nsapi_error
|
||||
*/
|
||||
int unregister_event_handler(void);
|
||||
|
||||
/** Set blocking status of interface.
|
||||
* Nonblocking mode unsupported.
|
||||
*
|
||||
* @param blocking true if connect is blocking
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
nsapi_error_t set_blocking(bool blocking)
|
||||
{
|
||||
if (blocking) {
|
||||
_blocking = blocking;
|
||||
return NSAPI_ERROR_OK;
|
||||
} else {
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
WHD_EMAC &_whd_emac;
|
||||
std::unique_ptr<CyDhcpServer> _dhcp_server;
|
||||
whd_interface_shared_info_t &_iface_shared;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2019 Cypress Semiconductor Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef INCLUDED_EMAC_EAPOL_H_
|
||||
#define INCLUDED_EMAC_EAPOL_H_
|
||||
|
||||
#include "whd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
#define EAPOL_PACKET_TYPE (0x888E)
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
|
||||
typedef whd_buffer_t whd_eapol_packet_t;
|
||||
|
||||
typedef void (*eapol_packet_handler_t)(whd_interface_t interface, whd_buffer_t buffer);
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Global Variables
|
||||
******************************************************/
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
whd_result_t emac_register_eapol_packet_handler(eapol_packet_handler_t eapol_packet_handler);
|
||||
void emac_unregister_eapol_packet_handler(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* ifndef INCLUDED_EMAC_EAPOL_H_ */
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cmsis_os.h"
|
||||
#include "whd_emac.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "events/mbed_shared_queues.h"
|
||||
#include "whd_wlioctl.h"
|
||||
#include "whd_buffer_api.h"
|
||||
#include "cybsp_wifi.h"
|
||||
#include "emac_eapol.h"
|
||||
#include "cy_result.h"
|
||||
|
||||
#define NULL_MAC(a) ( ( ( ( (unsigned char *)a )[0] ) == 0 ) && \
|
||||
( ( ( (unsigned char *)a )[1] ) == 0 ) && \
|
||||
( ( ( (unsigned char *)a )[2] ) == 0 ) && \
|
||||
( ( ( (unsigned char *)a )[3] ) == 0 ) && \
|
||||
( ( ( (unsigned char *)a )[4] ) == 0 ) && \
|
||||
( ( ( (unsigned char *)a )[5] ) == 0 ) )
|
||||
|
||||
extern "C"
|
||||
{
|
||||
eapol_packet_handler_t emac_eapol_packet_handler = NULL;
|
||||
void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up);
|
||||
} // extern "C"
|
||||
|
||||
WHD_EMAC::WHD_EMAC(whd_interface_role_t role, const uint8_t *mac_addr)
|
||||
: interface_type(role)
|
||||
{
|
||||
if (mac_addr) {
|
||||
set_hwaddr(mac_addr);
|
||||
}
|
||||
}
|
||||
|
||||
WHD_EMAC &WHD_EMAC::get_instance(whd_interface_role_t role, const uint8_t *mac_addr)
|
||||
{
|
||||
static WHD_EMAC emac_sta(WHD_STA_ROLE, mac_addr);
|
||||
static WHD_EMAC emac_ap(WHD_AP_ROLE, mac_addr);
|
||||
return role == WHD_AP_ROLE ? emac_ap : emac_sta;
|
||||
}
|
||||
|
||||
uint32_t WHD_EMAC::get_mtu_size() const
|
||||
{
|
||||
return WHD_PAYLOAD_MTU;
|
||||
}
|
||||
|
||||
uint32_t WHD_EMAC::get_align_preference() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WHD_EMAC::add_multicast_group(const uint8_t *addr)
|
||||
{
|
||||
memcpy(multicast_addr.octet, addr, sizeof(multicast_addr.octet));
|
||||
whd_wifi_register_multicast_address(ifp, &multicast_addr);
|
||||
}
|
||||
|
||||
void WHD_EMAC::remove_multicast_group(const uint8_t *addr)
|
||||
{
|
||||
whd_wifi_unregister_multicast_address(ifp, &multicast_addr);
|
||||
}
|
||||
|
||||
void WHD_EMAC::set_all_multicast(bool all)
|
||||
{
|
||||
/* No-op at this stage */
|
||||
}
|
||||
|
||||
void WHD_EMAC::power_down()
|
||||
{
|
||||
if (powered_up) {
|
||||
powered_up = false;
|
||||
whd_wifi_off(ifp);
|
||||
whd_deinit(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
bool WHD_EMAC::power_up()
|
||||
{
|
||||
if (!powered_up) {
|
||||
cy_rslt_t res = CY_RSLT_SUCCESS;
|
||||
if (ap_sta_concur && interface_type == WHD_AP_ROLE) {
|
||||
WHD_EMAC &emac_prime = WHD_EMAC::get_instance(WHD_STA_ROLE);
|
||||
if (NULL_MAC(unicast_addr.octet)) {
|
||||
emac_prime.get_hwaddr(unicast_addr.octet);
|
||||
// Generated mac will set locally administered bit 1 of first byte
|
||||
unicast_addr.octet[0] |= (1 << 1);
|
||||
}
|
||||
// Note: This assumes that the primary interface initializes the
|
||||
// wifi driver and turns on the wifi chip.
|
||||
res = cybsp_wifi_init_secondary(&ifp /* Out */, &unicast_addr);
|
||||
} else {
|
||||
WHD_EMAC &emac_other = WHD_EMAC::get_instance(interface_type == WHD_STA_ROLE ? WHD_AP_ROLE :
|
||||
WHD_STA_ROLE);
|
||||
if (!emac_other.powered_up) {
|
||||
res = cybsp_wifi_init_primary(&ifp /* OUT */);
|
||||
} else {
|
||||
ifp = emac_other.ifp;
|
||||
}
|
||||
}
|
||||
|
||||
if (CY_RSLT_SUCCESS == res) {
|
||||
drvp = cybsp_get_wifi_driver();
|
||||
powered_up = true;
|
||||
if (link_state && emac_link_state_cb) {
|
||||
emac_link_state_cb(link_state);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WHD_EMAC::get_hwaddr(uint8_t *addr) const
|
||||
{
|
||||
if (!NULL_MAC(unicast_addr.octet)) {
|
||||
memcpy(addr, unicast_addr.octet, sizeof(unicast_addr.octet));
|
||||
} else {
|
||||
whd_mac_t mac;
|
||||
whd_result_t res = whd_wifi_get_mac_address(ifp, &mac);
|
||||
MBED_ASSERT(res == WHD_SUCCESS);
|
||||
memcpy(addr, mac.octet, sizeof(mac.octet));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WHD_EMAC::set_hwaddr(const uint8_t *addr)
|
||||
{
|
||||
memcpy(unicast_addr.octet, addr, sizeof(unicast_addr.octet));
|
||||
}
|
||||
|
||||
uint8_t WHD_EMAC::get_hwaddr_size() const
|
||||
{
|
||||
whd_mac_t mac;
|
||||
return sizeof(mac.octet);
|
||||
}
|
||||
|
||||
void WHD_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
|
||||
{
|
||||
emac_link_input_cb = input_cb;
|
||||
}
|
||||
|
||||
void WHD_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
|
||||
{
|
||||
emac_link_state_cb = state_cb;
|
||||
}
|
||||
|
||||
void WHD_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
|
||||
{
|
||||
memory_manager = &mem_mngr;
|
||||
}
|
||||
|
||||
bool WHD_EMAC::link_out(emac_mem_buf_t *buf)
|
||||
{
|
||||
uint16_t offset = 64;
|
||||
whd_buffer_t buffer;
|
||||
|
||||
uint16_t size = memory_manager->get_total_len(buf);
|
||||
|
||||
whd_result_t res = whd_host_buffer_get(drvp, &buffer, WHD_NETWORK_TX, size + offset, WHD_TRUE);
|
||||
if (res != WHD_SUCCESS) {
|
||||
memory_manager->free(buf);
|
||||
return true;
|
||||
}
|
||||
MBED_ASSERT(res == WHD_SUCCESS);
|
||||
|
||||
whd_buffer_add_remove_at_front(drvp, &buffer, offset);
|
||||
|
||||
void *dest = whd_buffer_get_current_piece_data_pointer(drvp, buffer);
|
||||
memory_manager->copy_from_buf(dest, size, buf);
|
||||
|
||||
if (activity_cb) {
|
||||
activity_cb(true);
|
||||
}
|
||||
whd_network_send_ethernet_data(ifp, buffer);
|
||||
memory_manager->free(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WHD_EMAC::get_ifname(char *name, uint8_t size) const
|
||||
{
|
||||
switch (interface_type) {
|
||||
case WHD_STA_ROLE:
|
||||
memcpy(name, "st", size);
|
||||
break;
|
||||
case WHD_AP_ROLE:
|
||||
memcpy(name, "ap", size);
|
||||
break;
|
||||
default:
|
||||
memcpy(name, "wh", size);
|
||||
}
|
||||
}
|
||||
|
||||
void WHD_EMAC::set_activity_cb(mbed::Callback<void(bool)> cb)
|
||||
{
|
||||
activity_cb = cb;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
static void emac_receive_eapol_packet(whd_interface_t interface, whd_buffer_t buffer)
|
||||
{
|
||||
if (buffer != NULL) {
|
||||
if (emac_eapol_packet_handler != NULL) {
|
||||
|
||||
emac_eapol_packet_handler(interface, buffer);
|
||||
} else {
|
||||
whd_buffer_release(interface->whd_driver, buffer, WHD_NETWORK_RX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
whd_result_t emac_register_eapol_packet_handler(eapol_packet_handler_t eapol_packet_handler)
|
||||
{
|
||||
|
||||
if (emac_eapol_packet_handler == NULL) {
|
||||
emac_eapol_packet_handler = eapol_packet_handler;
|
||||
return WHD_SUCCESS;
|
||||
}
|
||||
|
||||
return WHD_HANDLER_ALREADY_REGISTERED;
|
||||
}
|
||||
|
||||
void emac_unregister_eapol_packet_handler(void)
|
||||
{
|
||||
emac_eapol_packet_handler = NULL;
|
||||
}
|
||||
|
||||
void cy_network_process_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer)
|
||||
{
|
||||
emac_mem_buf_t *mem_buf = NULL;
|
||||
|
||||
WHD_EMAC &emac = WHD_EMAC::get_instance(ifp->role);
|
||||
|
||||
if (!emac.powered_up || !emac.emac_link_input_cb) {
|
||||
// ignore any trailing packets
|
||||
whd_buffer_release(emac.drvp, buffer, WHD_NETWORK_RX);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *data = whd_buffer_get_current_piece_data_pointer(emac.drvp, buffer);
|
||||
|
||||
uint16_t size = whd_buffer_get_current_piece_size(emac.drvp, buffer);
|
||||
|
||||
|
||||
if (size > WHD_ETHERNET_SIZE) {
|
||||
|
||||
uint16_t ethertype;
|
||||
|
||||
ethertype = (uint16_t)(data[12] << 8 | data[13]);
|
||||
|
||||
if (ethertype == EAPOL_PACKET_TYPE) {
|
||||
|
||||
/* pass it to the EAP layer, but do not release the packet */
|
||||
emac_receive_eapol_packet(ifp, buffer);
|
||||
|
||||
} else {
|
||||
mem_buf = buffer;
|
||||
if (emac.activity_cb) {
|
||||
emac.activity_cb(false);
|
||||
}
|
||||
emac.emac_link_input_cb(mem_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up)
|
||||
{
|
||||
WHD_EMAC &emac = WHD_EMAC::get_instance(ifp->role);
|
||||
|
||||
emac.link_state = state_up;
|
||||
if (emac.emac_link_state_cb) {
|
||||
emac.emac_link_state_cb(state_up);
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WHD_EMAC_H_
|
||||
#define WHD_EMAC_H_
|
||||
|
||||
#include "EMAC.h"
|
||||
#include "EMACInterface.h"
|
||||
#include "WiFiInterface.h"
|
||||
#include "whd_int.h"
|
||||
|
||||
#include "rtos/Semaphore.h"
|
||||
#include "rtos/Mutex.h"
|
||||
|
||||
class WHD_EMAC : public EMAC {
|
||||
public:
|
||||
WHD_EMAC(whd_interface_role_t itype = WHD_STA_ROLE, const uint8_t *mac_addr = NULL);
|
||||
|
||||
static WHD_EMAC &get_instance(whd_interface_role_t role = WHD_STA_ROLE, const uint8_t *mac_addr = NULL);
|
||||
|
||||
/**
|
||||
* Return maximum transmission unit
|
||||
*
|
||||
* @return MTU in bytes
|
||||
*/
|
||||
virtual uint32_t get_mtu_size() const;
|
||||
|
||||
/**
|
||||
* Gets memory buffer alignment preference
|
||||
*
|
||||
* Gets preferred memory buffer alignment of the Emac device. IP stack may or may not
|
||||
* align link out memory buffer chains using the alignment.
|
||||
*
|
||||
* @return Memory alignment requirement in bytes
|
||||
*/
|
||||
virtual uint32_t get_align_preference() const;
|
||||
|
||||
/**
|
||||
* Return interface name
|
||||
*
|
||||
* @param name Pointer to where the name should be written
|
||||
* @param size Maximum number of character to copy
|
||||
*/
|
||||
virtual void get_ifname(char *name, uint8_t size) const;
|
||||
|
||||
/**
|
||||
* Returns size of the underlying interface HW address size.
|
||||
*
|
||||
* @return HW address size in bytes
|
||||
*/
|
||||
virtual uint8_t get_hwaddr_size() const;
|
||||
|
||||
/**
|
||||
* Return interface-supplied HW address
|
||||
*
|
||||
* Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size
|
||||
*
|
||||
* HW address need not be provided if this interface does not have its own HW
|
||||
* address configuration; stack will choose address from central system
|
||||
* configuration if the function returns false and does not write to addr.
|
||||
*
|
||||
* @param addr HW address for underlying interface
|
||||
* @return true if HW address is available
|
||||
*/
|
||||
virtual bool get_hwaddr(uint8_t *addr) const;
|
||||
|
||||
/**
|
||||
* Set HW address for interface
|
||||
*
|
||||
* Provided address has to be of correct size, see @a get_hwaddr_size
|
||||
*
|
||||
* Called to set the MAC address to actually use - if @a get_hwaddr is provided
|
||||
* the stack would normally use that, but it could be overridden, eg for test
|
||||
* purposes.
|
||||
*
|
||||
* @param addr Address to be set
|
||||
*/
|
||||
virtual void set_hwaddr(const uint8_t *addr);
|
||||
|
||||
/**
|
||||
* Sends the packet over the link
|
||||
*
|
||||
* That can not be called from an interrupt context.
|
||||
*
|
||||
* @param buf Packet to be send
|
||||
* @return True if the packet was send successfully, False otherwise
|
||||
*/
|
||||
virtual bool link_out(emac_mem_buf_t *buf);
|
||||
|
||||
/**
|
||||
* Initializes the HW
|
||||
*
|
||||
* @return True on success, False in case of an error.
|
||||
*/
|
||||
virtual bool power_up();
|
||||
|
||||
/**
|
||||
* Deinitializes the HW
|
||||
*
|
||||
*/
|
||||
virtual void power_down();
|
||||
|
||||
/**
|
||||
* Sets a callback that needs to be called for packets received for that interface
|
||||
*
|
||||
* @param input_cb Function to be register as a callback
|
||||
*/
|
||||
virtual void set_link_input_cb(emac_link_input_cb_t input_cb);
|
||||
|
||||
/**
|
||||
* Sets a callback that needs to be called on link status changes for given interface
|
||||
*
|
||||
* @param state_cb Function to be register as a callback
|
||||
*/
|
||||
virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb);
|
||||
|
||||
/** Add device to a multicast group
|
||||
*
|
||||
* @param address A multicast group hardware address
|
||||
*/
|
||||
virtual void add_multicast_group(const uint8_t *address);
|
||||
|
||||
/** Remove device from a multicast group
|
||||
*
|
||||
* @param address A multicast group hardware address
|
||||
*/
|
||||
virtual void remove_multicast_group(const uint8_t *address);
|
||||
|
||||
/** Request reception of all multicast packets
|
||||
*
|
||||
* @param all True to receive all multicasts
|
||||
* False to receive only multicasts addressed to specified groups
|
||||
*/
|
||||
virtual void set_all_multicast(bool all);
|
||||
|
||||
/** Sets memory manager that is used to handle memory buffers
|
||||
*
|
||||
* @param mem_mngr Pointer to memory manager
|
||||
*/
|
||||
virtual void set_memory_manager(EMACMemoryManager &mem_mngr);
|
||||
|
||||
/** Set callback to receive EMAC activity events
|
||||
*
|
||||
* @param activity_cb The callback for activity events
|
||||
*/
|
||||
virtual void set_activity_cb(mbed::Callback<void(bool is_tx_activity)> activity_cb);
|
||||
|
||||
emac_link_input_cb_t emac_link_input_cb = NULL; /**< Callback for incoming data */
|
||||
emac_link_state_change_cb_t emac_link_state_cb = NULL;
|
||||
EMACMemoryManager *memory_manager;
|
||||
bool powered_up = false;
|
||||
bool link_state = false;
|
||||
bool ap_sta_concur = false;
|
||||
whd_interface_role_t interface_type;
|
||||
whd_driver_t drvp = NULL;
|
||||
whd_interface_t ifp = NULL;
|
||||
whd_mac_t unicast_addr;
|
||||
whd_mac_t multicast_addr;
|
||||
mbed::Callback<void(bool)> activity_cb;
|
||||
};
|
||||
|
||||
#endif /* WHD_EMAC_H_ */
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "WhdSTAInterface.h"
|
||||
#include "WhdSoftAPInterface.h"
|
||||
#include "whd_interface.h"
|
||||
|
||||
whd_interface_shared_info_t whd_iface_shared;
|
||||
|
||||
WiFiInterface *WiFiInterface::get_target_default_instance()
|
||||
{
|
||||
static WhdSTAInterface wifi;
|
||||
return &wifi;
|
||||
}
|
||||
|
||||
WhdSoftAPInterface *WhdSoftAPInterface::get_default_instance()
|
||||
{
|
||||
static WhdSoftAPInterface softap;
|
||||
return &softap;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* WHD implementation of NetworkInterfaceAPI
|
||||
* Copyright (c) 2017-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WHD_INTERFACE_H
|
||||
#define WHD_INTERFACE_H
|
||||
|
||||
#include "rtos/Mutex.h"
|
||||
#include "OnboardNetworkStack.h"
|
||||
|
||||
/** WhdSTAInterface class
|
||||
* Shared information
|
||||
*/
|
||||
#define IF_STATUS_ALL_IF_DOWN 0x0
|
||||
#define IF_STATUS_STA_UP 0x1
|
||||
#define IF_STATUS_SOFT_AP_UP 0x2
|
||||
|
||||
enum whd_default_interface_config
|
||||
{
|
||||
DEFAULT_IF_NOT_SET,
|
||||
DEFAULT_IF_STA,
|
||||
DEFAULT_IF_SOFT_AP
|
||||
};
|
||||
|
||||
struct whd_interface_shared_info_t {
|
||||
rtos::Mutex mutex;
|
||||
whd_default_interface_config default_if_cfg;
|
||||
uint32_t if_status_flags;
|
||||
OnboardNetworkStack::Interface *iface_sta;
|
||||
OnboardNetworkStack::Interface *iface_softap;
|
||||
whd_interface_shared_info_t() : default_if_cfg(DEFAULT_IF_NOT_SET), if_status_flags(IF_STATUS_ALL_IF_DOWN),
|
||||
iface_sta(NULL), iface_softap(NULL)
|
||||
{}
|
||||
};
|
||||
|
||||
extern whd_interface_shared_info_t whd_iface_shared;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,135 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef WICED_NETWORK_H
|
||||
#define WICED_NETWORK_H
|
||||
#include "w_dtls_types.h"
|
||||
#include "wiced_result.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Macros
|
||||
******************************************************/
|
||||
|
||||
#define IP_HANDLE(interface) (wiced_ip_handle[(interface) & 3])
|
||||
|
||||
/******************************************************
|
||||
* Constants
|
||||
******************************************************/
|
||||
|
||||
#define WICED_MAXIMUM_NUMBER_OF_SOCKETS_WITH_CALLBACKS (1)
|
||||
#define WICED_MAXIMUM_NUMBER_OF_SERVER_SOCKETS (1)
|
||||
|
||||
#define SIZE_OF_ARP_ENTRY sizeof(1)
|
||||
|
||||
#define IP_STACK_SIZE (2 * 1024)
|
||||
#define ARP_CACHE_SIZE (6 * SIZE_OF_ARP_ENTRY)
|
||||
#define DHCP_STACK_SIZE (1024)
|
||||
#define WICED_PKT_SIZE (1500)
|
||||
#define WICED_ANY_PORT (0)
|
||||
|
||||
/******************************************************
|
||||
* Enumerations
|
||||
******************************************************/
|
||||
|
||||
typedef enum {
|
||||
WICED_SOCKET_ERROR
|
||||
} wiced_socket_state_t;
|
||||
|
||||
/******************************************************
|
||||
* Type Definitions
|
||||
******************************************************/
|
||||
typedef struct {
|
||||
uint8_t *payload;
|
||||
uint16_t len;
|
||||
uint16_t pktstart;
|
||||
} wiced_packet_t;
|
||||
|
||||
|
||||
//typedef NOOS_DUMMY wiced_tls_context_type_t;
|
||||
//typedef NOOS_DUMMY wiced_tls_context_t;
|
||||
//typedef NOOS_DUMMY wiced_tls_session_t;
|
||||
//typedef NOOS_DUMMY wiced_tls_certificate_t;
|
||||
//typedef NOOS_DUMMY wiced_tls_endpoint_type_t;
|
||||
typedef void *NOOS_TCP_SOCKET;
|
||||
|
||||
/******************************************************
|
||||
* Structures
|
||||
******************************************************/
|
||||
|
||||
typedef struct wiced_tcp_socket_struct wiced_tcp_socket_t;
|
||||
typedef struct wiced_udp_socket_struct wiced_udp_socket_t;
|
||||
|
||||
typedef wiced_result_t (*wiced_tcp_socket_callback_t)(wiced_tcp_socket_t *socket, void *arg);
|
||||
typedef wiced_result_t (*wiced_udp_socket_callback_t)(wiced_udp_socket_t *socket, void *arg);
|
||||
|
||||
struct wiced_udp_socket_struct {
|
||||
wiced_dtls_context_t *dtls_context;
|
||||
struct {
|
||||
wiced_tcp_socket_callback_t disconnect;
|
||||
wiced_tcp_socket_callback_t receive;
|
||||
wiced_tcp_socket_callback_t connect;
|
||||
} callbacks;
|
||||
void *callback_arg;
|
||||
};
|
||||
|
||||
struct wiced_tcp_socket_struct {
|
||||
NOOS_TCP_SOCKET socket;
|
||||
wiced_tls_context_t *tls_context;
|
||||
wiced_bool_t context_malloced;
|
||||
struct {
|
||||
wiced_tcp_socket_callback_t disconnect;
|
||||
wiced_tcp_socket_callback_t receive;
|
||||
wiced_tcp_socket_callback_t connect;
|
||||
} callbacks;
|
||||
void *callback_arg;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
wiced_tcp_socket_t socket[WICED_MAXIMUM_NUMBER_OF_SERVER_SOCKETS];
|
||||
int interface;
|
||||
uint16_t port;
|
||||
wiced_tls_identity_t *tls_identity;
|
||||
} wiced_tcp_server_t;
|
||||
|
||||
/******************************************************
|
||||
* Global Variables
|
||||
******************************************************/
|
||||
typedef struct {
|
||||
int dummy;
|
||||
} NOOS_IP;
|
||||
typedef struct {
|
||||
int dummy;
|
||||
} NOOS_PACKET_POOL;
|
||||
/*
|
||||
* Note: These objects are for internal use only!
|
||||
*/
|
||||
extern NOOS_IP wiced_ip_handle [3];
|
||||
extern NOOS_PACKET_POOL wiced_packet_pools [2]; /* 0=TX, 1=RX */
|
||||
|
||||
/******************************************************
|
||||
* Function Declarations
|
||||
******************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C" */
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,405 @@
|
||||
#include "CyDhcpServer.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct DHCP_options_table_s {
|
||||
uint8_t code;
|
||||
uint32_t length; /* 0x80000000 means variable */
|
||||
const char *name;
|
||||
} dhcp_options_table_t;
|
||||
|
||||
static dhcp_options_table_t dhcp_options_lookup_table[] = {
|
||||
{ 0, 0, "Pad" },
|
||||
{ 1, 4, "Subnet Mask" },
|
||||
{ 2, 4, "Time Offset" },
|
||||
{ 3, 0, "Router" },
|
||||
{ 4, 0, "Time Server" },
|
||||
{ 5, 0, "Name Server" },
|
||||
{ 6, 0, "Domain Server" },
|
||||
{ 7, 0, "Log Server" },
|
||||
{ 8, 0, "Quotes Server" },
|
||||
{ 9, 0, "LPR Server" },
|
||||
{ 10, 0, "Impress Server" },
|
||||
{ 11, 0, "RLP Server" },
|
||||
{ 12, 0, "Hostname" },
|
||||
{ 13, 2, "Boot File Size" },
|
||||
{ 14, 0, "Merit Dump File" },
|
||||
{ 15, 0, "Domain Name" },
|
||||
{ 16, 0, "Swap Server" },
|
||||
{ 17, 0, "Root Path" },
|
||||
{ 18, 0, "Extension File" },
|
||||
{ 19, 1, "Forward On/Off" },
|
||||
{ 20, 1, "SrcRte On/Off" },
|
||||
{ 21, 0, "Policy Filter" },
|
||||
{ 22, 2, "Max DG Assembly" },
|
||||
{ 23, 1, "Default IP TTL" },
|
||||
{ 24, 4, "MTU Timeout" },
|
||||
{ 25, 0, "MTU Plateau" },
|
||||
{ 26, 2, "MTU Interface" },
|
||||
{ 27, 1, "MTU Subnet" },
|
||||
{ 28, 4, "Broadcast Address" },
|
||||
{ 29, 1, "Mask Discovery" },
|
||||
{ 30, 1, "Mask Supplier" },
|
||||
{ 31, 1, "Router Discovery" },
|
||||
{ 32, 4, "Router Request" },
|
||||
{ 33, 0, "Static Route" },
|
||||
{ 34, 1, "Trailers" },
|
||||
{ 35, 4, "ARP Timeout" },
|
||||
{ 36, 1, "Ethernet" },
|
||||
{ 37, 1, "Default TCP TTL" },
|
||||
{ 38, 4, "Keepalive Time" },
|
||||
{ 39, 1, "Keepalive Data" },
|
||||
{ 40, 0, "NIS Domain" },
|
||||
{ 41, 0, "NIS Servers" },
|
||||
{ 42, 0, "NTP Servers" },
|
||||
{ 43, 0, "Vendor Specific" },
|
||||
{ 44, 0, "NETBIOS Name Srv" },
|
||||
{ 45, 0, "NETBIOS Dist Srv" },
|
||||
{ 46, 1, "NETBIOS Node Type" },
|
||||
{ 47, 0, "NETBIOS Scope" },
|
||||
{ 48, 0, "X Window Font" },
|
||||
{ 49, 0, "X Window Manager" },
|
||||
{ 50, 4, "Address Request" },
|
||||
{ 51, 4, "Address Time" },
|
||||
{ 52, 1, "Overload" },
|
||||
{ 53, 1, "DHCP Msg Type" },
|
||||
{ 54, 4, "DHCP Server Id" },
|
||||
{ 55, 0, "Parameter List" },
|
||||
{ 56, 0, "DHCP Message" },
|
||||
{ 57, 2, "DHCP Max Msg Size" },
|
||||
{ 58, 4, "Renewal Time" },
|
||||
{ 59, 4, "Rebinding Time" },
|
||||
{ 60, 0, "Class Id" },
|
||||
{ 61, 0, "Client Id" },
|
||||
{ 62, 0, "NetWare/IP Domain" },
|
||||
{ 63, 0, "NetWare/IP Option" },
|
||||
{ 64, 0, "NIS-Domain-Name" },
|
||||
{ 65, 0, "NIS-Server-Addr" },
|
||||
{ 66, 0, "Server-Name" },
|
||||
{ 67, 0, "Bootfile-Name" },
|
||||
{ 68, 0, "Home-Agent-Addrs" },
|
||||
{ 69, 0, "SMTP-Server" },
|
||||
{ 70, 0, "POP3-Server" },
|
||||
{ 71, 0, "NNTP-Server" },
|
||||
{ 72, 0, "WWW-Server" },
|
||||
{ 73, 0, "Finger-Server" },
|
||||
{ 74, 0, "IRC-Server" },
|
||||
{ 75, 0, "StreetTalk-Server" },
|
||||
{ 76, 0, "STDA-Server" },
|
||||
{ 77, 0, "User-Class" },
|
||||
{ 78, 0, "Directory Agent" },
|
||||
{ 79, 0, "Service Scope" },
|
||||
{ 80, 0, "Rapid Commit" },
|
||||
{ 81, 0, "Client FQDN" },
|
||||
{ 82, 0, "Relay Agent Information" },
|
||||
{ 83, 0, "iSNS" },
|
||||
{ 85, 0, "NDS Servers" },
|
||||
{ 86, 0, "NDS Tree Name" },
|
||||
{ 87, 0, "NDS Context" },
|
||||
{ 88, 0x80000000, "BCMCS Controller Domain Name list" },
|
||||
{ 89, 0x80000000, "BCMCS Controller IPv4 address option" },
|
||||
{ 90, 0, "Authentication" },
|
||||
{ 91, 0x80000000, "client-last-transaction-time option" },
|
||||
{ 92, 0x80000000, "associated-ip option" },
|
||||
{ 93, 0, "Client System" },
|
||||
{ 94, 0, "Client NDI" },
|
||||
{ 95, 0, "LDAP" },
|
||||
{ 97, 0, "UUID/GUID" },
|
||||
{ 98, 0, "User-Auth" },
|
||||
{ 99, 0x80000000, "GEOCONF_CIVIC" },
|
||||
{100, 0, "PCode" },
|
||||
{101, 0, "TCode" },
|
||||
{109, 16, "OPTION_DHCP4O6_S46_SADDR" },
|
||||
{112, 0, "Netinfo Address" },
|
||||
{113, 0, "Netinfo Tag" },
|
||||
{114, 0, "URL" },
|
||||
{116, 0, "Auto-Config" },
|
||||
{117, 0, "Name Service Search" },
|
||||
{118, 4, "Subnet Selection Option" },
|
||||
{119, 0, "Domain Search" },
|
||||
{120, 0, "SIP Servers DHCP Option" },
|
||||
{121, 0, "Classless Static Route Option" },
|
||||
{122, 0, "CCC" },
|
||||
{123, 16, "GeoConf Option" },
|
||||
{124, 0, "V-I Vendor Class" },
|
||||
{125, 0, "V-I Vendor-Specific Information" },
|
||||
{128, 0, "Etherboot signature. 6 bytes: E4:45:74:68:00:00" },
|
||||
{129, 4, "Call Server IP address" },
|
||||
{130, 0x80000000, "Ethernet interface. Variable" },
|
||||
{131, 0, "Remote statistics server IP address" },
|
||||
{132, 0, "IEEE 802.1Q VLAN ID" },
|
||||
{133, 0, "IEEE 802.1D/p Layer 2 Priority" },
|
||||
{134, 0, "Diffserv Code Point (DSCP) for" },
|
||||
{135, 0, "HTTP Proxy for phone-specific" },
|
||||
{136, 0, "OPTION_PANA_AGENT" },
|
||||
{137, 0, "OPTION_V4_LOST" },
|
||||
{138, 0, "OPTION_CAPWAP_AC_V4" },
|
||||
{139, 0, "OPTION-IPv4_Address-MoS" },
|
||||
{140, 0, "OPTION-IPv4_FQDN-MoS" },
|
||||
{141, 0, "SIP UA Configuration Service Domains" },
|
||||
{142, 0, "OPTION-IPv4_Address-ANDSF" },
|
||||
{143, 0, "OPTION_V4_SZTP_REDIRECT" },
|
||||
{144, 16, "GeoLoc" },
|
||||
{145, 1, "FORCERENEW_NONCE_CAPABLE" },
|
||||
{146, 0, "RDNSS Selection" },
|
||||
{151, 0x80000000, "N+1 status-code" },
|
||||
{152, 4, "base-time" },
|
||||
{153, 4, "start-time-of-state" },
|
||||
{154, 4, "query-start-time" },
|
||||
{155, 4, "query-end-time" },
|
||||
{156, 1, "dhcp-state" },
|
||||
{157, 1, "data-source" },
|
||||
{158, 0x80000000, " Variable; the minimum length is 5. OPTION_V4_PCP_SERVER" },
|
||||
{159, 4, "OPTION_V4_PORTPARAMS" },
|
||||
{160, 0, "DHCP Captive-Portal" },
|
||||
{161, 0x80000000, "(variable) OPTION_MUD_URL_V4" },
|
||||
{208, 4, "PXELINUX Magic" },
|
||||
{209, 0, "Configuration File" },
|
||||
{210, 0, "Path Prefix" },
|
||||
{211, 4, "Reboot Time" },
|
||||
{212, 0x80000000, "18+ N OPTION_6RD" },
|
||||
{213, 0, "OPTION_V4_ACCESS_DOMAIN" },
|
||||
{220, 0, "Subnet Allocation Option" },
|
||||
};
|
||||
|
||||
#define isprint(c) ((c) >= 0x20 && (c) < 0x7f)
|
||||
int hex_dump_print(const void *data_ptr, uint16_t length, int show_ascii)
|
||||
{
|
||||
uint8_t *data = (uint8_t *)data_ptr;
|
||||
uint8_t *char_ptr;
|
||||
int i, count;
|
||||
if ((data == NULL) || (length == 0)) {
|
||||
return -1;
|
||||
}
|
||||
count = 0;
|
||||
char_ptr = data;
|
||||
while (length > 0) {
|
||||
i = 0;
|
||||
while ((length > 0) && (i < 16)) {
|
||||
printf(" %02x", *data);
|
||||
i++;
|
||||
data++;
|
||||
length--;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (show_ascii != 0) {
|
||||
int fill = 16 - i;
|
||||
/* fill in for < 16 */
|
||||
while (fill > 0) {
|
||||
printf(" ");
|
||||
fill--;
|
||||
}
|
||||
/* space between numbers and chars */
|
||||
printf(" ");
|
||||
while (i > 0) {
|
||||
printf("%c", (isprint(*char_ptr) ? *char_ptr : '.'));
|
||||
char_ptr++;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
void dhcp_server_print_header_info(dhcp_packet_t *header, uint32_t datalen, const char *title)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
if (title != NULL) {
|
||||
printf("%s:\n", title);
|
||||
}
|
||||
|
||||
printf("Opcode :%2d : %s\n", header->Opcode, (header->Opcode == 1) ? "Request" : (header->Opcode == 2) ? "Reply" : "Unknown");
|
||||
printf("HwType :%2d : %s\n", header->HwType, (header->HwType == 1) ? "Ethernet" : "Unknown");
|
||||
printf("HwLength : : %d\n", header->HwLen);
|
||||
printf("Hops : : %d\n", header->Hops);
|
||||
printf("TransactionId : : 0x%lx\n", header->TransactionId);
|
||||
printf("Elapsed time : : %d\n", header->SecsElapsed);
|
||||
printf("Flags : : 0x%08x\n", header->Flags);
|
||||
uint8_t *ip_ptr = (uint8_t *)&header->ClientIpAddr;
|
||||
printf("from client IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]);
|
||||
ip_ptr = (uint8_t *)&header->YourIpAddr;
|
||||
printf("from us YOUR IP: : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]);
|
||||
ip_ptr = (uint8_t *)&header->ServerIpAddr;
|
||||
printf("DHCP server IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]);
|
||||
ip_ptr = (uint8_t *)&header->GatewayIpAddr;
|
||||
printf("gateway IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]);
|
||||
|
||||
printf("Client MAC : :");
|
||||
hex_dump_print(header->ClientHwAddr, 16, 0);
|
||||
ip_ptr = (uint8_t *)&header->MagicCookie;
|
||||
printf("Magic : : %2x %2x %2x %2x\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]);
|
||||
|
||||
printf("Options :\n");
|
||||
ptr = (uint8_t *)header->Options;
|
||||
printf("Hex Dump:\n");
|
||||
hex_dump_print(ptr, 64, 1);
|
||||
printf("\n");
|
||||
|
||||
while ((ptr != NULL) && (*ptr != DHCP_END_OPTION_CODE) && ((uint32_t)(ptr - &header->Options[0]) < datalen)) {
|
||||
int len;
|
||||
switch (*ptr) {
|
||||
case DHCP_SUBNETMASK_OPTION_CODE: // (1)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d SUBNET MASK : ", DHCP_SUBNETMASK_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 1);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_ROUTER_OPTION_CODE: // (3)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d ROUTER : ", DHCP_ROUTER_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 0);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_DNS_SERVER_OPTION_CODE: // (6)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d DNS SERVER : ", DHCP_DNS_SERVER_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 0);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_HOST_NAME_OPTION_CODE:
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d HOST NAME : ", DHCP_HOST_NAME_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 1);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_MTU_OPTION_CODE: // (26)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d MTU : ", DHCP_MTU_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 0);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE: // (50)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d REQUESTED IP : ", DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 0);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_LEASETIME_OPTION_CODE: // (51)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d LEASE TIME : ", DHCP_LEASETIME_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 0);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_MESSAGETYPE_OPTION_CODE: { // (53)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
int code = *ptr;
|
||||
printf(" Code:%d Length:%d MESSAGE : ", DHCP_MESSAGETYPE_OPTION_CODE, len);
|
||||
switch (code) {
|
||||
case 1:
|
||||
printf(" %d -- DHCP DISCOVER\n", code);
|
||||
break;
|
||||
case 2:
|
||||
printf(" %d -- DHCP OFFER\n", code);
|
||||
break;
|
||||
case 3:
|
||||
printf(" %d -- DHCP REQUEST\n", code);
|
||||
break;
|
||||
case 4:
|
||||
printf(" %d -- DHCP DECLINE\n", code);
|
||||
break;
|
||||
case 5:
|
||||
printf(" %d -- DHCP ACK\n", code);
|
||||
break;
|
||||
case 6:
|
||||
printf(" %d -- DHCP NACK\n", code);
|
||||
break;
|
||||
case 7:
|
||||
printf(" %d -- DHCP RELEASE\n", code);
|
||||
break;
|
||||
case 8:
|
||||
printf(" %d -- DHCP INFORM\n", code);
|
||||
break;
|
||||
default:
|
||||
printf(" %d -- INVALID\n", code);
|
||||
break;
|
||||
}
|
||||
ptr += len;
|
||||
break;
|
||||
}
|
||||
case DHCP_SERVER_IDENTIFIER_OPTION_CODE: // (54)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d SERVER ID : ", DHCP_SERVER_IDENTIFIER_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 0);
|
||||
ptr += len;
|
||||
break;
|
||||
case DHCP_PARAM_REQUEST_LIST_OPTION_CODE:
|
||||
// 9.8. Parameter Request List
|
||||
//
|
||||
// This option is used by a DHCP client to request values for specified
|
||||
// configuration parameters. The list of requested parameters is
|
||||
// specified as n octets, where each octet is a valid DHCP option code
|
||||
// as defined in this document.
|
||||
//
|
||||
// The client MAY list the options in order of preference. The DHCP
|
||||
// server is not required to return the options in the requested order,
|
||||
// but MUST try to insert the requested options in the order requested
|
||||
// by the client.
|
||||
//
|
||||
// The code for this option is 55. Its minimum length is 1.
|
||||
//
|
||||
// Code Len Option Codes
|
||||
// +-----+-----+-----+-----+---
|
||||
// | 55 | n | c1 | c2 | ...
|
||||
// +-----+-----+-----+-----+---
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d PARAM REQ : ", DHCP_PARAM_REQUEST_LIST_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 0);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
uint8_t sub_code;
|
||||
sub_code = *ptr++;
|
||||
|
||||
uint32_t lookup_index;
|
||||
uint32_t max_lookup = (sizeof(dhcp_options_lookup_table) / sizeof(dhcp_options_lookup_table[0]));
|
||||
for (lookup_index = 0; lookup_index < max_lookup; lookup_index++) {
|
||||
if (dhcp_options_lookup_table[lookup_index].code == sub_code) {
|
||||
uint32_t length = dhcp_options_lookup_table[lookup_index].length;
|
||||
if (length != 0) {
|
||||
/* length is variable, in the length field ? */
|
||||
length = *ptr;
|
||||
}
|
||||
printf(" Code:%3d : %s\n", dhcp_options_lookup_table[lookup_index].code, dhcp_options_lookup_table[lookup_index].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lookup_index >= max_lookup) {
|
||||
printf(" Code:%3d : UNKNOWN\n", dhcp_options_lookup_table[lookup_index].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DHCP_WPAD_OPTION_CODE: // (252)
|
||||
ptr++;
|
||||
len = *ptr++;
|
||||
printf(" Code:%d Length:%d WPAD : ", DHCP_WPAD_OPTION_CODE, len);
|
||||
hex_dump_print(ptr, len, 1);
|
||||
ptr += len;
|
||||
break;
|
||||
|
||||
default:
|
||||
ptr++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "cynetwork_utils.h"
|
||||
|
||||
uint8_t unsigned_to_decimal_string(uint32_t value, char *output, uint8_t min_length, uint8_t max_length)
|
||||
{
|
||||
uint8_t digits_left;
|
||||
char buffer[] = "0000000000";
|
||||
|
||||
if (output == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
max_length = (uint8_t) MIN(max_length, sizeof(buffer));
|
||||
digits_left = max_length;
|
||||
while ((value != 0) && (digits_left != 0)) {
|
||||
--digits_left;
|
||||
buffer[digits_left] = (char)((value % 10) + '0');
|
||||
value = value / 10;
|
||||
}
|
||||
|
||||
digits_left = (uint8_t) MIN((max_length - min_length), digits_left);
|
||||
memcpy(output, &buffer[digits_left], (size_t)(max_length - digits_left));
|
||||
|
||||
/* Add terminating null */
|
||||
output[(max_length - digits_left)] = '\x00';
|
||||
|
||||
return (uint8_t)(max_length - digits_left);
|
||||
}
|
||||
|
||||
void ipv4_to_string(char buffer[16], uint32_t ipv4_address)
|
||||
{
|
||||
uint8_t *ip = (uint8_t *)&ipv4_address;
|
||||
|
||||
/* unsigned_to_decimal_string() null-terminates the string
|
||||
* Save the original last character and replace it */
|
||||
char last_char = buffer[16];
|
||||
unsigned_to_decimal_string(ip[0], &buffer[0], 3, 3);
|
||||
buffer[3] = '.';
|
||||
unsigned_to_decimal_string(ip[1], &buffer[4], 3, 3);
|
||||
buffer[7] = '.';
|
||||
unsigned_to_decimal_string(ip[2], &buffer[8], 3, 3);
|
||||
buffer[11] = '.';
|
||||
unsigned_to_decimal_string(ip[3], &buffer[12], 3, 3);
|
||||
buffer[16] = last_char;
|
||||
}
|
||||
|
||||
uint32_t string_to_ipv4(const char *buffer)
|
||||
{
|
||||
uint32_t temp = 0;
|
||||
int char_count = 0;
|
||||
const char *ptr = buffer;
|
||||
|
||||
while ((ptr != NULL) && (*ptr != 0) && (char_count++ < 16)) {
|
||||
uint8_t byte = 0;
|
||||
while ((*ptr != 0) && (*ptr != '.') && (char_count++ < 16)) {
|
||||
byte *= 10;
|
||||
if ((*ptr >= '0') && (*ptr <= '9')) {
|
||||
byte += (*ptr - '0');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
temp <<= 8;
|
||||
temp |= byte;
|
||||
if (*ptr == '.') {
|
||||
ptr++; /* skip '.' */
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
extern int MIN(/*@sef@*/ int x, /*@sef@*/ int y); /* LINT : This tells lint that the parameter must be side-effect free. i.e. evaluation does not change any values (since it is being evaulated more than once */
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#endif /* ifndef MIN */
|
||||
|
||||
#define FX_IPTYPE_IPV4 (0)
|
||||
#define FX_IPTYPE_IPV6 (1)
|
||||
|
||||
typedef union {
|
||||
uint32_t addr;
|
||||
uint8_t addrs[4];
|
||||
} cy_ip_addr_v4_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t addr[4];
|
||||
} cy_ip_addr_v6_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
union {
|
||||
cy_ip_addr_v4_t addrv4;
|
||||
cy_ip_addr_v6_t addrv6;
|
||||
};
|
||||
} cy_ip_addr_t;
|
||||
|
||||
/**
|
||||
* Structure for storing a MAC address (Wi-Fi Media Access Control address).
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t octet[6]; /**< Unique 6-byte MAC address */
|
||||
} cy_mac_addr_t;
|
||||
|
||||
/**
|
||||
* Converts a unsigned long int to a decimal string
|
||||
*
|
||||
* @param value[in] : The unsigned long to be converted
|
||||
* @param output[out] : The buffer which will receive the decimal string
|
||||
* @param min_length[in] : the minimum number of characters to output (zero padding will apply if required).
|
||||
* @param max_length[in] : the maximum number of characters to output (up to 10 ). There must be space for terminating NULL.
|
||||
*
|
||||
* @note: A terminating NULL is added. Wnsure that there is space in the buffer for this.
|
||||
*
|
||||
* @return the number of characters returned (excluding terminating null)
|
||||
*
|
||||
*/
|
||||
uint8_t unsigned_to_decimal_string(uint32_t value, char *output, uint8_t min_length, uint8_t max_length);
|
||||
|
||||
/**
|
||||
* Convert a IPv4 address to a string
|
||||
*
|
||||
* @note: String is 16 bytes including terminating null
|
||||
*
|
||||
* @param[out] buffer : Buffer which will recieve the IPv4 string
|
||||
* @param[in] ipv4_address : IPv4 address to convert
|
||||
*/
|
||||
void ipv4_to_string(char buffer[16], uint32_t ipv4_address);
|
||||
|
||||
/**
|
||||
* Convert a IPv4 address to a string
|
||||
*
|
||||
* @note: String is 16 bytes including terminating null
|
||||
*
|
||||
* @param[in] buffer : Buffer which has the IPv4 string
|
||||
* @return ipv4_address (0 on failure)
|
||||
*/
|
||||
uint32_t string_to_ipv4(const char *buffer);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
3
connectivity/drivers/emac/TARGET_Cypress/mbed_lib.json
Normal file
3
connectivity/drivers/emac/TARGET_Cypress/mbed_lib.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "cypress-emac"
|
||||
}
|
||||
Reference in New Issue
Block a user