Get rid of Mesh6LoWPAN_ND and MeshThread classes.

* Move all the functionality to LoWPANNDInterface and
    ThreadInterface classes.
* AbstractMesh class modified to be pure virtual
* Thread/6LoWPAN specific functionality totally separated.
    Now linker will drop the unreferenced classes.
* MeshInterfaceNanostack now inherits from AbstractMesh
pull/3267/head
Seppo Takalo 2016-11-08 16:53:17 +02:00
parent 62558e9cff
commit 27cced74fb
13 changed files with 403 additions and 655 deletions

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2015 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.
*/
#ifndef LOWPANNDINTERFACE_H
#define LOWPANNDINTERFACE_H
#include "NanostackInterface.h"
class LoWPANNDInterface : public MeshInterfaceNanostack {
public:
/** Create an uninitialized LoWPANNDInterface
*
* Must initialize to initialize the mesh on a phy.
*/
LoWPANNDInterface() : MeshInterfaceNanostack() {
}
/** Create an initialized MeshInterface
*
*/
LoWPANNDInterface(NanostackRfPhy *phy) : MeshInterfaceNanostack(phy) {
}
int connect();
int disconnect();
bool getOwnIpAddress(char *address, int8_t len);
bool getRouterIpAddress(char *address, int8_t len);
private:
mesh_error_t init();
mesh_error_t mesh_connect();
mesh_error_t mesh_disconnect();
};
#endif

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2015 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.
*/
#ifndef __MESH6LOWPAN_ND_H__
#define __MESH6LOWPAN_ND_H__
#include "AbstractMesh.h"
/**
* \brief 6LoWPAN ND mesh networking class.
*/
class Mesh6LoWPAN_ND : public AbstractMesh
{
public:
Mesh6LoWPAN_ND();
virtual ~Mesh6LoWPAN_ND();
/**
* \brief Read own global IP address
*
* \param address is where the IP address will be copied
* \param len is the length of the address buffer, must be at least 40 bytes
* \return true if address is read successfully, false otherwise
*/
bool getOwnIpAddress(char *address, int8_t len);
/**
* \brief Read border router IP address
*
* \param address is where the IP address will be copied
* \param len is the length of the address buffer, must be at least 40 bytes
* \return true if address is read successfully, false otherwise
*/
bool getRouterIpAddress(char *address, int8_t len);
friend class MeshInterfaceFactory;
private:
/*
* avoid copy/assign object
*/
Mesh6LoWPAN_ND(Mesh6LoWPAN_ND const &copy);
Mesh6LoWPAN_ND &operator=(Mesh6LoWPAN_ND const &copy);
};
#endif /* __MESH6LOWPAN_ND_H__ */

View File

@ -1,75 +0,0 @@
/*
* Copyright (c) 2015 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.
*/
#ifndef __MESHTHREAD_H__
#define __MESHTHREAD_H__
#include "AbstractMesh.h"
/**
* \brief 6LoWPAN Thread mesh networking class.
*/
class MeshThread : public AbstractMesh
{
public:
virtual ~MeshThread();
MeshThread();
/*
* \brief Initialization of the interface.
* \param registered device is physical device registered
* \param callbackHandler is callback that is called when network state changes
* \param eui64 pointer to MAC address (8 bytes) of the registered RF driver
* \param pskd Not used
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_PARAM when input parameters are illegal (also in case when RF device is already associated to other interface)
* \return MESH_ERROR_MEMORY in case of memory error
* \return MESH_ERROR_UNKNOWN in other error cases
*/
mesh_error_t init(int8_t registered_device_id, mesh_network_handler_t callbackHandler, uint8_t *eui64, char *pskd);
/**
* \brief Overriding initialization of the base class.
* Use method init(int8_t, MeshNetworkHandler_t, uint8_t*, char*)
*/
virtual mesh_error_t init(int8_t registered_device_id, mesh_network_handler_t callbackHandler);
bool getOwnIpAddress(char *address, int8_t len);
/**
* \brief Set device data polling rate to value given in parameter pollrate. Data polling will be
* disabled if pollrate value is 0.
* \param pollrate data polling rate in seconds. Setting this to 0 disables data polling.
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_PARAM in case timeout value is bigger than 864001.
* \return MESH_ERROR_UNKNOWN in case of other error.
* */
virtual mesh_error_t data_poll_rate_set(uint32_t pollrate);
friend class MeshInterfaceFactory;
private:
/*
* avoid copy/assign object
*/
MeshThread(MeshThread const &copy);
MeshThread &operator=(MeshThread const &copy);
};
#endif /* __MESHTHREAD_H__ */

