mirror of https://github.com/ARMmbed/mbed-os.git
238 lines
8.1 KiB
C++
238 lines
8.1 KiB
C++
/*
|
|
* 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]);
|
|
}
|