Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ethernet_tasklet.c
00001 /* 00002 * Copyright (c) 2015 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 "net_interface.h" 00021 #include "ip6string.h" //ip6tos 00022 #include "nsdynmemLIB.h" 00023 #include "include/mesh_system.h" 00024 #include "ns_event_loop.h" 00025 #include "mesh_interface_types.h" 00026 #include "eventOS_event.h" 00027 #include "enet_tasklet.h" 00028 00029 // For tracing we need to define flag, have include and define group 00030 #include "ns_trace.h" 00031 #define TRACE_GROUP "IPV6" 00032 00033 #include "ethernet_mac_api.h" 00034 00035 #define INTERFACE_NAME "eth0" 00036 00037 // Tasklet timer events 00038 #define TIMER_EVENT_START_BOOTSTRAP 1 00039 00040 #define INVALID_INTERFACE_ID (-1) 00041 00042 #define STR_HELPER(x) #x 00043 #define STR(x) STR_HELPER(x) 00044 00045 /* 00046 * Mesh tasklet states. 00047 */ 00048 typedef enum { 00049 TASKLET_STATE_CREATED = 0, 00050 TASKLET_STATE_INITIALIZED, 00051 TASKLET_STATE_BOOTSTRAP_STARTED, 00052 TASKLET_STATE_BOOTSTRAP_FAILED, 00053 TASKLET_STATE_BOOTSTRAP_READY 00054 } tasklet_state_t; 00055 00056 /* 00057 * Mesh tasklet data structure. 00058 */ 00059 typedef struct { 00060 void (*mesh_api_cb)(mesh_connection_status_t nwk_status); 00061 tasklet_state_t tasklet_state; 00062 mesh_connection_status_t connection_status; 00063 timeout_t *poll_network_status_timeout; 00064 int8_t node_main_tasklet_id; 00065 int8_t network_interface_id; 00066 int8_t tasklet; 00067 uint8_t ip[16]; 00068 } tasklet_data_str_t; 00069 00070 /* Tasklet data */ 00071 static tasklet_data_str_t *tasklet_data_ptr = NULL; 00072 static eth_mac_api_t *eth_mac_api = NULL; 00073 typedef void (*mesh_interface_cb)(mesh_connection_status_t mesh_status); 00074 00075 00076 /* private function prototypes */ 00077 static void enet_tasklet_main(arm_event_s *event); 00078 static void enet_tasklet_network_state_changed(mesh_connection_status_t status); 00079 static void enet_tasklet_parse_network_event(arm_event_s *event); 00080 static void enet_tasklet_configure_and_connect_to_network(void); 00081 static void enet_tasklet_poll_network_status(void *param); 00082 static void enet_tasklet_generate_event(uint8_t link_status, mesh_connection_status_t mesh_status); 00083 /* 00084 * \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver. 00085 * @param event, describes the sender, receiver and event type. 00086 * 00087 * NOTE: Interrupts requested by HW are possible during this function! 00088 */ 00089 void enet_tasklet_main(arm_event_s *event) 00090 { 00091 arm_library_event_type_e event_type; 00092 event_type = (arm_library_event_type_e) event->event_type; 00093 00094 switch (event_type) { 00095 case ARM_LIB_NWK_INTERFACE_EVENT: 00096 /* This event is delivered every and each time when there is new 00097 * information of network connectivity. 00098 */ 00099 enet_tasklet_parse_network_event(event); 00100 break; 00101 00102 case ARM_LIB_TASKLET_INIT_EVENT: 00103 /* Event with type EV_INIT is an initializer event of NanoStack OS. 00104 * The event is delivered when the NanoStack OS is running fine. 00105 * This event should be delivered ONLY ONCE. 00106 */ 00107 tasklet_data_ptr->node_main_tasklet_id = event->receiver; 00108 mesh_system_send_connect_event(tasklet_data_ptr->tasklet); 00109 break; 00110 00111 case ARM_LIB_SYSTEM_TIMER_EVENT: 00112 eventOS_event_timer_cancel(event->event_id, 00113 tasklet_data_ptr->node_main_tasklet_id); 00114 00115 if (event->event_id == TIMER_EVENT_START_BOOTSTRAP) { 00116 tr_debug("Restart bootstrap"); 00117 enet_tasklet_configure_and_connect_to_network(); 00118 } 00119 break; 00120 00121 case APPLICATION_EVENT: 00122 if (event->event_id == APPL_EVENT_CONNECT) { 00123 enet_tasklet_configure_and_connect_to_network(); 00124 } else if (event->event_id == APPL_BACKHAUL_LINK_UP 00125 && tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_STARTED) { 00126 // Ethernet cable has been plugged in 00127 arm_nwk_interface_configure_ipv6_bootstrap_set( 00128 tasklet_data_ptr->network_interface_id, NET_IPV6_BOOTSTRAP_AUTONOMOUS, NULL); 00129 enet_tasklet_configure_and_connect_to_network(); 00130 00131 if (tasklet_data_ptr->poll_network_status_timeout != NULL) { 00132 // Restart poll timer 00133 eventOS_timeout_cancel(tasklet_data_ptr->poll_network_status_timeout); 00134 } 00135 tasklet_data_ptr->poll_network_status_timeout = 00136 eventOS_timeout_every_ms(enet_tasklet_poll_network_status, 2000, NULL); 00137 } else if (event->event_id == APPL_BACKHAUL_LINK_DOWN) { 00138 // Ethernet cable has been removed 00139 arm_nwk_interface_down(tasklet_data_ptr->network_interface_id); 00140 eventOS_timeout_cancel(tasklet_data_ptr->poll_network_status_timeout); 00141 tasklet_data_ptr->poll_network_status_timeout = NULL; 00142 memset(tasklet_data_ptr->ip, 0x0, 16); 00143 enet_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED); 00144 } else if (event->event_id == APPL_BACKHAUL_INTERFACE_PHY_DOWN) { 00145 // disconnect called 00146 if (tasklet_data_ptr != NULL) { 00147 if (tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) { 00148 if (tasklet_data_ptr->connection_status != MESH_BOOTSTRAP_STARTED) { 00149 arm_nwk_interface_down(tasklet_data_ptr->network_interface_id); 00150 } 00151 tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID; 00152 enet_tasklet_network_state_changed(MESH_DISCONNECTED); 00153 } 00154 tasklet_data_ptr->mesh_api_cb = NULL; 00155 eventOS_timeout_cancel(tasklet_data_ptr->poll_network_status_timeout); 00156 } 00157 } 00158 break; 00159 00160 default: 00161 break; 00162 } // switch(event_type) 00163 } 00164 00165 /** 00166 * \brief Network state event handler. 00167 * \param event show network start response or current network state. 00168 * 00169 * - ARM_NWK_BOOTSTRAP_READY: Save NVK persistent data to NVM and Net role 00170 * - ARM_NWK_NWK_SCAN_FAIL: Link Layer Active Scan Fail, Stack is Already at Idle state 00171 * - ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: No ND Router at current Channel Stack is Already at Idle state 00172 * - ARM_NWK_NWK_CONNECTION_DOWN: Connection to Access point is lost wait for Scan Result 00173 * - ARM_NWK_NWK_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels 00174 * - ARM_NWK_AUHTENTICATION_FAIL: Pana Authentication fail, Stack is Already at Idle state 00175 */ 00176 void enet_tasklet_parse_network_event(arm_event_s *event) 00177 { 00178 arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e) event->event_data; 00179 tr_debug("app_parse_network_event() %d", status); 00180 switch (status) { 00181 case ARM_NWK_BOOTSTRAP_READY: 00182 /* Network is ready and node is connected to Access Point */ 00183 if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) { 00184 tr_info("IPv6 bootstrap ready"); 00185 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_READY; 00186 enet_tasklet_poll_network_status(NULL); 00187 } 00188 break; 00189 case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL: 00190 /* No ND Router at current Channel Stack is Already at Idle state */ 00191 tr_info("Bootstrap fail"); 00192 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00193 enet_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); 00194 break; 00195 case ARM_NWK_NWK_CONNECTION_DOWN: 00196 /* Connection to Access point is lost wait for Scan Result */ 00197 tr_info("Connection lost"); 00198 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00199 enet_tasklet_network_state_changed(MESH_BOOTSTRAP_FAILED); 00200 break; 00201 default: 00202 tr_warn("Unknown event %d", status); 00203 break; 00204 } 00205 00206 if (tasklet_data_ptr->tasklet_state != TASKLET_STATE_BOOTSTRAP_READY) { 00207 // Set 5s timer for new network scan 00208 eventOS_event_timer_request(TIMER_EVENT_START_BOOTSTRAP, 00209 ARM_LIB_SYSTEM_TIMER_EVENT, 00210 tasklet_data_ptr->node_main_tasklet_id, 00211 5000); 00212 } 00213 } 00214 00215 static void enet_tasklet_poll_network_status(void *param) 00216 { 00217 /* Check if we do have an IP */ 00218 uint8_t temp_ipv6[16]; 00219 if (arm_net_address_get(tasklet_data_ptr->network_interface_id, ADDR_IPV6_GP, temp_ipv6) == 0) { 00220 /* Check if this is link local address or not */ 00221 if (memcmp(temp_ipv6, tasklet_data_ptr->ip, 16) == 0) { 00222 return; 00223 } else { 00224 memcpy(tasklet_data_ptr->ip, temp_ipv6, 16); 00225 uint8_t temp_ipv6_local[16]; 00226 if (arm_net_address_get(tasklet_data_ptr->network_interface_id, ADDR_IPV6_LL, temp_ipv6_local) == 0 00227 && (memcmp(temp_ipv6, temp_ipv6_local, 16) != 0)) { 00228 enet_tasklet_network_state_changed(MESH_CONNECTED_GLOBAL); 00229 } else { 00230 enet_tasklet_network_state_changed(MESH_CONNECTED_LOCAL);; 00231 } 00232 } 00233 } else { 00234 if (tasklet_data_ptr->connection_status != MESH_DISCONNECTED && 00235 tasklet_data_ptr->connection_status != MESH_BOOTSTRAP_STARTED) { 00236 enet_tasklet_network_state_changed(MESH_DISCONNECTED); 00237 } 00238 } 00239 } 00240 00241 /* 00242 * \brief Configure and establish network connection 00243 * 00244 */ 00245 void enet_tasklet_configure_and_connect_to_network(void) 00246 { 00247 int8_t status; 00248 00249 status = arm_nwk_interface_up(tasklet_data_ptr->network_interface_id); 00250 if (status >= 0) { 00251 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED; 00252 tr_info("Start Bootstrap"); 00253 enet_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED); 00254 } else { 00255 tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; 00256 tr_err("Bootstrap start failed, %d", status); 00257 enet_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED); 00258 } 00259 } 00260 00261 /* 00262 * Inform application about network state change 00263 */ 00264 void enet_tasklet_network_state_changed(mesh_connection_status_t status) 00265 { 00266 tasklet_data_ptr->connection_status = status; 00267 if (tasklet_data_ptr->mesh_api_cb) { 00268 (tasklet_data_ptr->mesh_api_cb)(status); 00269 } 00270 } 00271 00272 /* Public functions */ 00273 int8_t enet_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id) 00274 { 00275 int8_t re_connecting = true; 00276 int8_t tasklet_id = tasklet_data_ptr->tasklet; 00277 00278 if (tasklet_data_ptr->tasklet_state == TASKLET_STATE_CREATED) { 00279 re_connecting = false; 00280 } 00281 00282 memset(tasklet_data_ptr, 0, sizeof(tasklet_data_str_t)); 00283 tasklet_data_ptr->mesh_api_cb = callback; 00284 tasklet_data_ptr->network_interface_id = nwk_interface_id; 00285 tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED; 00286 tasklet_data_ptr->poll_network_status_timeout = 00287 eventOS_timeout_every_ms(enet_tasklet_poll_network_status, 2000, NULL); 00288 00289 if (re_connecting == false) { 00290 tasklet_data_ptr->tasklet = eventOS_event_handler_create(&enet_tasklet_main, 00291 ARM_LIB_TASKLET_INIT_EVENT); 00292 if (tasklet_data_ptr->tasklet < 0) { 00293 // -1 handler already used by other tasklet 00294 // -2 memory allocation failure 00295 return tasklet_data_ptr->tasklet; 00296 } 00297 } else { 00298 tasklet_data_ptr->tasklet = tasklet_id; 00299 mesh_system_send_connect_event(tasklet_data_ptr->tasklet); 00300 } 00301 00302 return 0; 00303 } 00304 00305 int8_t enet_tasklet_disconnect(bool send_cb) 00306 { 00307 enet_tasklet_generate_event(APPL_BACKHAUL_INTERFACE_PHY_DOWN, MESH_DISCONNECTED); 00308 return 0; 00309 } 00310 00311 void enet_tasklet_init(void) 00312 { 00313 if (tasklet_data_ptr == NULL) { 00314 tasklet_data_ptr = ns_dyn_mem_alloc(sizeof(tasklet_data_str_t)); 00315 tasklet_data_ptr->tasklet_state = TASKLET_STATE_CREATED; 00316 tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID; 00317 } 00318 } 00319 00320 int8_t enet_tasklet_network_init(int8_t device_id) 00321 { 00322 if (tasklet_data_ptr->network_interface_id != -1) { 00323 tr_debug("Interface already at active state\n"); 00324 return tasklet_data_ptr->network_interface_id; 00325 } 00326 if (!eth_mac_api) { 00327 eth_mac_api = ethernet_mac_create(device_id); 00328 } 00329 00330 tasklet_data_ptr->network_interface_id = arm_nwk_interface_ethernet_init(eth_mac_api, "eth0"); 00331 00332 tr_debug("interface ID: %d", tasklet_data_ptr->network_interface_id); 00333 arm_nwk_interface_configure_ipv6_bootstrap_set( 00334 tasklet_data_ptr->network_interface_id, NET_IPV6_BOOTSTRAP_AUTONOMOUS, NULL); 00335 return tasklet_data_ptr->network_interface_id; 00336 } 00337 00338 /* For now, to enable to compile without Nanostack interface changes, enables Nanostack PPP 00339 interface only if default stack is Nanostack and interface cellular. After Nanostack 00340 with updated interface call arm_nwk_interface_ppp_init() is integrated to mbed-os, this 00341 flagging can be removed. 00342 */ 00343 #define NANOSTACK 0x11991199 00344 #define CELLULAR 0x22992299 00345 #if MBED_CONF_NSAPI_DEFAULT_STACK == NANOSTACK && MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == CELLULAR 00346 #define ENABLE_NANOSTACK_PPP 00347 #endif 00348 #undef NANOSTACK 00349 #undef CELLULAR 00350 00351 int8_t enet_tasklet_ppp_network_init(int8_t device_id) 00352 { 00353 #ifdef ENABLE_NANOSTACK_PPP 00354 if (tasklet_data_ptr->network_interface_id != -1) { 00355 tr_debug("Interface already at active state\n"); 00356 return tasklet_data_ptr->network_interface_id; 00357 } 00358 if (!eth_mac_api) { 00359 eth_mac_api = ethernet_mac_create(device_id); 00360 } 00361 00362 tasklet_data_ptr->network_interface_id = arm_nwk_interface_ppp_init(eth_mac_api, "ppp0"); 00363 00364 tr_debug("interface ID: %d", tasklet_data_ptr->network_interface_id); 00365 arm_nwk_interface_configure_ipv6_bootstrap_set( 00366 tasklet_data_ptr->network_interface_id, NET_IPV6_BOOTSTRAP_AUTONOMOUS, NULL); 00367 return tasklet_data_ptr->network_interface_id; 00368 #else 00369 return -1; 00370 #endif 00371 } 00372 00373 void enet_tasklet_link_state_changed(bool up) 00374 { 00375 if (up) { 00376 enet_tasklet_generate_event(APPL_BACKHAUL_LINK_UP, MESH_BOOTSTRAP_STARTED); 00377 } else { 00378 enet_tasklet_generate_event(APPL_BACKHAUL_LINK_DOWN, MESH_BOOTSTRAP_STARTED); 00379 } 00380 } 00381 00382 static void enet_tasklet_generate_event(uint8_t link_status, mesh_connection_status_t mesh_status) 00383 { 00384 arm_event_s event = { 00385 .receiver = tasklet_data_ptr->tasklet, 00386 .sender = tasklet_data_ptr->tasklet, 00387 .event_type = APPLICATION_EVENT, 00388 .priority = ARM_LIB_LOW_PRIORITY_EVENT, 00389 .event_id = link_status, 00390 .event_data = mesh_status 00391 }; 00392 eventOS_event_send(&event); 00393 }
Generated on Tue Jul 12 2022 13:54:19 by
