Knight KE / Mbed OS Game_Master
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 int ThreadInterface::connect()
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 
00089     return _interface->bringup(false, NULL, NULL, NULL, IPV6_STACK, _blocking);
00090 }
00091 
00092 nsapi_error_t Nanostack::ThreadInterface::bringup(bool dhcp, const char *ip,
00093                                                   const char *netmask, const char *gw,
00094                                                   nsapi_ip_stack_t stack, bool blocking)
00095 {
00096     if (_connect_status == NSAPI_STATUS_GLOBAL_UP  || _connect_status == NSAPI_STATUS_LOCAL_UP ) {
00097         return NSAPI_ERROR_IS_CONNECTED ;
00098     } else if (_connect_status == NSAPI_STATUS_CONNECTING ) {
00099         return NSAPI_ERROR_ALREADY ;
00100     }
00101 
00102     if (stack == IPV4_STACK) {
00103         return NSAPI_ERROR_UNSUPPORTED ;
00104     }
00105 
00106     if (register_phy() < 0) {
00107         return NSAPI_ERROR_DEVICE_ERROR ;
00108     }
00109     nanostack_lock();
00110 
00111     _blocking = blocking;
00112 
00113     // After the RF is up, we can seed the random from it.
00114     randLIB_seed_random();
00115 
00116     mesh_error_t status = init();
00117     if (status != MESH_ERROR_NONE) {
00118         nanostack_unlock();
00119         return map_mesh_error(status);
00120     }
00121 
00122     status = mesh_connect();
00123     if (status != MESH_ERROR_NONE) {
00124         nanostack_unlock();
00125         return map_mesh_error(status);
00126     }
00127 
00128     // Release mutex before blocking
00129     nanostack_unlock();
00130 
00131     // In Thread wait connection for ever:
00132     // -routers will create new network and get local connectivity
00133     // -end devices will get connectivity once attached to existing network
00134     // -devices without network settings gets connectivity once commissioned and attached to network
00135     _connect_status = NSAPI_STATUS_CONNECTING ;
00136     if (_connection_status_cb) {
00137         _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_CONNECTING );
00138     }
00139     if (_blocking) {
00140         int32_t count = connect_semaphore.wait(osWaitForever);
00141 
00142         if (count <= 0) {
00143             return NSAPI_ERROR_DHCP_FAILURE ; // sort of...
00144         }
00145     }
00146     return 0;
00147 }
00148 
00149 int ThreadInterface::disconnect()
00150 {
00151     return _interface->bringdown();
00152 }
00153 
00154 nsapi_error_t Nanostack::ThreadInterface::bringdown()
00155 {
00156     nanostack_lock();
00157 
00158     mesh_error_t status = mesh_disconnect();
00159 
00160     nanostack_unlock();
00161 
00162     return map_mesh_error(status);
00163 }
00164 
00165 mesh_error_t Nanostack::ThreadInterface::init()
00166 {
00167     thread_tasklet_init();
00168     __mesh_handler_set_callback(this);
00169     device_eui64_get(NULL); // Ensure we've selected the EUI-64 - this does it
00170     interface_id = thread_tasklet_network_init(_device_id);
00171 
00172     if (interface_id == -2) {
00173         return MESH_ERROR_PARAM;
00174     } else if (interface_id == -3) {
00175         return MESH_ERROR_MEMORY;
00176     } else if (interface_id < 0) {
00177         return MESH_ERROR_UNKNOWN;
00178     }
00179     return MESH_ERROR_NONE;
00180 }
00181 
00182 mesh_error_t Nanostack::ThreadInterface::mesh_connect()
00183 {
00184     int8_t status;
00185     tr_debug("connect()");
00186 
00187     status = thread_tasklet_connect(&__mesh_handler_c_callback, interface_id);
00188 
00189     if (status >= 0) {
00190         return MESH_ERROR_NONE;
00191     } else if (status == -1) {
00192         return MESH_ERROR_PARAM;
00193     } else if (status == -2) {
00194         return MESH_ERROR_MEMORY;
00195     } else if (status == -3) {
00196         return MESH_ERROR_STATE;
00197     } else {
00198         return MESH_ERROR_UNKNOWN;
00199     }
00200 }
00201 
00202 mesh_error_t Nanostack::ThreadInterface::mesh_disconnect()
00203 {
00204     int8_t status;
00205 
00206     status = thread_tasklet_disconnect(true);
00207 
00208     if (status >= 0) {
00209         return MESH_ERROR_NONE;
00210     }
00211 
00212     return MESH_ERROR_UNKNOWN;
00213 }
00214 
00215 void ThreadInterface::device_eui64_set(const uint8_t *eui64)
00216 {
00217     get_interface()->device_eui64_set(eui64);
00218 }
00219 
00220 void ThreadInterface::device_eui64_get(uint8_t *eui64)
00221 {
00222     get_interface()->device_eui64_get(eui64);
00223 }
00224 
00225 void Nanostack::ThreadInterface::device_eui64_set(const uint8_t *eui64)
00226 {
00227     eui64_set = true;
00228     thread_tasklet_device_eui64_set(eui64);
00229 }
00230 
00231 void Nanostack::ThreadInterface::device_eui64_get(uint8_t *eui64)
00232 {
00233     if (!eui64_set) {
00234         uint8_t eui64_buf[8];
00235         get_phy().get_mac_address(eui64_buf);
00236         device_eui64_set(eui64_buf);
00237     }
00238 
00239     if (eui64) {
00240         thread_tasklet_device_eui64_get(eui64);
00241     }
00242 }
00243 
00244 mesh_error_t ThreadInterface::device_pskd_set(const char *pskd)
00245 {
00246     return get_interface()->device_pskd_set(pskd);
00247 }
00248 
00249 mesh_error_t Nanostack::ThreadInterface::device_pskd_set(const char *pskd)
00250 {
00251     return (mesh_error_t)thread_tasklet_device_pskd_set(pskd);
00252 }
00253 
00254 #define THREAD 0x2345
00255 #if MBED_CONF_NSAPI_DEFAULT_MESH_TYPE == THREAD && DEVICE_802_15_4_PHY
00256 MBED_WEAK MeshInterface *MeshInterface::get_target_default_instance()
00257 {
00258     static ThreadInterface thread(NanostackRfPhy::get_default_instance());
00259 
00260     return thread;
00261 }
00262 #endif