mirror of https://github.com/ARMmbed/mbed-os.git
297 lines
8.2 KiB
C++
297 lines
8.2 KiB
C++
/*
|
|
* Copyright (c) 2016-2019 ARM Limited. All rights reserved.
|
|
* 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 "MeshInterfaceNanostack.h"
|
|
#include "Nanostack.h"
|
|
#include "NanostackLockGuard.h"
|
|
#include "mesh_system.h"
|
|
#include "nanostack/net_interface.h"
|
|
#include "thread_management_if.h"
|
|
#include "ip6string.h"
|
|
#include "mbed_error.h"
|
|
#include "mbed_rtc_time.h"
|
|
|
|
#if (MBED_CONF_MBED_MESH_API_SYSTEM_TIME_UPDATE_FROM_NANOSTACK == true)
|
|
static uint64_t time_read_callback(void)
|
|
{
|
|
time_t seconds = time(NULL);
|
|
|
|
return (uint64_t)seconds;
|
|
}
|
|
|
|
static void time_write_callback(uint64_t time_write)
|
|
{
|
|
set_time((time_t)time_write);
|
|
}
|
|
#endif /* MBED_CONF_MBED_MESH_API_SYSTEM_TIME_UPDATE_FROM_NANOSTACK */
|
|
|
|
nsapi_error_t Nanostack::Interface::get_ip_address(SocketAddress *address)
|
|
{
|
|
NanostackLockGuard lock;
|
|
uint8_t binary_ipv6[16];
|
|
|
|
if (arm_net_address_get(interface_id, ADDR_IPV6_GP, binary_ipv6) == 0) {
|
|
address->set_ip_bytes(binary_ipv6, NSAPI_IPv6);
|
|
return NSAPI_ERROR_OK;
|
|
} else {
|
|
return NSAPI_ERROR_NO_ADDRESS;
|
|
}
|
|
}
|
|
|
|
char *Nanostack::Interface::get_mac_address(char *buf, nsapi_size_t buflen)
|
|
{
|
|
NanostackLockGuard lock;
|
|
link_layer_address_s addr;
|
|
if (buflen >= 24 && arm_nwk_mac_address_read(interface_id, &addr) == 0) {
|
|
snprintf(buf, buflen, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", addr.mac_long[0], addr.mac_long[1], addr.mac_long[2], addr.mac_long[3], addr.mac_long[4], addr.mac_long[5], addr.mac_long[6], addr.mac_long[7]);
|
|
return buf;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
nsapi_error_t Nanostack::Interface::set_mac_address(uint8_t *buf, nsapi_size_t buflen)
|
|
{
|
|
if (buflen != 8) {
|
|
/* Provided MAC is too short */
|
|
return NSAPI_ERROR_PARAMETER;
|
|
}
|
|
|
|
if (_device_id >= 0) {
|
|
/* device is already registered, can't set MAC address anymore */
|
|
return NSAPI_ERROR_BUSY;
|
|
}
|
|
|
|
NanostackMACPhy *phy = interface_phy.nanostack_mac_phy();
|
|
if (phy) {
|
|
phy->set_mac_address(buf);
|
|
return NSAPI_ERROR_OK;
|
|
}
|
|
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
nsapi_error_t Nanostack::Interface::get_netmask(SocketAddress *address)
|
|
{
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
nsapi_error_t Nanostack::Interface::get_gateway(SocketAddress *address)
|
|
{
|
|
return NSAPI_ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
nsapi_connection_status_t Nanostack::Interface::get_connection_status() const
|
|
{
|
|
return _connect_status;
|
|
}
|
|
|
|
void Nanostack::Interface::get_mac_address(uint8_t *buf) const
|
|
{
|
|
NanostackMACPhy *phy = interface_phy.nanostack_mac_phy();
|
|
if (phy) {
|
|
phy->get_mac_address(buf);
|
|
}
|
|
}
|
|
|
|
void Nanostack::Interface::attach(
|
|
mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
|
{
|
|
_connection_status_cb = status_cb;
|
|
}
|
|
|
|
Nanostack::Interface::Interface(NanostackPhy &phy) : interface_phy(phy)
|
|
{
|
|
mesh_system_init();
|
|
}
|
|
|
|
int InterfaceNanostack::connect()
|
|
{
|
|
nsapi_error_t error = do_initialize();
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
#if (MBED_CONF_MBED_MESH_API_SYSTEM_TIME_UPDATE_FROM_NANOSTACK == true)
|
|
mesh_system_time_callback_set(time_read_callback, time_write_callback);
|
|
#endif /* MBED_CONF_MBED_MESH_API_SYSTEM_TIME_UPDATE_FROM_NANOSTACK */
|
|
|
|
return _interface->bringup(false, NULL, NULL, NULL, IPV6_STACK, _blocking);
|
|
}
|
|
|
|
int InterfaceNanostack::disconnect()
|
|
{
|
|
if (!_interface) {
|
|
return NSAPI_ERROR_NO_CONNECTION;
|
|
}
|
|
return _interface->bringdown();
|
|
}
|
|
|
|
char *Nanostack::MeshInterface::get_interface_name(char *buf)
|
|
{
|
|
if (interface_id < 0) {
|
|
return NULL;
|
|
}
|
|
sprintf(buf, "MES%d", interface_id);
|
|
return buf;
|
|
};
|
|
|
|
nsapi_error_t MeshInterfaceNanostack::initialize(NanostackRfPhy *phy)
|
|
{
|
|
if (_phy && phy && _phy != phy) {
|
|
error("Phy already set");
|
|
return NSAPI_ERROR_IS_CONNECTED;
|
|
}
|
|
if (phy) {
|
|
_phy = phy;
|
|
}
|
|
if (_phy) {
|
|
return do_initialize();
|
|
} else {
|
|
return NSAPI_ERROR_PARAMETER;
|
|
}
|
|
}
|
|
|
|
void Nanostack::Interface::network_handler(mesh_connection_status_t status)
|
|
{
|
|
if (_blocking) {
|
|
if (_connect_status == NSAPI_STATUS_CONNECTING
|
|
&& (status == MESH_CONNECTED || status == MESH_CONNECTED_LOCAL
|
|
|| status == MESH_CONNECTED_GLOBAL)) {
|
|
connect_semaphore.release();
|
|
} else if (status == MESH_DISCONNECTED) {
|
|
disconnect_semaphore.release();
|
|
connect_semaphore.release();
|
|
}
|
|
}
|
|
|
|
bool global_up = false;
|
|
|
|
if (status == MESH_CONNECTED) {
|
|
uint8_t temp_ipv6_global[16];
|
|
uint8_t temp_ipv6_local[16];
|
|
if (arm_net_address_get(interface_id, ADDR_IPV6_LL, temp_ipv6_local) == 0) {
|
|
_connect_status = NSAPI_STATUS_LOCAL_UP;
|
|
}
|
|
if (arm_net_address_get(interface_id, ADDR_IPV6_GP, temp_ipv6_global) == 0
|
|
&& (memcmp(temp_ipv6_global, temp_ipv6_local, 16) != 0)) {
|
|
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
|
global_up = true;
|
|
}
|
|
} else if (status == MESH_CONNECTED_LOCAL) {
|
|
_connect_status = NSAPI_STATUS_LOCAL_UP;
|
|
} else if (status == MESH_CONNECTED_GLOBAL) {
|
|
_connect_status = NSAPI_STATUS_GLOBAL_UP;
|
|
} else if (status == MESH_BOOTSTRAP_STARTED || status == MESH_BOOTSTRAP_FAILED) {
|
|
_connect_status = NSAPI_STATUS_CONNECTING;
|
|
} else {
|
|
_connect_status = NSAPI_STATUS_DISCONNECTED;
|
|
}
|
|
|
|
if (_connection_status_cb && (global_up || (_previous_connection_status != _connect_status
|
|
&& (_previous_connection_status != NSAPI_STATUS_GLOBAL_UP || status != MESH_BOOTSTRAP_STARTED)
|
|
&& (_previous_connection_status != NSAPI_STATUS_CONNECTING || status != MESH_BOOTSTRAP_START_FAILED)))) {
|
|
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
|
|
}
|
|
_previous_connection_status = _connect_status;
|
|
}
|
|
|
|
nsapi_error_t Nanostack::Interface::register_phy()
|
|
{
|
|
NanostackLockGuard lock;
|
|
|
|
if (_device_id < 0) {
|
|
_device_id = interface_phy.phy_register();
|
|
}
|
|
if (_device_id < 0) {
|
|
return NSAPI_ERROR_DEVICE_ERROR;
|
|
}
|
|
|
|
return NSAPI_ERROR_OK;
|
|
}
|
|
|
|
Nanostack *InterfaceNanostack::get_stack()
|
|
{
|
|
return &Nanostack::get_instance();
|
|
}
|
|
|
|
nsapi_error_t InterfaceNanostack::get_ip_address(SocketAddress *address)
|
|
{
|
|
if (_interface->get_ip_address(address) == NSAPI_ERROR_OK) {
|
|
ip_addr = address->get_ip_address();
|
|
return NSAPI_ERROR_OK;
|
|
}
|
|
|
|
return NSAPI_ERROR_NO_ADDRESS;
|
|
}
|
|
|
|
const char *InterfaceNanostack::get_mac_address()
|
|
{
|
|
if (_interface->get_mac_address(mac_addr_str, sizeof(mac_addr_str))) {
|
|
return mac_addr_str;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
nsapi_error_t InterfaceNanostack::set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len)
|
|
{
|
|
return _interface->set_mac_address(mac_addr, addr_len);
|
|
}
|
|
|
|
nsapi_connection_status_t InterfaceNanostack::get_connection_status() const
|
|
{
|
|
if (_interface) {
|
|
return _interface->get_connection_status();
|
|
} else {
|
|
return NSAPI_STATUS_DISCONNECTED;
|
|
}
|
|
}
|
|
|
|
void InterfaceNanostack::attach(
|
|
mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
|
|
{
|
|
_connection_status_cb = status_cb;
|
|
if (_interface) {
|
|
_interface->attach(status_cb);
|
|
}
|
|
}
|
|
|
|
nsapi_error_t InterfaceNanostack::set_blocking(bool blocking)
|
|
{
|
|
_blocking = blocking;
|
|
return NSAPI_ERROR_OK;
|
|
}
|
|
|
|
nsapi_error_t InterfaceNanostack::set_file_system_root_path(const char *root_path)
|
|
{
|
|
int status = mesh_system_set_file_system_root_path(root_path);
|
|
|
|
if (status == 0) {
|
|
return MESH_ERROR_NONE;
|
|
} else if (status == -2) {
|
|
return MESH_ERROR_MEMORY;
|
|
}
|
|
|
|
return MESH_ERROR_UNKNOWN;
|
|
}
|
|
|
|
#if !DEVICE_802_15_4_PHY
|
|
MBED_WEAK MeshInterface *MeshInterface::get_target_default_instance()
|
|
{
|
|
return NULL;
|
|
}
|
|
#endif
|