Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ThreadInterface.cpp Source File

ThreadInterface.cpp

00001 /*
00002  * Copyright (c) 2018 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "ThreadInterface.h"
00018 #include "include/thread_tasklet.h"
00019 #include "callback_handler.h"
00020 #include "mesh_system.h"
00021 #include "randLIB.h"
00022 
00023 #include "ns_trace.h"
00024 #define TRACE_GROUP "nsth"
00025 
00026 class Nanostack::ThreadInterface : public Nanostack::MeshInterface {
00027 public:
00028     virtual nsapi_error_t bringup(bool dhcp, const char *ip,
00029                                   const char *netmask, const char *gw,
00030                                   nsapi_ip_stack_t stack = IPV6_STACK,
00031                                   bool blocking = true);
00032     virtual nsapi_error_t bringdown();
00033     friend class Nanostack;
00034     friend class ::ThreadInterface;
00035 private:
00036     ThreadInterface(NanostackRfPhy &phy) : MeshInterface(phy), eui64_set(false) { }
00037 
00038     /*
00039      * \brief Initialization of the interface.
00040      * \return MESH_ERROR_NONE on success.
00041      * \return MESH_ERROR_PARAM when input parameters are illegal (also in case when RF device is already associated to other interface)
00042      * \return MESH_ERROR_MEMORY in case of memory error
00043      * \return MESH_ERROR_UNKNOWN in other error cases
00044      */
00045     mesh_error_t init();
00046     /**
00047      * \brief Connect interface to the mesh network
00048      * \return MESH_ERROR_NONE on success.
00049      * \return MESH_ERROR_PARAM in case of illegal parameters.
00050      * \return MESH_ERROR_MEMORY in case of memory error.
00051      * \return MESH_ERROR_STATE if interface is already connected to network.
00052      * \return MESH_ERROR_UNKNOWN in case of unspecified error.
00053      * */
00054     mesh_error_t mesh_connect();
00055 
00056     /**
00057      * \brief Disconnect interface from the mesh network
00058      * \return MESH_ERROR_NONE on success.
00059      * \return MESH_ERROR_UNKNOWN in case of error.
00060      * */
00061     mesh_error_t mesh_disconnect();
00062 
00063     /**
00064      * \brief Sets the eui64 for the device configuration.
00065      * By default this value is read from the radio driver.
00066      * The value must be set before calling the connect function.
00067      * */
00068     void device_eui64_set(const uint8_t *eui64);
00069 
00070     /**
00071      * \brief Reads the eui64 from the device configuration.
00072      * */
00073     void device_eui64_get(uint8_t *eui64);
00074 
00075     /**
00076      * \brief sets the PSKd for the device configuration.
00077      * The default value is overwritten, which is defined in the mbed_lib.json file in the mesh-api
00078      * The value must be set before calling the connect function.
00079      * \return MESH_ERROR_NONE on success.
00080      * \return MESH_ERROR_PARAM in case of illegal parameters.
00081      * \return MESH_ERROR_MEMORY in case of memory error.
00082      * */
00083 
00084     mesh_error_t device_pskd_set(const char *pskd);
00085 
00086     bool eui64_set;
00087 };
00088 
00089 Nanostack::ThreadInterface *ThreadInterface::get_interface() const
00090 {
00091     return static_cast<Nanostack::ThreadInterface *>(_interface);
00092 }
00093 
00094 nsapi_error_t ThreadInterface::do_initialize()
00095 {
00096     if (!_interface) {
00097         _interface = new (std::nothrow) Nanostack::ThreadInterface(*_phy);
00098         if (!_interface) {
00099             return NSAPI_ERROR_NO_MEMORY ;
00100         }
00101         _interface->attach(_connection_status_cb);
00102     }
00103     return NSAPI_ERROR_OK ;
00104 }
00105 
00106 nsapi_error_t Nanostack::ThreadInterface::bringup(bool dhcp, const char *ip,
00107                                                   const char *netmask, const char *gw,
00108                                                   nsapi_ip_stack_t stack, bool blocking)
00109 {
00110     if (_connect_status == NSAPI_STATUS_GLOBAL_UP  || _connect_status == NSAPI_STATUS_LOCAL_UP ) {
00111         return NSAPI_ERROR_IS_CONNECTED ;
00112     } else if (_connect_status == NSAPI_STATUS_CONNECTING ) {
00113         return NSAPI_ERROR_ALREADY ;
00114     }
00115 
00116     if (stack == IPV4_STACK) {
00117         return NSAPI_ERROR_UNSUPPORTED ;
00118     }
00119 
00120     if (register_phy() < 0) {
00121         return NSAPI_ERROR_DEVICE_ERROR ;
00122     }
00123     nanostack_lock();
00124 
00125     _blocking = blocking;
00126 
00127     // After the RF is up, we can seed the random from it.
00128     randLIB_seed_random();
00129 
00130     mesh_error_t status = init();
00131     if (status != MESH_ERROR_NONE) {
00132         nanostack_unlock();
00133         return map_mesh_error(status);
00134     }
00135 
00136     status = mesh_connect();
00137     if (status != MESH_ERROR_NONE) {
00138         nanostack_unlock();
00139         return map_mesh_error(status);
00140     }
00141 
00142     // Release mutex before blocking
00143     nanostack_unlock();
00144 
00145     // In Thread wait connection for ever:
00146     // -routers will create new network and get local connectivity
00147     // -end devices will get connectivity once attached to existing network
00148     // -devices without network settings gets connectivity once commissioned and attached to network
00149     _connect_status = NSAPI_STATUS_CONNECTING ;
00150     if (_blocking) {
00151         connect_semaphore.acquire();
00152     }
00153     return 0;
00154 }
00155 
00156 nsapi_error_t Nanostack::ThreadInterface::bringdown()
00157 {
00158     nanostack_lock();
00159 
00160     mesh_error_t status = mesh_disconnect();
00161 
00162     nanostack_unlock();
00163 
00164     return map_mesh_error(status);
00165 }
00166 
00167 mesh_error_t Nanostack::ThreadInterface::init()
00168 {
00169     thread_tasklet_init();
00170     __mesh_handler_set_callback(this);
00171     device_eui64_get(NULL); // Ensure we've selected the EUI-64 - this does it
00172     interface_id = thread_tasklet_network_init(_device_id);
00173 
00174     if (interface_id == -2) {
00175         return MESH_ERROR_PARAM;
00176     } else if (interface_id == -3) {
00177         return MESH_ERROR_MEMORY;
00178     } else if (interface_id < 0) {
00179         return MESH_ERROR_UNKNOWN;
00180     }
00181     return MESH_ERROR_NONE;
00182 }
00183 
00184 mesh_error_t Nanostack::ThreadInterface::mesh_connect()
00185 {
00186     int8_t status;
00187     tr_debug("connect()");
00188 
00189     status = thread_tasklet_connect(&__mesh_handler_c_callback, interface_id);
00190 
00191     if (status >= 0) {
00192         return MESH_ERROR_NONE;
00193     } else if (status == -1) {
00194         return MESH_ERROR_PARAM;
00195     } else if (status == -2) {
00196         return MESH_ERROR_MEMORY;
00197     } else if (status == -3) {
00198         return MESH_ERROR_STATE;
00199     } else {
00200         return MESH_ERROR_UNKNOWN;
00201     }
00202 }
00203 
00204 mesh_error_t Nanostack::ThreadInterface::mesh_disconnect()
00205 {
00206     int8_t status;
00207 
00208     status = thread_tasklet_disconnect(true);
00209 
00210     if (status >= 0) {
00211         return MESH_ERROR_NONE;
00212     }
00213 
00214     return MESH_ERROR_UNKNOWN;
00215 }
00216 
00217 void ThreadInterface::device_eui64_set(const uint8_t *eui64)
00218 {
00219     get_interface()->device_eui64_set(eui64);
00220 }
00221 
00222 void ThreadInterface::device_eui64_get(uint8_t *eui64)
00223 {
00224     memset(eui64, 0, 8);
00225     if (!get_interface()) {
00226         return;
00227     }
00228     get_interface()->device_eui64_get(eui64);
00229 }
00230 
00231 void Nanostack::ThreadInterface::device_eui64_set(const uint8_t *eui64)
00232 {
00233     eui64_set = true;
00234     thread_tasklet_device_eui64_set(eui64);
00235 }
00236 
00237 void Nanostack::ThreadInterface::device_eui64_get(uint8_t *eui64)
00238 {
00239     if (!eui64_set) {
00240         uint8_t eui64_buf[8];
00241         if (register_phy() < 0) {
00242             return;
00243         }
00244         get_phy().get_mac_address(eui64_buf);
00245         device_eui64_set(eui64_buf);
00246     }
00247 
00248     if (eui64) {
00249         thread_tasklet_device_eui64_get(eui64);
00250     }
00251 }
00252 
00253 mesh_error_t ThreadInterface::device_pskd_set(const char *pskd)
00254 {
00255     return get_interface()->device_pskd_set(pskd);
00256 }
00257 
00258 mesh_error_t Nanostack::ThreadInterface::device_pskd_set(const char *pskd)
00259 {
00260     return (mesh_error_t)thread_tasklet_device_pskd_set(pskd);
00261 }
00262 
00263 #define THREAD 0x2345
00264 #if MBED_CONF_NSAPI_DEFAULT_MESH_TYPE == THREAD && DEVICE_802_15_4_PHY
00265 
00266 MBED_WEAK MeshInterface *MeshInterface::get_target_default_instance()
00267 {
00268     static bool inited;
00269     static ThreadInterface interface;
00270     singleton_lock();
00271     if (!inited) {
00272         nsapi_error_t result = interface.initialize(&NanostackRfPhy::get_default_instance());
00273         if (result != 0) {
00274             tr_error("Thread initialize failed: %d", result);
00275             singleton_unlock();
00276             return NULL;
00277         }
00278         inited = true;
00279     }
00280     singleton_unlock();
00281     return &interface;
00282 }
00283 #endif