Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wisun_tasklet.c Source File

wisun_tasklet.c

00001 /*
00002  * Copyright (c) 2018-2019 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 <string.h> //memset
00018 #include "eventOS_event_timer.h"
00019 #include "common_functions.h"
00020 #include "ip6string.h"  //ip6tos
00021 #include "nsdynmemLIB.h"
00022 #include "include/wisun_tasklet.h"
00023 #include "include/mesh_system.h"
00024 #include "ns_event_loop.h"
00025 #include "fhss_api.h "
00026 #include "fhss_config.h "
00027 #include "multicast_api.h"
00028 #include "mac_api.h"
00029 #include "sw_mac.h"
00030 #include "ns_list.h"
00031 #include "net_interface.h"
00032 #include "ws_management_api.h" //ws_management_node_init
00033 #ifdef MBED_CONF_MBED_MESH_API_CERTIFICATE_HEADER
00034 #if !defined(MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE) || !defined(MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE) || \
00035     !defined(MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY)
00036 #error Invalid Wi-SUN certificate configuration
00037 #endif
00038 #include MBED_CONF_MBED_MESH_API_CERTIFICATE_HEADER
00039 #endif
00040 
00041 // For tracing we need to define flag, have include and define group
00042 //#define HAVE_DEBUG
00043 #define TRACE_GROUP  "WSND"
00044 #include "ns_trace.h"
00045 
00046 // Tasklet timer events
00047 #define TIMER_EVENT_START_BOOTSTRAP   1
00048 #define INVALID_INTERFACE_ID        (-1)
00049 #define INTERFACE_NAME              "WiSunInterface"
00050 /*
00051  * Mesh tasklet states.
00052  */
00053 typedef enum {
00054     TASKLET_STATE_CREATED = 0,
00055     TASKLET_STATE_INITIALIZED,
00056     TASKLET_STATE_BOOTSTRAP_STARTED,
00057     TASKLET_STATE_BOOTSTRAP_FAILED,
00058     TASKLET_STATE_BOOTSTRAP_READY
00059 } tasklet_state_t;
00060 
00061 /*
00062  * Mesh tasklet data structure.
00063  */
00064 typedef struct {
00065     void (*mesh_api_cb)(mesh_connection_status_t nwk_status);
00066     tasklet_state_t tasklet_state;
00067     int8_t tasklet;
00068     net_6lowpan_mode_e operating_mode;
00069     net_6lowpan_mode_extension_e operating_mode_extension;
00070     int8_t network_interface_id;
00071 } wisun_tasklet_data_str_t;
00072 
00073 typedef struct {
00074     char *network_name;
00075     uint8_t regulatory_domain;
00076     uint8_t rd_operating_class;
00077     uint8_t rd_operating_mode;
00078     uint8_t uc_channel_function;
00079     uint8_t bc_channel_function;
00080     uint8_t uc_dwell_interval;
00081     uint32_t bc_interval;
00082     uint8_t bc_dwell_interval;
00083     uint16_t uc_fixed_channel;
00084     uint16_t bc_fixed_channel;
00085 } wisun_network_settings_t;
00086 
00087 typedef struct {
00088     arm_certificate_entry_s arm_cert_entry;
00089     ns_list_link_t      link; /*!< List link entry */
00090 } wisun_certificate_entry_t;
00091 
00092 typedef NS_LIST_HEAD (wisun_certificate_entry_t, link) cert_list_t;
00093 typedef struct {
00094     cert_list_t own_certificates_list;
00095     cert_list_t trusted_certificates_list;
00096     bool remove_own_certificates: 1;
00097     bool remove_trusted_certificates: 1;
00098 } wisun_certificates_t;
00099 
00100 #define WS_NA 0xff       // Not applicable value
00101 #define WS_DEFAULT 0x00  // Use default value
00102 
00103 /* Tasklet data */
00104 static wisun_tasklet_data_str_t *wisun_tasklet_data_ptr = NULL;
00105 static wisun_certificates_t *wisun_certificates_ptr = NULL;
00106 static wisun_network_settings_t wisun_settings_str = {
00107     .network_name = NULL,
00108     .regulatory_domain = MBED_CONF_MBED_MESH_API_WISUN_REGULATORY_DOMAIN,
00109     .rd_operating_class = MBED_CONF_MBED_MESH_API_WISUN_OPERATING_CLASS,
00110     .rd_operating_mode = MBED_CONF_MBED_MESH_API_WISUN_OPERATING_MODE,
00111     .uc_channel_function = MBED_CONF_MBED_MESH_API_WISUN_UC_CHANNEL_FUNCTION,
00112     .bc_channel_function = MBED_CONF_MBED_MESH_API_WISUN_BC_CHANNEL_FUNCTION,
00113     .uc_dwell_interval = MBED_CONF_MBED_MESH_API_WISUN_UC_DWELL_INTERVAL,
00114     .bc_interval = MBED_CONF_MBED_MESH_API_WISUN_BC_INTERVAL,
00115     .bc_dwell_interval = MBED_CONF_MBED_MESH_API_WISUN_BC_DWELL_INTERVAL,
00116     .uc_fixed_channel = MBED_CONF_MBED_MESH_API_WISUN_UC_FIXED_CHANNEL,
00117     .bc_fixed_channel = MBED_CONF_MBED_MESH_API_WISUN_BC_FIXED_CHANNEL
00118 };
00119 static mac_api_t *mac_api = NULL;
00120 
00121 extern fhss_timer_t fhss_functions;
00122 
00123 /* private function prototypes */
00124 static void wisun_tasklet_main(arm_event_s *event);
00125 static void wisun_tasklet_network_state_changed(mesh_connection_status_t status);
00126 static void wisun_tasklet_parse_network_event(arm_event_s *event);
00127 static void wisun_tasklet_configure_and_connect_to_network(void);
00128 static void wisun_tasklet_clear_stored_certificates(void) ;
00129 static int wisun_tasklet_store_certificate_data(const uint8_t *cert, uint16_t cert_len, const uint8_t *cert_key, uint16_t cert_key_len, bool remove_own, bool remove_trusted, bool trusted_cert);
00130 static int wisun_tasklet_add_stored_certificates(void) ;
00131 
00132 /*
00133  * \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver.
00134  * @param event, describes the sender, receiver and event type.
00135  *
00136  * NOTE: Interrupts requested by HW are possible during this function!
00137  */
00138 static void wisun_tasklet_main(arm_event_s *event)
00139 {
00140     arm_library_event_type_e event_type;
00141     event_type = (arm_library_event_type_e) event->event_type;
00142 
00143     switch (event_type) {
00144         case ARM_LIB_NWK_INTERFACE_EVENT:
00145             /* This event is delivered every and each time when there is new
00146              * information of network connectivity.
00147              */
00148             wisun_tasklet_parse_network_event(event);
00149             break;
00150 
00151         case ARM_LIB_TASKLET_INIT_EVENT:
00152             /* Event with type EV_INIT is an initializer event of NanoStack OS.
00153              * The event is delivered when the NanoStack OS is running fine.
00154              * This event should be delivered ONLY ONCE.
00155              */
00156             mesh_system_send_connect_event(wisun_tasklet_data_ptr->tasklet);
00157             break;
00158 
00159         case ARM_LIB_SYSTEM_TIMER_EVENT:
00160             eventOS_event_timer_cancel(event->event_id, wisun_tasklet_data_ptr->tasklet);
00161 
00162             if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) {
00163                 tr_debug("Restart bootstrap");
00164                 wisun_tasklet_configure_and_connect_to_network();
00165             }
00166             break;
00167 
00168         case APPLICATION_EVENT:
00169             if (event->event_id == APPL_EVENT_CONNECT) {
00170                 wisun_tasklet_configure_and_connect_to_network();
00171             }
00172             break;
00173 
00174         default:
00175             break;
00176     } // switch(event_type)
00177 }
00178 
00179 /**
00180  * \brief Network state event handler.
00181  * \param event show network start response or current network state.
00182  *
00183  * - ARM_NWK_BOOTSTRAP_READY: Save NVK persistent data to NVM and Net role
00184  * - ARM_NWK_NWK_SCAN_FAIL: Link Layer Active Scan Fail, Stack is Already at Idle state
00185  * - ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: No WS Router at current Channel Stack is Already at Idle state
00186  * - ARM_NWK_NWK_CONNECTION_DOWN: Connection to Access point is lost wait for Scan Result
00187  * - ARM_NWK_NWK_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels
00188  * - ARM_NWK_AUHTENTICATION_FAIL: Pana Authentication fail, Stack is Already at Idle state
00189  */
00190 static void wisun_tasklet_parse_network_event(arm_event_s *event)
00191 {
00192     arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e) event->event_data;
00193     tr_debug("app_parse_network_event() %d", status);
00194     switch (status) {
00195         case ARM_NWK_BOOTSTRAP_READY:
00196             /* Network is ready and node is connected to Access Point */
00197             if (wisun_tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) {
00198                 tr_info("Wi-SUN bootstrap ready");
00199                 wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY;
00200                 wisun_tasklet_network_state_changed(MESH_CONNECTED);
00201             }
00202             break;
00203         case ARM_NWK_NWK_SCAN_FAIL:
00204             /* Link Layer Active Scan Fail, Stack is Already at Idle state */
00205             tr_debug("Link Layer Scan Fail: No Beacons");
00206             wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
00207             wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED);
00208             break;
00209         case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
00210             /* No WS Router at current Channel Stack is Already at Idle state */
00211             tr_debug("WS Scan/ GP REG fail");
00212             wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
00213             wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED);
00214             break;
00215         case ARM_NWK_NWK_CONNECTION_DOWN:
00216             /* Connection to Access point is lost wait for Scan Result */
00217             tr_debug("WS/RPL scan new network");
00218             wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
00219             wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
00220             break;
00221         case ARM_NWK_NWK_PARENT_POLL_FAIL:
00222             wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
00223             wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED);
00224             break;
00225         case ARM_NWK_AUHTENTICATION_FAIL:
00226             tr_debug("Network authentication fail");
00227             wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
00228             wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED);
00229             break;
00230         default:
00231             tr_warn("Unknown event %d", status);
00232             break;
00233     }
00234 
00235     if ((wisun_tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY &&
00236             wisun_tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_STARTED) &&
00237             wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) {
00238         // Set 5s timer for new network scan
00239         eventOS_event_timer_request(TIMER_EVENT_START_BOOTSTRAP,
00240                                     ARM_LIB_SYSTEM_TIMER_EVENT,
00241                                     wisun_tasklet_data_ptr->tasklet,
00242                                     5000);
00243 
00244     }
00245 }
00246 
00247 /*
00248  * \brief Configure and establish network connection
00249  *
00250  */
00251 static void wisun_tasklet_configure_and_connect_to_network(void)
00252 {
00253     int status;
00254     fhss_timer_t *fhss_timer_ptr = &fhss_functions;
00255 
00256     wisun_tasklet_data_ptr->operating_mode = NET_6LOWPAN_ROUTER;
00257     wisun_tasklet_data_ptr->operating_mode_extension = NET_6LOWPAN_WS;
00258 
00259     arm_nwk_interface_configure_6lowpan_bootstrap_set(
00260         wisun_tasklet_data_ptr->network_interface_id,
00261         wisun_tasklet_data_ptr->operating_mode,
00262         wisun_tasklet_data_ptr->operating_mode_extension);
00263 
00264     if (wisun_tasklet_add_stored_certificates() != 0) {
00265         tr_error("Can't set Wi-SUN certificates");
00266         return;
00267     }
00268 
00269     status = ws_management_node_init(wisun_tasklet_data_ptr->network_interface_id,
00270                                      MBED_CONF_MBED_MESH_API_WISUN_REGULATORY_DOMAIN,
00271                                      wisun_settings_str.network_name,
00272                                      fhss_timer_ptr);
00273     if (status < 0) {
00274         tr_error("Failed to initialize WS");
00275         return;
00276     }
00277 
00278     if (wisun_settings_str.uc_channel_function != WS_NA) {
00279         status = ws_management_fhss_unicast_channel_function_configure(wisun_tasklet_data_ptr->network_interface_id,
00280                                                                        wisun_settings_str.uc_channel_function,
00281                                                                        wisun_settings_str.uc_fixed_channel,
00282                                                                        wisun_settings_str.uc_dwell_interval);
00283 
00284         if (status < 0) {
00285             tr_error("Failed to set unicast channel function configuration");
00286             return;
00287         }
00288     }
00289 
00290     if (wisun_settings_str.bc_channel_function != WS_NA ||
00291             wisun_settings_str.bc_dwell_interval != WS_DEFAULT ||
00292             wisun_settings_str.bc_interval != WS_DEFAULT) {
00293         status = ws_management_fhss_broadcast_channel_function_configure(wisun_tasklet_data_ptr->network_interface_id,
00294                                                                          wisun_settings_str.bc_channel_function,
00295                                                                          wisun_settings_str.bc_fixed_channel,
00296                                                                          wisun_settings_str.bc_dwell_interval,
00297                                                                          wisun_settings_str.bc_interval);
00298 
00299         if (status < 0) {
00300             tr_error("Failed to set broadcast channel function configuration");
00301             return;
00302         }
00303     }
00304 
00305     if (wisun_settings_str.uc_dwell_interval != WS_DEFAULT ||
00306             wisun_settings_str.bc_dwell_interval != WS_DEFAULT ||
00307             wisun_settings_str.bc_interval != WS_DEFAULT) {
00308         status = ws_management_fhss_timing_configure(wisun_tasklet_data_ptr->network_interface_id,
00309                                                      wisun_settings_str.uc_dwell_interval,
00310                                                      wisun_settings_str.bc_interval,
00311                                                      wisun_settings_str.bc_dwell_interval);
00312 
00313         if (status < 0) {
00314             tr_error("Failed to set fhss configuration");
00315             return;
00316         }
00317     }
00318 
00319     if (wisun_settings_str.regulatory_domain != WS_NA ||
00320             wisun_settings_str.rd_operating_class != WS_NA ||
00321             wisun_settings_str.rd_operating_mode != WS_NA) {
00322         status = ws_management_regulatory_domain_set(wisun_tasklet_data_ptr->network_interface_id,
00323                                                      wisun_settings_str.regulatory_domain,
00324                                                      wisun_settings_str.rd_operating_class,
00325                                                      wisun_settings_str.rd_operating_mode);
00326 
00327         if (status < 0) {
00328             tr_error("Failed to set regulatory domain!");
00329             return;
00330         }
00331     }
00332 
00333 #if defined(MBED_CONF_MBED_MESH_API_CERTIFICATE_HEADER)
00334     arm_certificate_entry_s trusted_cert = {
00335         .cert = MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE,
00336         .key = NULL,
00337         .cert_len = 0,
00338         .key_len = 0
00339     };
00340 #ifdef MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE_LEN
00341     trusted_cert.cert_len = MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE_LEN;
00342 #else
00343     trusted_cert.cert_len = strlen((const char *) MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE) + 1;
00344 #endif
00345     arm_network_trusted_certificate_add((const arm_certificate_entry_s *)&trusted_cert);
00346 
00347     arm_certificate_entry_s own_cert = {
00348         .cert = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE,
00349         .key =  MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY,
00350         .cert_len = 0,
00351         .key_len = 0
00352     };
00353 #ifdef MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_LEN
00354     own_cert.cert_len = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_LEN;
00355 #else
00356     own_cert.cert_len = strlen((const char *) MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE) + 1;
00357 #endif
00358 #ifdef MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY_LEN
00359     own_cert.key_len = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY_LEN;
00360 #else
00361     own_cert.key_len = strlen((const char *) MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY) + 1;
00362 #endif
00363     arm_network_own_certificate_add((const arm_certificate_entry_s *)&own_cert);
00364 #endif
00365 
00366     status = arm_nwk_interface_up(wisun_tasklet_data_ptr->network_interface_id);
00367     if (status >= 0) {
00368         wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
00369         tr_info("Start Wi-SUN Bootstrap");
00370         wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
00371     } else {
00372         wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED;
00373         tr_err("Bootstrap start failed, %d", status);
00374         wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED);
00375     }
00376 }
00377 
00378 /*
00379  * Inform application about network state change
00380  */
00381 static void wisun_tasklet_network_state_changed(mesh_connection_status_t status)
00382 {
00383     if (wisun_tasklet_data_ptr->mesh_api_cb) {
00384         (wisun_tasklet_data_ptr->mesh_api_cb)(status);
00385     }
00386 }
00387 
00388 static int wisun_tasklet_store_certificate_data(const uint8_t *cert, uint16_t cert_len, const uint8_t *cert_key, uint16_t cert_key_len, bool remove_own, bool remove_trusted, bool trusted_cert)
00389 {
00390     if (wisun_certificates_ptr == NULL) {
00391         wisun_certificates_ptr = (wisun_certificates_t *)ns_dyn_mem_alloc(sizeof(wisun_certificates_t));
00392         if (!wisun_certificates_ptr) {
00393             return -1;
00394         }
00395         ns_list_init(&wisun_certificates_ptr->own_certificates_list);
00396         ns_list_init(&wisun_certificates_ptr->trusted_certificates_list);
00397         wisun_certificates_ptr->remove_own_certificates = false;
00398         wisun_certificates_ptr->remove_trusted_certificates = false;
00399     }
00400 
00401     if (remove_own) {
00402         wisun_certificates_ptr->remove_own_certificates = true;
00403         return 0;
00404     }
00405 
00406     if (remove_trusted) {
00407         wisun_certificates_ptr->remove_trusted_certificates = true;
00408         return 0;
00409     }
00410 
00411     wisun_certificate_entry_t *ws_cert_entry_store = (wisun_certificate_entry_t *)ns_dyn_mem_alloc(sizeof(wisun_certificate_entry_t));
00412     if (!ws_cert_entry_store) {
00413         wisun_tasklet_clear_stored_certificates();
00414         return -1;
00415     }
00416 
00417     ws_cert_entry_store->arm_cert_entry.cert = cert;
00418     ws_cert_entry_store->arm_cert_entry.cert_len = cert_len;
00419 
00420     if (cert_key) {
00421         ws_cert_entry_store->arm_cert_entry.key = cert_key;
00422         ws_cert_entry_store->arm_cert_entry.key_len = cert_key_len;
00423     } else {
00424         ws_cert_entry_store->arm_cert_entry.key = NULL;
00425         ws_cert_entry_store->arm_cert_entry.key_len = 0;
00426     }
00427 
00428     if (trusted_cert) {
00429         ns_list_add_to_end(&wisun_certificates_ptr->trusted_certificates_list, ws_cert_entry_store);
00430     } else {
00431         ns_list_add_to_end(&wisun_certificates_ptr->own_certificates_list, ws_cert_entry_store);
00432     }
00433 
00434     return 0;
00435 }
00436 
00437 static void wisun_tasklet_clear_stored_certificates(void)
00438 {
00439     if (!wisun_certificates_ptr) {
00440         return;
00441     }
00442 
00443     ns_list_foreach_safe(wisun_certificate_entry_t, trusted_cert_entry, &wisun_certificates_ptr->trusted_certificates_list) {
00444         ns_list_remove(&wisun_certificates_ptr->trusted_certificates_list, trusted_cert_entry);
00445         ns_dyn_mem_free(trusted_cert_entry);
00446     }
00447 
00448     ns_list_foreach_safe(wisun_certificate_entry_t, own_cert_entry, &wisun_certificates_ptr->own_certificates_list) {
00449         ns_list_remove(&wisun_certificates_ptr->own_certificates_list, own_cert_entry);
00450         ns_dyn_mem_free(own_cert_entry);
00451     }
00452 
00453     ns_dyn_mem_free(wisun_certificates_ptr);
00454     wisun_certificates_ptr = NULL;
00455 }
00456 
00457 static int wisun_tasklet_add_stored_certificates(void)
00458 {
00459     int8_t status = 0;
00460 
00461     if (wisun_certificates_ptr == NULL) {
00462         // certificates not updated
00463         return 0;
00464     }
00465 
00466     if (wisun_certificates_ptr->remove_own_certificates) {
00467         status = arm_network_own_certificates_remove();
00468         if (status != 0) {
00469             goto CERTIFICATE_SET_END;
00470         }
00471     }
00472 
00473     if (wisun_certificates_ptr->remove_trusted_certificates) {
00474         status = arm_network_trusted_certificates_remove();
00475         if (status != 0) {
00476             goto CERTIFICATE_SET_END;
00477         }
00478     }
00479 
00480     ns_list_foreach(wisun_certificate_entry_t, cert_entry, &wisun_certificates_ptr->trusted_certificates_list) {
00481         status = arm_network_trusted_certificate_add(&cert_entry->arm_cert_entry);
00482         if (status != 0) {
00483             goto CERTIFICATE_SET_END;
00484         }
00485     }
00486 
00487     ns_list_foreach(wisun_certificate_entry_t, cert_entry, &wisun_certificates_ptr->own_certificates_list) {
00488         status = arm_network_own_certificate_add(&cert_entry->arm_cert_entry);
00489         if (status != 0) {
00490             goto CERTIFICATE_SET_END;
00491         }
00492     }
00493 
00494 CERTIFICATE_SET_END:
00495     wisun_tasklet_clear_stored_certificates();
00496 
00497     return status;
00498 }
00499 
00500 /* Public functions */
00501 int8_t wisun_tasklet_get_router_ip_address(char *address, int8_t len)
00502 {
00503     network_layer_address_s nd_address;
00504 
00505     if ((len >= 40) && (0 == arm_nwk_nd_address_read(wisun_tasklet_data_ptr->network_interface_id, &nd_address))) {
00506         ip6tos(nd_address.border_router, address);
00507         tr_debug("Router IP address: %s", address);
00508         return 0;
00509     } else {
00510         return -1;
00511     }
00512 }
00513 
00514 int8_t wisun_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id)
00515 {
00516     bool re_connecting = true;
00517     int8_t tasklet_id = wisun_tasklet_data_ptr->tasklet;
00518 
00519     if (wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) {
00520         return -3;  // already connected to network
00521     }
00522 
00523     if (wisun_tasklet_data_ptr->tasklet_state == TASKLET_STATE_CREATED) {
00524         re_connecting = false;
00525     }
00526 
00527     memset(wisun_tasklet_data_ptr, 0, sizeof(wisun_tasklet_data_str_t));
00528     wisun_tasklet_data_ptr->mesh_api_cb = callback;
00529     wisun_tasklet_data_ptr->network_interface_id = nwk_interface_id;
00530     wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED;
00531 
00532     if (re_connecting == false) {
00533         wisun_tasklet_data_ptr->tasklet = eventOS_event_handler_create(&wisun_tasklet_main,
00534                                                                        ARM_LIB_TASKLET_INIT_EVENT);
00535         if (wisun_tasklet_data_ptr->tasklet < 0) {
00536             // -1 handler already used by other tasklet
00537             // -2 memory allocation failure
00538             return wisun_tasklet_data_ptr->tasklet;
00539         }
00540     } else {
00541         wisun_tasklet_data_ptr->tasklet = tasklet_id;
00542         mesh_system_send_connect_event(wisun_tasklet_data_ptr->tasklet);
00543     }
00544 
00545     return wisun_tasklet_data_ptr->tasklet;
00546 }
00547 
00548 int8_t wisun_tasklet_disconnect(bool send_cb)
00549 {
00550     int8_t status = -1;
00551     if (wisun_tasklet_data_ptr != NULL) {
00552         if (wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) {
00553             status = arm_nwk_interface_down(wisun_tasklet_data_ptr->network_interface_id);
00554             wisun_tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID;
00555             if (send_cb == true) {
00556                 wisun_tasklet_network_state_changed(MESH_DISCONNECTED);
00557             }
00558         }
00559         wisun_tasklet_data_ptr->mesh_api_cb = NULL;
00560     }
00561     return status;
00562 }
00563 
00564 void wisun_tasklet_init(void)
00565 {
00566     if (wisun_tasklet_data_ptr == NULL) {
00567         wisun_tasklet_data_ptr = (wisun_tasklet_data_str_t *)ns_dyn_mem_alloc(sizeof(wisun_tasklet_data_str_t));
00568         // allocation not validated, in case of failure execution stops here
00569         memset(wisun_tasklet_data_ptr, 0, sizeof(wisun_tasklet_data_str_t));
00570         wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_CREATED;
00571         wisun_tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID;
00572     }
00573 }
00574 
00575 int8_t wisun_tasklet_network_init(int8_t device_id)
00576 {
00577     // TODO, read interface name from configuration
00578     mac_description_storage_size_t storage_sizes;
00579     storage_sizes.device_decription_table_size = 32;
00580     storage_sizes.key_description_table_size = 4;
00581     storage_sizes.key_lookup_size = 1;
00582     storage_sizes.key_usage_size = 3;
00583     if (!mac_api) {
00584         mac_api = ns_sw_mac_create(device_id, &storage_sizes);
00585     }
00586 
00587     if (!wisun_settings_str.network_name) {
00588         // No network name set by API, use network name from configuration
00589         int wisun_network_name_len = sizeof(MBED_CONF_MBED_MESH_API_WISUN_NETWORK_NAME);
00590         wisun_settings_str.network_name = (char *)ns_dyn_mem_alloc(wisun_network_name_len);
00591         if (!wisun_settings_str.network_name) {
00592             return -3;
00593         }
00594         strncpy(wisun_settings_str.network_name, MBED_CONF_MBED_MESH_API_WISUN_NETWORK_NAME, wisun_network_name_len);
00595     }
00596 
00597     return arm_nwk_interface_lowpan_init(mac_api, INTERFACE_NAME);
00598 }
00599 
00600 int wisun_tasklet_set_network_name(int8_t nwk_interface_id, char *network_name_ptr)
00601 {
00602     if (!network_name_ptr || strlen(network_name_ptr) > 32) {
00603         return -1;
00604     }
00605 
00606     // save the network name to have support for disconnect/connect
00607     ns_dyn_mem_free(wisun_settings_str.network_name);
00608     wisun_settings_str.network_name = (char *)ns_dyn_mem_alloc(strlen(network_name_ptr) + 1);
00609     if (!wisun_settings_str.network_name) {
00610         return -2;
00611     }
00612 
00613     strcpy(wisun_settings_str.network_name, network_name_ptr);
00614 
00615     if (wisun_tasklet_data_ptr && wisun_tasklet_data_ptr->tasklet_state == TASKLET_STATE_BOOTSTRAP_READY) {
00616         // interface is up, try to change name dynamically
00617         return ws_management_network_name_set(nwk_interface_id, wisun_settings_str.network_name);
00618     }
00619 
00620     return 0;
00621 }
00622 
00623 int wisun_tasklet_set_regulatory_domain(int8_t nwk_interface_id, uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode)
00624 {
00625     int status = 0;
00626 
00627     wisun_settings_str.regulatory_domain = regulatory_domain;
00628     wisun_settings_str.rd_operating_class = operating_class;
00629     wisun_settings_str.rd_operating_mode = operating_mode;
00630 
00631     if (wisun_tasklet_data_ptr && wisun_tasklet_data_ptr->tasklet_state == TASKLET_STATE_BOOTSTRAP_READY) {
00632         status = ws_management_regulatory_domain_set(nwk_interface_id, regulatory_domain, operating_class, operating_mode);
00633     }
00634 
00635     return status;
00636 }
00637 
00638 int wisun_tasklet_set_own_certificate(uint8_t *cert, uint16_t cert_len, uint8_t *cert_key, uint16_t cert_key_len)
00639 {
00640     if (wisun_tasklet_data_ptr) {
00641         // this API can be only used before first connect()
00642         tr_err("Already connected");
00643         return -2;
00644     }
00645 
00646     return wisun_tasklet_store_certificate_data(cert, cert_len, cert_key, cert_key_len, false, false, false);
00647 }
00648 
00649 int wisun_tasklet_remove_own_certificates(void)
00650 {
00651     if (wisun_tasklet_data_ptr) {
00652         // this API can be only used before first connect()
00653         tr_err("Already connected");
00654         return -2;
00655     }
00656 
00657     return wisun_tasklet_store_certificate_data(NULL, 0, NULL, 0, true, false, false);
00658 }
00659 
00660 int wisun_tasklet_remove_trusted_certificates(void)
00661 {
00662     if (wisun_tasklet_data_ptr) {
00663         // this API can be only used before first connect()
00664         tr_err("Already connected");
00665         return -2;
00666     }
00667 
00668     return wisun_tasklet_store_certificate_data(NULL, 0, NULL, 0, false, true, false);
00669 }
00670 
00671 int wisun_tasklet_set_trusted_certificate(uint8_t *cert, uint16_t cert_len)
00672 {
00673     if (wisun_tasklet_data_ptr) {
00674         // this API can be only used before first connect()
00675         tr_err("Already connected");
00676         return -2;
00677     }
00678     return wisun_tasklet_store_certificate_data(cert, cert_len, NULL, 0, false, false, true);
00679 }