Merge pull request #3267 from SeppoTakalo/mesh_refactor

ONME-2857: Ethernet interface for Nanostack
pull/3321/head
Russ Butler 2016-11-22 12:59:50 -05:00 committed by GitHub
commit f843d49247
32 changed files with 1119 additions and 1074 deletions

View File

@ -4,6 +4,8 @@ ARM mbed mesh API allows the client to use the IPv6 mesh network.
The client can use the `LoWPANNDInterface` or `ThreadInterface` object for connecting to the mesh network and when successfully connected, the client can create a socket by using the [mbed C++ socket API](https://developer.mbed.org/teams/NetworkSocketAPI/code/NetworkSocketAPI/docs/tip/) to start communication with a remote peer.
For ethernet `NanostackEthernetInterface` is provided.
## Supported mesh networking modes
Currently, 6LoWPAN-ND (neighbour discovery) and Thread bootstrap modes are supported.
@ -27,18 +29,18 @@ An example of the configuration file:
}
```
**Configurable parameters in section `mbed-mesh-api`:**
### Configurable parameters in section mbed-mesh-api
| Parameter name | Value | Description |
| --------------- | ------------- | ----------- |
| heap-size | number [0-0xfffe] | Nanostack's internal heap size |
**Thread related configuration parameters:**
### Thread related configuration parameters
| Parameter name | Value | Description |
| --------------- | ------------- | ----------- |
| thread-pskd | string [6-255 chars] | Human-scaled commissioning credentials. |
| hread-device-type | enum from mesh_device_type_t | Set device operating mode. |
| thread-device-type | enum from mesh_device_type_t | Set device operating mode. |
| thread-config-channel-mask | number [0-0x07fff800] | Channel mask, 0x07fff800 scans all channels. |
| thread-config-channel-page | number [0, 2]| Channel page, 0 for 2,4 GHz and 2 for sub-GHz radios. |
| thread-config-channel | number [0-27] | RF channel to use. |
@ -47,7 +49,7 @@ An example of the configuration file:
| thread-config-ml-prefix | byte array [8] | Mesh local prefix. |
| thread-config-pskc | byte array [16] | Pre-Shared Key for the Commissioner. |
**6LoWPAN related configuration parameters:**
### 6LoWPAN related configuration parameters
| Parameter name | Type | Description |
| --------------- | ---------| ----------- |
@ -63,7 +65,9 @@ An example of the configuration file:
## Usage notes
This module should not be used directly by the applications. The applications should use the `LoWPANNDInterface` or `ThreadInterface` directly.
This module should not be used directly by the applications. The applications should use the `LoWPANNDInterface`, `ThreadInterface` or `NanostackEthernetInterface` directly.
When using Ethernet interface, there is no configuration options available. It is using dynamic mode to learn the IPv6 prefix from the network. No static configuration is supported.
### Network connection states
@ -77,13 +81,20 @@ See the example application [mbed-os-example-mesh-minimal](https://github.com/AR
## Usage example for 6LoWPAN ND mode
**Create a network interface:**
Create a network interface and driver objects.
```
LoWPANNDInterface mesh;
NanostackRfPhyNcs36510 rf_phy;
```
**Connect:**
Initialize interface with given PHY driver.
```
mesh.initialize(&rf_phy);
```
Then connect to network:
```
if (mesh.connect()) {
@ -102,3 +113,23 @@ Basically the same as for ND, but the network interface uses different class:
ThreadInterface mesh;
mesh.connect();
```
## Usage example with Ethernet
API is still the same, you just need to provide a driver that implements `NanostackEthernetPhy` API.
```
NanostackEthernetInterface eth;
NanostackEthernetPhyK64F phy;
int main() {
eth.initialize(&phy);
if (eth.connect()) {
printf("Connection failed!\r\n");
return -1;
}
printf("connected. IP = %s\r\n", eth.get_ip_address());
}
```

View File

@ -1,114 +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 __ABSTRACTMESH_H__
#define __ABSTRACTMESH_H__
#include "AbstractNetworkInterface.h"
#include "mbed.h"
#ifdef YOTTA_CFG
#include "core-util/FunctionPointer.h"
using namespace mbed;
using namespace mbed::util;
#endif
/**
* \brief Abstract Mesh networking interface.
* This class can't be instantiated directly.
*/
class AbstractMesh : public AbstractNetworkInterface
{
public:
/**
* Typedef for network callback
*/
#ifdef YOTTA_CFG
typedef FunctionPointer1<void, mesh_connection_status_t> mesh_network_handler_t;
#else
typedef FunctionPointerArg1<void, mesh_connection_status_t> mesh_network_handler_t;
#endif
/**
* Constructor
* \param type mesh network type
*/
AbstractMesh(mesh_network_type_t type);
// Destructor, force derived classes to implement own destructors
// and prevent class creation.
virtual ~AbstractMesh() = 0;
/**
* \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);
/**
* \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 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);
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;
};
#endif /* __ABSTRACTMESH_H__ */

View File

@ -1,60 +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 __ABSTRACTNETWORKINTERFACE_H__
#define __ABSTRACTNETWORKINTERFACE_H__
#include <stdint.h>
#include "mesh_interface_types.h"
/**
* \brief Abstract base class for network interfaces.
* This is a pure virtual class; it can't instantiated directly, but
* it provides common functionality for derived classes.
*
* Note! This class will be replaced by connection manager when it is available.
*/
class AbstractNetworkInterface
{
public:
/**
* Virtual destructor.
*/
virtual ~AbstractNetworkInterface();
/**
* Connect the interface to the network.
*/
virtual mesh_error_t connect() = 0;
/**
* Disconnect the interface from the network.
*/
virtual mesh_error_t 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;
};
#endif /* __ABSTRACTNETWORKINTERFACE_H__ */

View File

@ -0,0 +1,47 @@
/*
* 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 "MeshInterfaceNanostack.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) { }
nsapi_error_t initialize(NanostackRfPhy *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,66 +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:
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:
/*
* \brief private constructor for the 6LoWPAN_ND
*/
Mesh6LoWPAN_ND();
/*
* avoid copy/assign object
*/
Mesh6LoWPAN_ND(Mesh6LoWPAN_ND const &copy);
Mesh6LoWPAN_ND &operator=(Mesh6LoWPAN_ND const &copy);
};
#endif /* __MESH6LOWPAN_ND_H__ */

View File

@ -1,50 +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 __MESHINTERFACEFACTORY_H__
#define __MESHINTERFACEFACTORY_H__
#include <stdlib.h>
#include "AbstractMesh.h"
/**
* \brief MeshInterfaceFactory.
* This is a factory class provides interface for creating Mesh Interface
* object for application to utilize mesh networking.
*/
class MeshInterfaceFactory
{
public:
/**
* \brief Creates Mesh interface object that can be used for connecting
* to mesh network.
* \param type, type of the mesh network.
* \return M2MInterfaceImpl , Object to manage other LWM2M operations.
*/
static AbstractMesh *createInterface(const mesh_network_type_t &type);
private:
// Prevents the use of assignment operator by accident.
MeshInterfaceFactory &operator=(const MeshInterfaceFactory & /*other*/);
// Prevents the use of copy constructor by accident
MeshInterfaceFactory(const MeshInterfaceFactory & /*other*/);
};
#endif /* __MESHINTERFACEFACTORY_H__ */

View File

@ -0,0 +1,91 @@
/*
* 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 MESHINTERFACENANOSTACK_H
#define MESHINTERFACENANOSTACK_H
#include "mbed.h"
#include "MeshInterface.h"
#include "NanostackRfPhy.h"
#include "mesh_interface_types.h"
class MeshInterfaceNanostack : public MeshInterface {
public:
/** Attach phy and initialize the mesh
*
* Initializes a mesh interface on the given phy. Not needed if
* the phy is passed to the mesh's constructor.
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t initialize(NanostackPhy *phy);
/** Start the interface
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t connect() = 0;
/** Stop the interface
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t disconnect() = 0;
/** Get the internally stored IP address
/return IP address of the interface or null if not yet connected
*/
virtual const char *get_ip_address();
/** Get the internally stored MAC address
/return MAC address of the interface
*/
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(NanostackPhy *phy);
nsapi_error_t register_phy();
virtual NetworkStack * get_stack(void);
/**
* \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;
NanostackPhy *phy;
/** 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;
};
#endif /* MESHINTERFACENANOSTACK_H */

View File

@ -1,79 +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();
/*
* \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:
/*
* \brief private constructor for the MeshThread
*/
MeshThread();
/*
* avoid copy/assign object
*/
MeshThread(MeshThread const &copy);
MeshThread &operator=(MeshThread const &copy);
};
#endif /* __MESHTHREAD_H__ */

View File

@ -0,0 +1,36 @@
/*
* 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 NANOSTACKETHERNETINTERFACE_H
#define NANOSTACKETHERNETINTERFACE_H
#include "MeshInterfaceNanostack.h"
#include "NanostackEthernetPhy.h"
class NanostackEthernetInterface : public MeshInterfaceNanostack {
public:
NanostackEthernetInterface() : MeshInterfaceNanostack() { }
NanostackEthernetInterface(NanostackEthernetPhy *phy) : MeshInterfaceNanostack(phy) { }
nsapi_error_t initialize(NanostackEthernetPhy *phy);
int connect();
int disconnect();
bool getOwnIpAddress(char *address, int8_t len);
bool getRouterIpAddress(char *address, int8_t len);
};
#endif // NANOSTACKETHERNETINTERFACE_H

View File

@ -0,0 +1,75 @@
/*
* 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 THREADINTERFACE_H
#define THREADINTERFACE_H
#include "MeshInterfaceNanostack.h"
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 initialize(NanostackRfPhy *phy);
int connect();
int disconnect();
private:
/*
* \brief Initialization of the interface.
* \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();
/**
* \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.
* */
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.
* */
mesh_error_t mesh_disconnect();
/**
* \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);
};
#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

@ -1,26 +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.
*/
/*
* Abstract networking interface.
*/
#include "mbed.h"
#include "mbed-mesh-api/AbstractNetworkInterface.h"
AbstractNetworkInterface::~AbstractNetworkInterface()
{
}

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,127 @@
#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"
nsapi_error_t LoWPANNDInterface::initialize(NanostackRfPhy *phy)
{
return MeshInterfaceNanostack::initialize(phy);
}
int LoWPANNDInterface::connect()
{
nanostack_lock();
if (register_phy() < 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,42 +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.h"
#include "mbed-mesh-api/Mesh6LoWPAN_ND.h"
#include "mbed-mesh-api/MeshThread.h"
#include "include/callback_handler.h"
#include "mbed-mesh-api/MeshInterfaceFactory.h"
AbstractMesh *MeshInterfaceFactory::createInterface(const mesh_network_type_t &type)
{
AbstractMesh *meshInstance = NULL;
// instance can be created only if there is no existing instance.
if (__abstract_mesh_interface == NULL) {
if (type == MESH_TYPE_6LOWPAN_ND) {
meshInstance = (AbstractMesh *)new Mesh6LoWPAN_ND;
}
if (type == MESH_TYPE_THREAD) {
meshInstance = (AbstractMesh *)new MeshThread;
}
}
return meshInstance;
}

View File

@ -0,0 +1,95 @@
/*
* 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.
*/
#include "MeshInterfaceNanostack.h"
#include "NanostackInterface.h"
#include "mesh_system.h"
MeshInterfaceNanostack::MeshInterfaceNanostack()
: phy(NULL), _network_interface_id(-1), _device_id(-1), eui64(),
ip_addr_str(), mac_addr_str(), connect_semaphore(0)
{
// Nothing to do
}
MeshInterfaceNanostack::MeshInterfaceNanostack(NanostackPhy *phy)
: phy(phy), _network_interface_id(-1), _device_id(-1), connect_semaphore(0)
{
// Nothing to do
}
nsapi_error_t MeshInterfaceNanostack::initialize(NanostackPhy *phy)
{
mesh_system_init();
if (this->phy != NULL) {
error("Phy already set");
}
this->phy = phy;
return 0;
}
void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t status)
{
nanostack_lock();
if (status == MESH_CONNECTED) {
connect_semaphore.release();
}
nanostack_unlock();
}
nsapi_error_t MeshInterfaceNanostack::register_phy()
{
nanostack_lock();
_device_id = phy->phy_register();
if (_device_id < 0) {
nanostack_unlock();
return -1;
}
// Read mac address after registering the device.
phy->get_mac_address(eui64);
sprintf(mac_addr_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", eui64[0], eui64[1], eui64[2], eui64[3], eui64[4], eui64[5], eui64[6], eui64[7]);
nanostack_unlock();
return 0;
}
NetworkStack * MeshInterfaceNanostack::get_stack()
{
return NanostackInterface::get_stack();
}
const char *MeshInterfaceNanostack::get_ip_address()
{
nanostack_lock();
const char *ret = NULL;
if (getOwnIpAddress(ip_addr_str, sizeof ip_addr_str)) {
ret = ip_addr_str;
}
nanostack_unlock();
return ret;
}
const char *MeshInterfaceNanostack::get_mac_address()
{
return mac_addr_str;
}

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,84 @@
/*
* 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.
*/
#include "NanostackEthernetInterface.h"
#include "mesh_system.h"
#include "callback_handler.h"
#include "enet_tasklet.h"
nsapi_error_t NanostackEthernetInterface::initialize(NanostackEthernetPhy *phy)
{
nsapi_error_t err = MeshInterfaceNanostack::initialize(phy);
if (err != NSAPI_ERROR_OK)
return err;
nanostack_lock();
if (register_phy() < 0) {
nanostack_unlock();
return NSAPI_ERROR_DEVICE_ERROR;
}
enet_tasklet_init();
__mesh_handler_set_callback(this);
_network_interface_id = enet_tasklet_network_init(_device_id);
nanostack_unlock();
if (_network_interface_id < 0)
return MESH_ERROR_UNKNOWN;
else
return MESH_ERROR_NONE;
}
int NanostackEthernetInterface::connect()
{
nanostack_lock();
int8_t status = enet_tasklet_connect(&__mesh_handler_c_callback, _network_interface_id);
nanostack_unlock();
if (status == -1) {
return MESH_ERROR_PARAM;
} else if (status == -2) {
return MESH_ERROR_MEMORY;
} else if (status == -3) {
return MESH_ERROR_STATE;
} else if (status != 0) {
return MESH_ERROR_UNKNOWN;
}
int32_t count = connect_semaphore.wait(30000);
if (count <= 0) {
return NSAPI_ERROR_DHCP_FAILURE; // sort of...
}
return 0;
}
int NanostackEthernetInterface::disconnect()
{
enet_tasklet_disconnect();
return 0;
}
bool NanostackEthernetInterface::getOwnIpAddress(char *address, int8_t len)
{
return enet_tasklet_get_ip_address(address, len)?false:true;
}
bool NanostackEthernetInterface::getRouterIpAddress(char *address, int8_t len)
{
return false;
}

View File

@ -0,0 +1,122 @@
#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"
nsapi_error_t ThreadInterface::initialize(NanostackRfPhy *phy)
{
return MeshInterfaceNanostack::initialize(phy);
}
int ThreadInterface::connect()
{
nanostack_lock();
if (register_phy() < 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

@ -0,0 +1,281 @@
/*
* 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.
*/
#include <string.h> //memset
#include "eventOS_event_timer.h"
#include "common_functions.h"
#include "net_interface.h"
#include "ip6string.h" //ip6tos
#include "nsdynmemLIB.h"
#include "include/static_config.h"
#include "include/mesh_system.h"
#include "ns_event_loop.h"
#include "mesh_interface_types.h"
#include "eventOS_event.h"
// For tracing we need to define flag, have include and define group
#include "ns_trace.h"
#define TRACE_GROUP "IPV6"
#include "ethernet_mac_api.h"
#define INTERFACE_NAME "eth0"
// Tasklet timer events
#define TIMER_EVENT_START_BOOTSTRAP 1
#define INVALID_INTERFACE_ID (-1)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
/*
* Mesh tasklet states.
*/
typedef enum {
TASKLET_STATE_CREATED = 0,
TASKLET_STATE_INITIALIZED,
TASKLET_STATE_BOOTSTRAP_STARTED,
TASKLET_STATE_BOOTSTRAP_FAILED,
TASKLET_STATE_BOOTSTRAP_READY
} tasklet_state_t;
/*
* Mesh tasklet data structure.
*/
typedef struct {
void (*mesh_api_cb)(mesh_connection_status_t nwk_status);
tasklet_state_t tasklet_state;
int8_t node_main_tasklet_id;
int8_t network_interface_id;
int8_t tasklet;
} tasklet_data_str_t;
/* Tasklet data */
static tasklet_data_str_t *tasklet_data_ptr = NULL;
static eth_mac_api_t *eth_mac_api = NULL;
typedef void (*mesh_interface_cb)(mesh_connection_status_t mesh_status);
/* private function prototypes */
static void enet_tasklet_main(arm_event_s *event);
static void enet_tasklet_network_state_changed(mesh_connection_status_t status);
static void enet_tasklet_parse_network_event(arm_event_s *event);
static void enet_tasklet_configure_and_connect_to_network(void);
/*
* \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver.
* @param event, describes the sender, receiver and event type.
*
* NOTE: Interrupts requested by HW are possible during this function!
*/
void enet_tasklet_main(arm_event_s *event)
{
arm_library_event_type_e event_type;
event_type = (arm_library_event_type_e) event->event_type;
switch (event_type) {
case ARM_LIB_NWK_INTERFACE_EVENT:
/* This event is delivered every and each time when there is new
* information of network connectivity.
*/
enet_tasklet_parse_network_event(event);
break;
case ARM_LIB_TASKLET_INIT_EVENT:
/* Event with type EV_INIT is an initializer event of NanoStack OS.
* The event is delivered when the NanoStack OS is running fine.
* This event should be delivered ONLY ONCE.
*/
tasklet_data_ptr->node_main_tasklet_id = event->receiver;
mesh_system_send_connect_event(tasklet_data_ptr->tasklet);
break;
case ARM_LIB_SYSTEM_TIMER_EVENT:
eventOS_event_timer_cancel(event->event_id,
tasklet_data_ptr->node_main_tasklet_id);
if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) {
tr_debug("Restart bootstrap");
enet_tasklet_configure_and_connect_to_network();
}
break;
case APPLICATION_EVENT:
if (event->event_id == APPL_EVENT_CONNECT) {
enet_tasklet_configure_and_connect_to_network();
}
break;
default:
break;
} // switch(event_type)
}
/**
* \brief Network state event handler.
* \param event show network start response or current network state.
*
* - ARM_NWK_BOOTSTRAP_READY: Save NVK persistent data to NVM and Net role
* - ARM_NWK_NWK_SCAN_FAIL: Link Layer Active Scan Fail, Stack is Already at Idle state
* - ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: No ND Router at current Channel Stack is Already at Idle state
* - ARM_NWK_NWK_CONNECTION_DOWN: Connection to Access point is lost wait for Scan Result
* - ARM_NWK_NWK_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels
* - ARM_NWK_AUHTENTICATION_FAIL: Pana Authentication fail, Stack is Already at Idle state
*/
void enet_tasklet_parse_network_event(arm_event_s *event)
{
arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e) event->event_data;
tr_debug("app_parse_network_event() %d", status);
switch (status) {
case ARM_NWK_BOOTSTRAP_READY:
/* Network is ready and node is connected to Access Point */
if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) {
tr_info("IPv6 bootstrap ready");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY;
enet_tasklet_network_state_changed(MESH_CONNECTED);
}
break;
case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
/* No ND Router at current Channel Stack is Already at Idle state */
tr_info("Bootstrap fail");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
break;
case ARM_NWK_NWK_CONNECTION_DOWN:
/* Connection to Access point is lost wait for Scan Result */
tr_info("Connection lost");
tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
break;
default:
tr_warn("Unknown event %d", status);
break;
}
if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) {
// Set 5s timer for new network scan
eventOS_event_timer_request(TIMER_EVENT_START_BOOTSTRAP,
ARM_LIB_SYSTEM_TIMER_EVENT,
tasklet_data_ptr->node_main_tasklet_id,
5000);
}
}
/*
* \brief Configure and establish network connection
*
*/
void enet_tasklet_configure_and_connect_to_network(void)
{
arm_nwk_interface_up(tasklet_data_ptr->network_interface_id);
}
/*
* Inform application about network state change
*/
void enet_tasklet_network_state_changed(mesh_connection_status_t status)
{
if (tasklet_data_ptr->mesh_api_cb) {
(tasklet_data_ptr->mesh_api_cb)(status);
}
}
/* Public functions */
int8_t enet_tasklet_get_ip_address(char *address, int8_t len)
{
uint8_t binary_ipv6[16];
if ((len >= 40) && (0 == arm_net_address_get(
tasklet_data_ptr->network_interface_id, ADDR_IPV6_GP, binary_ipv6))) {
ip6tos(binary_ipv6, address);
//tr_debug("IP address: %s", address);
return 0;
} else {
return -1;
}
}
int8_t enet_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id)
{
int8_t re_connecting = true;
int8_t tasklet_id = tasklet_data_ptr->tasklet;
if (tasklet_data_ptr->tasklet_state == TASKLET_STATE_CREATED) {
re_connecting = false;
}
memset(tasklet_data_ptr, 0, sizeof(tasklet_data_str_t));
tasklet_data_ptr->mesh_api_cb = callback;
tasklet_data_ptr->network_interface_id = nwk_interface_id;
tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED;
if (re_connecting == false) {
tasklet_data_ptr->tasklet = eventOS_event_handler_create(&enet_tasklet_main,
ARM_LIB_TASKLET_INIT_EVENT);
if (tasklet_data_ptr->tasklet < 0) {
// -1 handler already used by other tasklet
// -2 memory allocation failure
return tasklet_data_ptr->tasklet;
}
} else {
tasklet_data_ptr->tasklet = tasklet_id;
mesh_system_send_connect_event(tasklet_data_ptr->tasklet);
}
return 0;
}
int8_t enet_tasklet_disconnect(bool send_cb)
{
int8_t status = -1;
if (tasklet_data_ptr != NULL) {
if (tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) {
status = arm_nwk_interface_down(tasklet_data_ptr->network_interface_id);
tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID;
if (send_cb == true) {
enet_tasklet_network_state_changed(MESH_DISCONNECTED);
}
}
tasklet_data_ptr->mesh_api_cb = NULL;
}
return status;
}
void enet_tasklet_init(void)
{
if (tasklet_data_ptr == NULL) {
tasklet_data_ptr = ns_dyn_mem_alloc(sizeof(tasklet_data_str_t));
tasklet_data_ptr->tasklet_state = TASKLET_STATE_CREATED;
tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID;
}
}
int8_t enet_tasklet_network_init(int8_t device_id)
{
if (tasklet_data_ptr->network_interface_id != -1) {
tr_debug("Interface already at active state\n");
return tasklet_data_ptr->network_interface_id;
}
if (!eth_mac_api) {
eth_mac_api = ethernet_mac_create(device_id);
}
tasklet_data_ptr->network_interface_id = arm_nwk_interface_ethernet_init(eth_mac_api, "eth0");
tr_debug("interface ID: %d", tasklet_data_ptr->network_interface_id);
arm_nwk_interface_configure_ipv6_bootstrap_set(
tasklet_data_ptr->network_interface_id, NET_IPV6_BOOTSTRAP_AUTONOMOUS, NULL);
return tasklet_data_ptr->network_interface_id;
}

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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 ARM Limited. All rights reserved.
* 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.
@ -13,16 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#ifdef YOTTA_CFG
/* At the moment, nothing in the Yotta build is providing these */
void arm_random_module_init(void)
{
}
#ifndef ENET_TASKLET_H
#define ENET_TASKLET_H
uint32_t arm_random_seed_get(void)
{
return 0;
#ifdef __cplusplus
extern "C" {
#endif
void enet_tasklet_init(void);
uint8_t enet_tasklet_network_init(int8_t);
int8_t enet_tasklet_connect(void (*)(mesh_connection_status_t mesh_status), int8_t nwk_interface_id);
void enet_tasklet_disconnect();
int8_t enet_tasklet_get_ip_address(char *address, int8_t len);
#ifdef __cplusplus
}
#endif
#endif // ENET_TASKLET_H

View File

@ -42,4 +42,11 @@ void mesh_system_init(void);
#ifdef __cplusplus
}
#endif
#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())
#endif /* __INCLUDE_MESH_SYSTEM__ */

View File

@ -20,11 +20,7 @@
#include "nsdynmemLIB.h"
#include "randLIB.h"
#include "platform/arm_hal_timer.h"
#ifdef YOTTA_CFG
#include "sal-iface-6lowpan/ns_sal.h"
#else
#include "ns_hal_init.h"
#endif
#include "include/static_config.h"
#include "include/mesh_system.h"
// For tracing we need to define flag, have include and define group
@ -60,23 +56,11 @@ static void mesh_system_heap_error_handler(heap_fail_t event)
void mesh_system_init(void)
{
if (mesh_initialized == false) {
#ifndef YOTTA_CFG
ns_hal_init(app_stack_heap, MBED_MESH_API_HEAP_SIZE,
mesh_system_heap_error_handler, NULL);
eventOS_scheduler_mutex_wait();
net_init_core();
eventOS_scheduler_mutex_release();
#else
ns_dyn_mem_init(app_stack_heap, MBED_MESH_API_HEAP_SIZE,
mesh_system_heap_error_handler, NULL);
randLIB_seed_random();
platform_timer_enable();
eventOS_scheduler_init();
trace_init(); // trace system needs to be initialized right after eventOS_scheduler_init
net_init_core();
/* initialize 6LoWPAN socket adaptation layer */
ns_sal_init_stack();
#endif
mesh_initialized = true;
}
}

View File

@ -23,9 +23,8 @@
#include "include/nd_tasklet.h"
#include "include/static_config.h"
#include "include/mesh_system.h"
#ifndef YOTTA_CFG
#include "ns_event_loop.h"
#endif
// For tracing we need to define flag, have include and define group
#define HAVE_DEBUG 1
#include "ns_trace.h"
@ -386,9 +385,7 @@ int8_t nd_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id)
// -2 memory allocation failure
return tasklet_data_ptr->tasklet;
}
#ifndef YOTTA_CFG
ns_event_loop_thread_start();
#endif
} else {
tasklet_data_ptr->tasklet = tasklet_id;
mesh_system_send_connect_event(tasklet_data_ptr->tasklet);

View File

@ -25,9 +25,8 @@
#include "include/thread_tasklet.h"
#include "include/static_config.h"
#include "include/mesh_system.h"
#ifndef YOTTA_CFG
#include "ns_event_loop.h"
#endif
// For tracing we need to define flag, have include and define group
#define HAVE_DEBUG 1
#include "ns_trace.h"
@ -396,9 +395,7 @@ int8_t thread_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_i
// -2 memory allocation failure
return thread_tasklet_data_ptr->tasklet;
}
#ifndef YOTTA_CFG
ns_event_loop_thread_start();
#endif
} else {
thread_tasklet_data_ptr->tasklet = tasklet;
mesh_system_send_connect_event(thread_tasklet_data_ptr->tasklet);
@ -449,7 +446,7 @@ int8_t thread_tasklet_network_init(int8_t device_id)
void thread_tasklet_device_config_set(uint8_t *eui64, char *pskd)
{
(void) pskd; // this parameter is delivered via yotta configuration
(void) pskd; // this parameter is delivered via mbed configuration
memcpy(device_configuration.eui64, eui64, 8);
}

View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 2016 ARM Limited. All rights reserved.
*/
#ifndef NANOSTACK_ETHERNET_PHY_H_
#define NANOSTACK_ETHERNET_PHY_H_
#include "NanostackPhy.h"
class NanostackEthernetPhy : public NanostackPhy {
};
#endif /* NANOSTACK_INTERFACE_H_ */

View File

@ -23,11 +23,10 @@
#include "eventOS_scheduler.h"
#include "randLIB.h"
#include "mbed-mesh-api/MeshInterfaceFactory.h"
#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"
@ -40,10 +39,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
@ -109,7 +104,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;
@ -444,177 +439,6 @@ void NanostackSocket::event_connnect_closed(socket_callback_t *sock_cb)
close();
}
MeshInterfaceNanostack::MeshInterfaceNanostack()
: phy(NULL), mesh_api(NULL), rf_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)
{
// Nothing to do
}
nsapi_error_t MeshInterfaceNanostack::initialize(NanostackRfPhy *phy)
{
if (this->phy != NULL) {
error("Phy already set");
}
this->phy = phy;
return 0;
}
void MeshInterfaceNanostack::mesh_network_handler(mesh_connection_status_t status)
{
nanostack_lock();
if (status == MESH_CONNECTED) {
connect_semaphore.release();
}
nanostack_unlock();
}
nsapi_error_t MeshInterfaceNanostack::register_rf()
{
nanostack_lock();
rf_device_id = phy->rf_register();
if (rf_device_id < 0) {
nanostack_unlock();
return -1;
}
// Read mac address after registering the device.
phy->get_mac_address(eui64);
sprintf(mac_addr_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", eui64[0], eui64[1], eui64[2], eui64[3], eui64[4], eui64[5], eui64[6], eui64[7]);
nanostack_unlock();
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)) {
ret = ip_addr_str;
}
nanostack_unlock();
return ret;
}
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 = MeshInterfaceFactory::createInterface(MESH_TYPE_THREAD);
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 = MeshInterfaceFactory::createInterface(MESH_TYPE_6LOWPAN_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()
@ -633,8 +457,10 @@ NanostackInterface * NanostackInterface::get_stack()
const char * NanostackInterface::get_ip_address()
{
// Unsupported
return NULL;
// Must result a valid IPv6 address
// For gethostbyname() to detect IP version.
static const char localhost[] = "::";
return localhost;
}
nsapi_error_t NanostackInterface::socket_open(void **handle, nsapi_protocol_t protocol)

View File

@ -1,16 +1,30 @@
/*
* 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 here for backward compatibility
#include "LoWPANNDInterface.h"
#include "ThreadInterface.h"
#include "NanostackEthernetInterface.h"
#include "MeshInterfaceNanostack.h"
class NanostackInterface : public NetworkStack {
public:
@ -218,106 +232,6 @@ private:
static NanostackInterface * _ns_interface;
};
class MeshInterfaceNanostack : public MeshInterface {
public:
/** Attach phy and initialize the mesh
*
* Initializes a mesh interface on the given phy. Not needed if
* the phy is passed to the mesh's constructor.
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t initialize(NanostackRfPhy *phy);
/** Start the interface
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t connect() = 0;
/** Stop the interface
*
* @return 0 on success, negative on failure
*/
virtual nsapi_error_t disconnect();
/** Get the internally stored IP address
/return IP address of the interface or null if not yet connected
*/
virtual const char *get_ip_address();
/** Get the internally stored MAC address
/return MAC address of the interface
*/
virtual const char *get_mac_address();
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);
NanostackRfPhy *phy;
AbstractMesh *mesh_api;
int8_t rf_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_ */

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2016 ARM Limited. All rights reserved.
*/
#ifndef NANOSTACK_PHY_H_
#define NANOSTACK_PHY_H_
class NanostackPhy {
public:
/** Register this physical interface with Nanostack
*
* @return Device driver ID or a negative error
* code on failure
*/
virtual int8_t phy_register() = 0;
/** Read the mac address of this physical interface
*
* Note - some devices do not have a mac address
* in hardware.
*/
virtual void get_mac_address(uint8_t *mac) = 0;
/** Set the mac address of this physical interface
*
*/
virtual void set_mac_address(uint8_t *mac) = 0;
protected:
NanostackPhy() {}
virtual ~NanostackPhy() {}
};
#endif /* NANOSTACK_INTERFACE_H_ */

View File

@ -5,7 +5,9 @@
#ifndef NANOSTACK_RF_PHY_H_
#define NANOSTACK_RF_PHY_H_
class NanostackRfPhy {
#include "NanostackPhy.h"
class NanostackRfPhy : public NanostackPhy {
public:
/** Register this physical interface with Nanostack
@ -20,21 +22,17 @@ public:
*/
virtual void rf_unregister() = 0;
/** Read the mac address of this physical interface
/** Register this physical interface with Nanostack
*
* Note - some devices do not have a mac address
* in hardware.
* @return Device driver ID or a negative error
* code on failure
*/
virtual void get_mac_address(uint8_t *mac) = 0;
int8_t phy_register() { return rf_register();}
/** Set the mac address of this physical interface
/** Unregister this physical interface
*
*/
virtual void set_mac_address(uint8_t *mac) = 0;
protected:
NanostackRfPhy() {}
virtual ~NanostackRfPhy() {}
void unregister() { rf_unregister(); }
};
#endif /* NANOSTACK_INTERFACE_H_ */
#endif /* NANOSTACK_RF_PHY_H_ */