View File

@ -14,47 +14,40 @@
* limitations under the License.
*/
#ifndef __ABSTRACTMESH_H__
#define __ABSTRACTMESH_H__
#ifndef THREADINTERFACE_H
#define THREADINTERFACE_H
#include "mbed.h"
#include "mesh_interface_types.h"
/**
* \brief Abstract Mesh networking interface.
* This class can't be instantiated directly.
*/
class AbstractMesh
{
#include "NanostackInterface.h"
class ThreadInterface : public MeshInterfaceNanostack {
public:
/**
* Typedef for network callback
/** Create an uninitialized LoWPANNDInterface
*
* Must initialize to initialize the mesh on a phy.
*/
typedef FunctionPointerArg1<void, mesh_connection_status_t> mesh_network_handler_t;
ThreadInterface() : MeshInterfaceNanostack() {
/**
* Constructor
* \param type mesh network type
}
/** Create an initialized MeshInterface
*
*/
AbstractMesh(mesh_network_type_t type);
ThreadInterface(NanostackRfPhy *phy) : MeshInterfaceNanostack(phy) {
// Destructor, force derived classes to implement own destructors
// and prevent class creation.
virtual ~AbstractMesh() = 0;
}
/**
int connect();
int disconnect();
private:
/*
* \brief Initialization of the interface.
* \param registered device is physical device registered
* \param callbackHandler is callback that is called when network state changes
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_PARAM when input parameters are illegal (also in case when RF device is already associated to other interface)
* \return MESH_ERROR_MEMORY in case of memory error
* \return MESH_ERROR_UNKNOWN in other error cases
*/
virtual mesh_error_t init(int8_t registered_device_id, mesh_network_handler_t callbackHandler);
mesh_error_t init();
/**
* \brief Connect interface to the mesh network
* \return MESH_ERROR_NONE on success.
@ -63,20 +56,14 @@ public:
* \return MESH_ERROR_STATE if interface is already connected to network.
* \return MESH_ERROR_UNKNOWN in case of unspecified error.
* */
virtual mesh_error_t connect();
mesh_error_t mesh_connect();
/**
* \brief Disconnect interface from the mesh network
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_UNKNOWN in case of error.
* */
virtual mesh_error_t disconnect();
/**
* \brief Callback from C-layer
* \param state state of the network
* */
void callback(mesh_connection_status_t state);
mesh_error_t mesh_disconnect();
/**
* \brief Read own global IP address
@ -85,29 +72,7 @@ public:
* \param len is the length of the address buffer, must be at least 40 bytes
* \return true if address is read successfully, false otherwise
*/
virtual bool getOwnIpAddress(char *address, int8_t len) = 0;
protected:
/*
* Mesh callback function
*/
mesh_network_handler_t _mesh_network_handler;
/*
* Network interface ID
*/
int8_t _network_interface_id;
/*
* Registered device ID
*/
int8_t _device_id;
/*
* Mesh network type
*/
mesh_network_type_t _mesh_network_type;
bool getOwnIpAddress(char *address, int8_t len);
};
#endif /* __ABSTRACTMESH_H__ */
#endif // THREADINTERFACE_H

View File

@ -1,140 +0,0 @@
/*
* Copyright (c) 2015 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.
*/
/*
* Mesh networking interface.
*/
#include "mbed-mesh-api/AbstractMesh.h"
#include "mbed-mesh-api/MeshThread.h"
#include "mbed-mesh-api/Mesh6LoWPAN_ND.h"
#include "include/callback_handler.h"
#include "include/mesh_system.h"
#include "include/nd_tasklet.h"
#include "include/thread_tasklet.h"
#define HAVE_DEBUG 1
#include "ns_trace.h"
#define TRACE_GROUP "m6La"
AbstractMesh::AbstractMesh(mesh_network_type_t type) :
_mesh_network_handler(NULL), _network_interface_id(-1), _device_id(-1)
{
__abstract_mesh_interface = this;
_mesh_network_type = type;
// initialize mesh networking resources, memory, timers, etc...
mesh_system_init();
}
AbstractMesh::~AbstractMesh()
{
tr_debug("~AbstractMesh()");
__abstract_mesh_interface = NULL;
}
mesh_error_t AbstractMesh::init(int8_t registered_device_id, mesh_network_handler_t callbackHandler)
{
tr_debug("init()");
if (callbackHandler == (mesh_network_handler_t)NULL) {
return MESH_ERROR_PARAM;
}
_device_id = registered_device_id;
_mesh_network_handler = callbackHandler;
// Create network interface
if (_mesh_network_type == MESH_TYPE_THREAD) {
thread_tasklet_init();
_network_interface_id = thread_tasklet_network_init(_device_id);
} else if (_mesh_network_type == MESH_TYPE_6LOWPAN_ND) {
nd_tasklet_init();
_network_interface_id = nd_tasklet_network_init(_device_id);
}
if (_network_interface_id >= 0) {
return MESH_ERROR_NONE;
} else if (_network_interface_id == -2) {
return MESH_ERROR_PARAM;
} else if (_network_interface_id == -3) {
return MESH_ERROR_MEMORY;
}
return MESH_ERROR_UNKNOWN;
}
mesh_error_t AbstractMesh::connect()
{
int8_t status = -9; // init to unknown error
tr_debug("connect()");
if (_mesh_network_handler == (mesh_network_handler_t)NULL) {
// initialization hasn't been made and connect gets called
return MESH_ERROR_PARAM;
}
if (_mesh_network_type == MESH_TYPE_THREAD) {
status = thread_tasklet_connect(&__mesh_handler_c_callback, _network_interface_id);
} else if (_mesh_network_type == MESH_TYPE_6LOWPAN_ND) {
status = nd_tasklet_connect(&__mesh_handler_c_callback, _network_interface_id);
}
if (status >= 0) {
return MESH_ERROR_NONE;
} else if (status == -1) {
return MESH_ERROR_PARAM;
} else if (status == -2) {
return MESH_ERROR_MEMORY;
} else if (status == -3) {
return MESH_ERROR_STATE;
} else {
return MESH_ERROR_UNKNOWN;
}
}
/*
* Disable optimization as gcc compiler fails to return correct enum value.
*/
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
#define DISABLE_GCC_OPT __attribute__((optimize("O0")))
#else
#define DISABLE_GCC_OPT
#endif
mesh_error_t DISABLE_GCC_OPT AbstractMesh::disconnect()
{
int8_t status = -1;
if (_mesh_network_type == MESH_TYPE_THREAD) {
status = thread_tasklet_disconnect(true);
} else if (_mesh_network_type == MESH_TYPE_6LOWPAN_ND) {
status = nd_tasklet_disconnect(true);
}
if (status >= 0) {
return MESH_ERROR_NONE;
}
return MESH_ERROR_UNKNOWN;
}
void AbstractMesh::callback(mesh_connection_status_t state)
{
if (_mesh_network_handler) {
_mesh_network_handler(state);
}
}

View File

@ -17,12 +17,17 @@
#include "include/callback_handler.h"
AbstractMesh *__abstract_mesh_interface = NULL;
static MeshInterfaceNanostack *_handler = NULL;
void __mesh_handler_c_callback(mesh_connection_status_t state)
{
if (__abstract_mesh_interface) {
__abstract_mesh_interface->callback(state);
if (_handler) {
_handler->mesh_network_handler(state);
}
}
void __mesh_handler_set_callback(MeshInterfaceNanostack *handler)
{
_handler = handler;
}

View File

@ -0,0 +1,128 @@
#include "LoWPANNDInterface.h"
#include "include/nd_tasklet.h"
#include "callback_handler.h"
#include "mesh_system.h"
#include "randLIB.h"
#include "ns_trace.h"
#define TRACE_GROUP "nslp"
#include "nanostack-event-loop/eventOS_scheduler.h"
#define nanostack_lock() eventOS_scheduler_mutex_wait()
#define nanostack_unlock() eventOS_scheduler_mutex_release()
#define nanostack_assert_locked() //MBED_ASSERT(eventOS_scheduler_mutex_is_owner())
int LoWPANNDInterface::connect()
{
nanostack_lock();
if (register_rf() < 0) {
nanostack_unlock();
return NSAPI_ERROR_DEVICE_ERROR;
}
// After the RF is up, we can seed the random from it.
randLIB_seed_random();
mesh_error_t status = init();
if (status != MESH_ERROR_NONE) {
nanostack_unlock();
return map_mesh_error(status);
}
status = mesh_connect();
if (status != MESH_ERROR_NONE) {
nanostack_unlock();
return map_mesh_error(status);
}
// Release mutex before blocking
nanostack_unlock();
int32_t count = connect_semaphore.wait(30000);
if (count <= 0) {
return NSAPI_ERROR_DHCP_FAILURE; // sort of...
}
return 0;
}
int LoWPANNDInterface::disconnect()
{
nanostack_lock();
mesh_error_t status = mesh_disconnect();
nanostack_unlock();
return map_mesh_error(status);
}
mesh_error_t LoWPANNDInterface::init()
{
nd_tasklet_init();
__mesh_handler_set_callback(this);
_network_interface_id = nd_tasklet_network_init(_device_id);
if (_network_interface_id == -2) {
return MESH_ERROR_PARAM;
} else if (_network_interface_id == -3) {
return MESH_ERROR_MEMORY;
} else if (_network_interface_id < 0) {
return MESH_ERROR_UNKNOWN;
}
return MESH_ERROR_NONE;
}
mesh_error_t LoWPANNDInterface::mesh_connect()
{
int8_t status = -9; // init to unknown error
tr_debug("connect()");
status = nd_tasklet_connect(&__mesh_handler_c_callback, _network_interface_id);
if (status >= 0) {
return MESH_ERROR_NONE;
} else if (status == -1) {
return MESH_ERROR_PARAM;
} else if (status == -2) {
return MESH_ERROR_MEMORY;
} else if (status == -3) {
return MESH_ERROR_STATE;
} else {
return MESH_ERROR_UNKNOWN;
}
}
mesh_error_t LoWPANNDInterface::mesh_disconnect()
{
int8_t status = -1;
status = nd_tasklet_disconnect(true);
if (status >= 0) {
return MESH_ERROR_NONE;
}
return MESH_ERROR_UNKNOWN;
}
bool LoWPANNDInterface::getOwnIpAddress(char *address, int8_t len)
{
tr_debug("getOwnIpAddress()");
if (nd_tasklet_get_ip_address(address, len) == 0) {
return true;
}
return false;
}
bool LoWPANNDInterface::getRouterIpAddress(char *address, int8_t len)
{
tr_debug("getRouterIpAddress()");
if (nd_tasklet_get_router_ip_address(address, len) == 0) {
return true;
}
return false;
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2015 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.
*/
/*
* 6LoWPAN ND (neighbor discovery) network interface.
* Class provides methods for 6LoWPAN (ND) network handling.l
*/
#include <stdio.h>
#include "mbed.h"
#include "mbed-mesh-api/Mesh6LoWPAN_ND.h"
#include "include/nd_tasklet.h"
#define HAVE_DEBUG 1
#include "ns_trace.h"
#define TRACE_GROUP "m6LND"
Mesh6LoWPAN_ND::Mesh6LoWPAN_ND() : AbstractMesh(MESH_TYPE_6LOWPAN_ND)
{
}
Mesh6LoWPAN_ND::~Mesh6LoWPAN_ND()
{
tr_debug("~Mesh6LoWPAN()");
nd_tasklet_disconnect(false);
}
bool Mesh6LoWPAN_ND::getOwnIpAddress(char *address, int8_t len)
{
tr_debug("getOwnIpAddress()");
if (nd_tasklet_get_ip_address(address, len) == 0) {
return true;
}
return false;
}
bool Mesh6LoWPAN_ND::getRouterIpAddress(char *address, int8_t len)
{
tr_debug("getRouterIpAddress()");
if (nd_tasklet_get_router_ip_address(address, len) == 0) {
return true;
}
return false;
}

View File

@ -1,93 +0,0 @@
/*
* Copyright (c) 2015 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.
*/
/*
* Thread network interface.
* Class provides methods for 6LoWPAN (Thread mode) network handling.
*/
#include <stdio.h>
#include "mbed.h"
#include "mbed-mesh-api/MeshThread.h"
#include "include/thread_tasklet.h"
#include "include/callback_handler.h"
#define HAVE_DEBUG 1
#include "ns_trace.h"
#define TRACE_GROUP "m6LTh"
MeshThread::MeshThread() : AbstractMesh(MESH_TYPE_THREAD)
{
}
MeshThread::~MeshThread()
{
tr_debug("~MeshThread()");
thread_tasklet_disconnect(false);
}
mesh_error_t MeshThread::init(int8_t registered_device_id, mesh_network_handler_t callbackHandler, uint8_t *eui64, char *pskd)
{
if (eui64 == NULL) {
return MESH_ERROR_PARAM;
}
mesh_error_t status = AbstractMesh::init(registered_device_id, callbackHandler);
if (status == MESH_ERROR_NONE) {
thread_tasklet_device_config_set(eui64, pskd);
}
return status;
}
mesh_error_t MeshThread::init(int8_t registered_device_id, mesh_network_handler_t callbackHandler)
{
// TODO: Use test values for device configuration
return MeshThread::init(registered_device_id, callbackHandler, NULL, NULL);
}
bool MeshThread::getOwnIpAddress(char *address, int8_t len)
{
tr_debug("getOwnIpAddress()");
if (thread_tasklet_get_ip_address(address, len) == 0) {
return true;
}
return false;
}
mesh_error_t MeshThread::data_poll_rate_set(uint32_t pollrate)
{
mesh_error_t status = MESH_ERROR_NONE;
int8_t retval = thread_tasklet_data_poll_rate_set(pollrate);
switch (retval) {
case 0:
status = MESH_ERROR_NONE;
break;
case -2:
status = MESH_ERROR_PARAM;
break;
default:
//case -1:
status = MESH_ERROR_UNKNOWN;
break;
}
return status;
}

View File

@ -0,0 +1,123 @@
#include "ThreadInterface.h"
#include "include/thread_tasklet.h"
#include "callback_handler.h"
#include "mesh_system.h"
#include "randLIB.h"
#include "ns_trace.h"
#define TRACE_GROUP "nsth"
#include "nanostack-event-loop/eventOS_scheduler.h"
#define nanostack_lock() eventOS_scheduler_mutex_wait()
#define nanostack_unlock() eventOS_scheduler_mutex_release()
#define nanostack_assert_locked() //MBED_ASSERT(eventOS_scheduler_mutex_is_owner())
int ThreadInterface::connect()
{
nanostack_lock();
if (register_rf() < 0) {
nanostack_unlock();
return NSAPI_ERROR_DEVICE_ERROR;
}
// After the RF is up, we can seed the random from it.
randLIB_seed_random();
mesh_error_t status = init();
if (status != MESH_ERROR_NONE) {
nanostack_unlock();
return map_mesh_error(status);
}
status = mesh_connect();
if (status != MESH_ERROR_NONE) {
nanostack_unlock();
return map_mesh_error(status);
}
// Release mutex before blocking
nanostack_unlock();
int32_t count = connect_semaphore.wait(30000);
if (count <= 0) {
return NSAPI_ERROR_DHCP_FAILURE; // sort of...
}
return 0;
}
int ThreadInterface::disconnect()
{
nanostack_lock();
mesh_error_t status = mesh_disconnect();
nanostack_unlock();
return map_mesh_error(status);
}
mesh_error_t ThreadInterface::init()
{
if (eui64 == NULL) {
return MESH_ERROR_PARAM;
}
thread_tasklet_init();
__mesh_handler_set_callback(this);
thread_tasklet_device_config_set(eui64, NULL);
_network_interface_id = thread_tasklet_network_init(_device_id);
if (_network_interface_id == -2) {
return MESH_ERROR_PARAM;
} else if (_network_interface_id == -3) {
return MESH_ERROR_MEMORY;
} else if (_network_interface_id < 0) {
return MESH_ERROR_UNKNOWN;
}
return MESH_ERROR_NONE;
}
bool ThreadInterface::getOwnIpAddress(char *address, int8_t len)
{
tr_debug("getOwnIpAddress()");
if (thread_tasklet_get_ip_address(address, len) == 0) {
return true;
}
return false;
}
mesh_error_t ThreadInterface::mesh_connect()
{
int8_t status;
tr_debug("connect()");
status = thread_tasklet_connect(&__mesh_handler_c_callback, _network_interface_id);
if (status >= 0) {
return MESH_ERROR_NONE;
} else if (status == -1) {
return MESH_ERROR_PARAM;
} else if (status == -2) {
return MESH_ERROR_MEMORY;
} else if (status == -3) {
return MESH_ERROR_STATE;
} else {
return MESH_ERROR_UNKNOWN;
}
}
mesh_error_t ThreadInterface::mesh_disconnect()
{
int8_t status;
status = thread_tasklet_disconnect(true);
if (status >= 0) {
return MESH_ERROR_NONE;
}
return MESH_ERROR_UNKNOWN;
}

View File

@ -18,9 +18,7 @@
#define __INCLUDE_CALLBACK_HANDLER_H__
#include "mbed.h"
#include "mbed-mesh-api/AbstractMesh.h"
extern AbstractMesh *__abstract_mesh_interface;
#include "mesh_interface_types.h"
#ifdef __cplusplus
extern "C" {
@ -32,6 +30,9 @@ void __mesh_handler_c_callback(mesh_connection_status_t state);
}
#endif
#ifdef __cplusplus
#include "NanostackInterface.h"
void __mesh_handler_set_callback(MeshInterfaceNanostack *handler);
#endif
#endif /* __INCLUDE_CALLBACK_HANDLER_H__ */

View File

@ -26,11 +26,18 @@
#include "mesh_system.h" // from inside mbed-mesh-api
#include "socket_api.h"
#include "net_interface.h"
// Uncomment to enable trace
//#define HAVE_DEBUG
#include "ns_trace.h"
#define TRACE_GROUP "nsif"
#include "nanostack-event-loop/eventOS_scheduler.h"
#define nanostack_lock() eventOS_scheduler_mutex_wait()
#define nanostack_unlock() eventOS_scheduler_mutex_release()
#define nanostack_assert_locked() //MBED_ASSERT(eventOS_scheduler_mutex_is_owner())
#define NS_INTERFACE_SOCKETS_MAX 16 //same as NanoStack SOCKET_MAX
#define NANOSTACK_SOCKET_UDP 17 // same as nanostack SOCKET_UDP
#define NANOSTACK_SOCKET_TCP 6 // same as nanostack SOCKET_TCP
@ -38,10 +45,6 @@
#define MALLOC ns_dyn_mem_alloc
#define FREE ns_dyn_mem_free
#define nanostack_lock() eventOS_scheduler_mutex_wait()
#define nanostack_unlock() eventOS_scheduler_mutex_release()
#define nanostack_assert_locked() //MBED_ASSERT(eventOS_scheduler_mutex_is_owner())
enum socket_mode_t {
SOCKET_MODE_UNOPENED, // No socket ID
SOCKET_MODE_OPENED, // Socket ID but no assigned use yet
@ -107,7 +110,7 @@ private:
static NanostackSocket * socket_tbl[NS_INTERFACE_SOCKETS_MAX];
static nsapi_error_t map_mesh_error(mesh_error_t err)
nsapi_error_t map_mesh_error(mesh_error_t err)
{
switch (err) {
case MESH_ERROR_NONE: return 0;
@ -443,20 +446,21 @@ void NanostackSocket::event_connnect_closed(socket_callback_t *sock_cb)
}
MeshInterfaceNanostack::MeshInterfaceNanostack()
: phy(NULL), mesh_api(NULL), rf_device_id(-1), eui64(),
: phy(NULL), _network_interface_id(-1), _device_id(-1), eui64(),
ip_addr_str(), mac_addr_str(), connect_semaphore(0)
{
// Nothing to do
}
MeshInterfaceNanostack::MeshInterfaceNanostack(NanostackRfPhy *phy)
: phy(phy), mesh_api(NULL), rf_device_id(-1), connect_semaphore(0)
: phy(phy), _network_interface_id(-1), _device_id(-1), connect_semaphore(0)
{
// Nothing to do
}
nsapi_error_t MeshInterfaceNanostack::initialize(NanostackRfPhy *phy)
{
mesh_system_init();
if (this->phy != NULL) {
error("Phy already set");
}
@ -479,8 +483,8 @@ nsapi_error_t MeshInterfaceNanostack::register_rf()
{
nanostack_lock();
rf_device_id = phy->rf_register();
if (rf_device_id < 0) {
_device_id = phy->rf_register();
if (_device_id < 0) {
nanostack_unlock();
return -1;
}
@ -493,51 +497,17 @@ nsapi_error_t MeshInterfaceNanostack::register_rf()
return 0;
}
nsapi_error_t MeshInterfaceNanostack::actual_connect()
{
nanostack_assert_locked();
mesh_error_t status = mesh_api->connect();
if (status != MESH_ERROR_NONE) {
nanostack_unlock();
return map_mesh_error(status);
}
// Release mutex before blocking
nanostack_unlock();
int32_t count = connect_semaphore.wait(30000);
nanostack_lock();
if (count <= 0) {
return NSAPI_ERROR_DHCP_FAILURE; // sort of...
}
return 0;
}
NetworkStack * MeshInterfaceNanostack::get_stack()
{
return NanostackInterface::get_stack();
}
nsapi_error_t MeshInterfaceNanostack::disconnect()
{
nanostack_lock();
mesh_error_t status = mesh_api->disconnect();
nanostack_unlock();
return map_mesh_error(status);
}
const char *MeshInterfaceNanostack::get_ip_address()
{
nanostack_lock();
const char *ret = NULL;
if (mesh_api && mesh_api->getOwnIpAddress(ip_addr_str, sizeof ip_addr_str)) {
if (getOwnIpAddress(ip_addr_str, sizeof ip_addr_str)) {
ret = ip_addr_str;
}
@ -551,68 +521,6 @@ const char *MeshInterfaceNanostack::get_mac_address()
return mac_addr_str;
}
nsapi_error_t ThreadInterface::connect()
{
// initialize mesh networking resources, memory, timers, etc...
mesh_system_init();
nanostack_lock();
mesh_api = new MeshThread;
if (!mesh_api) {
nanostack_unlock();
return NSAPI_ERROR_NO_MEMORY;
}
if (register_rf() < 0) {
nanostack_unlock();
return NSAPI_ERROR_DEVICE_ERROR;
}
// After the RF is up, we can seed the random from it.
randLIB_seed_random();
mesh_error_t status = ((MeshThread *)mesh_api)->init(rf_device_id, AbstractMesh::mesh_network_handler_t(static_cast<MeshInterfaceNanostack *>(this), &ThreadInterface::mesh_network_handler), eui64, NULL);
if (status != MESH_ERROR_NONE) {
nanostack_unlock();
return map_mesh_error(status);
}
nsapi_error_t ret = this->actual_connect();
nanostack_unlock();
return ret;
}
nsapi_error_t LoWPANNDInterface::connect()
{
// initialize mesh networking resources, memory, timers, etc...
mesh_system_init();
nanostack_lock();
mesh_api = new Mesh6LoWPAN_ND;
if (!mesh_api) {
nanostack_unlock();
return NSAPI_ERROR_NO_MEMORY;
}
if (register_rf() < 0) {
nanostack_unlock();
return NSAPI_ERROR_DEVICE_ERROR;
}
// After the RF is up, we can seed the random from it.
randLIB_seed_random();
mesh_error_t status = ((Mesh6LoWPAN_ND *)mesh_api)->init(rf_device_id, AbstractMesh::mesh_network_handler_t(static_cast<MeshInterfaceNanostack *>(this), &LoWPANNDInterface::mesh_network_handler));
if (status != MESH_ERROR_NONE) {
nanostack_unlock();
return map_mesh_error(status);
}
nsapi_error_t ret = this->actual_connect();
nanostack_unlock();
return ret;
}
NanostackInterface * NanostackInterface::_ns_interface;
NanostackInterface * NanostackInterface::get_stack()

View File

@ -1,16 +1,27 @@
/*
* Copyright (c) 2016 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.
*/
#ifndef NANOSTACK_INTERFACE_H_
#define NANOSTACK_INTERFACE_H_
#include "mbed.h"
#include "NetworkStack.h"
#include "MeshInterface.h"
#include "NanostackRfPhy.h"
#include "mbed-mesh-api/Mesh6LoWPAN_ND.h"
#include "mbed-mesh-api/MeshThread.h"
#include "mesh_interface_types.h"
class NanostackInterface : public NetworkStack {
public:
@ -240,7 +251,7 @@ public:
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t disconnect();
virtual nsapi_error_t disconnect() = 0;
/** Get the internally stored IP address
/return IP address of the interface or null if not yet connected
@ -252,72 +263,56 @@ public:
*/
virtual const char *get_mac_address();
/**
* \brief Callback from C-layer
* \param state state of the network
* */
void mesh_network_handler(mesh_connection_status_t status);
protected:
MeshInterfaceNanostack();
MeshInterfaceNanostack(NanostackRfPhy *phy);
nsapi_error_t register_rf();
nsapi_error_t actual_connect();
virtual NetworkStack * get_stack(void);
void mesh_network_handler(mesh_connection_status_t status);
/**
* \brief Connect interface to the mesh network
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_PARAM in case of illegal parameters.
* \return MESH_ERROR_MEMORY in case of memory error.
* \return MESH_ERROR_STATE if interface is already connected to network.
* \return MESH_ERROR_UNKNOWN in case of unspecified error.
* */
virtual mesh_error_t mesh_connect() = 0;
/**
* \brief Disconnect interface from the mesh network
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_UNKNOWN in case of error.
* */
virtual mesh_error_t mesh_disconnect() = 0;
/**
* \brief Read own global IP address
*
* \param address is where the IP address will be copied
* \param len is the length of the address buffer, must be at least 40 bytes
* \return true if address is read successfully, false otherwise
*/
virtual bool getOwnIpAddress(char *address, int8_t len) = 0;
NanostackRfPhy *phy;
AbstractMesh *mesh_api;
int8_t rf_device_id;
/** Network interface ID */
int8_t _network_interface_id;
/** Registered device ID */
int8_t _device_id;
uint8_t eui64[8];
char ip_addr_str[40];
char mac_addr_str[24];
Semaphore connect_semaphore;
};
class LoWPANNDInterface : public MeshInterfaceNanostack {
public:
/** Create an uninitialized LoWPANNDInterface
*
* Must initialize to initialize the mesh on a phy.
*/
LoWPANNDInterface() : MeshInterfaceNanostack() {
}
/** Create an initialized MeshInterface
*
*/
LoWPANNDInterface(NanostackRfPhy *phy) : MeshInterfaceNanostack(phy) {
}
nsapi_error_t connect();
protected:
Mesh6LoWPAN_ND *get_mesh_api() const { return static_cast<Mesh6LoWPAN_ND *>(mesh_api); }
private:
};
class ThreadInterface : public MeshInterfaceNanostack {
public:
/** Create an uninitialized LoWPANNDInterface
*
* Must initialize to initialize the mesh on a phy.
*/
ThreadInterface() : MeshInterfaceNanostack() {
}
/** Create an initialized MeshInterface
*
*/
ThreadInterface(NanostackRfPhy *phy) : MeshInterfaceNanostack(phy) {
}
nsapi_error_t connect();
protected:
MeshThread *get_mesh_api() const { return static_cast<MeshThread *>(mesh_api); }
private:
};
nsapi_error_t map_mesh_error(mesh_error_t err);
#endif /* NANOSTACK_INTERFACE_H_ */