takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ThreadInterface.cpp Source File

ThreadInterface.cpp

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