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
NanostackPPPInterface.cpp
00001 /* 00002 * Copyright (c) 2019 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "NanostackPPPInterface.h" 00019 #include "NanostackPPPPhy.h" 00020 #include "PPP.h" 00021 #include "nsdynmemLIB.h" 00022 #include "arm_hal_phy.h" 00023 #include "mbed_interface.h" 00024 #include "mesh_system.h" 00025 #include "callback_handler.h" 00026 #include "enet_tasklet.h" 00027 #include "ip6string.h" 00028 00029 class PPPPhy : public NanostackPPPPhy { 00030 public: 00031 PPPPhy(NanostackMemoryManager &mem, PPP &m); 00032 virtual int8_t phy_register(); 00033 00034 virtual void phy_power_on(); 00035 virtual void phy_power_off(); 00036 00037 virtual void get_iid64(uint8_t *iid64); 00038 virtual uint16_t get_mtu(); 00039 00040 virtual void set_link_state_change_cb(link_state_change_cb_t cb); 00041 00042 int8_t tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle, data_protocol_e data_flow); 00043 00044 void ppp_phy_rx(net_stack_mem_buf_t *mem); 00045 void link_state_cb(bool up); 00046 00047 private: 00048 NanostackMemoryManager &memory_manager; 00049 PPP &ppp; 00050 uint8_t iid64[8]; 00051 link_state_change_cb_t link_state_change_cb; 00052 bool active; 00053 bool powered_up; 00054 int8_t device_id; 00055 phy_device_driver_s phy; 00056 }; 00057 00058 nsapi_error_t Nanostack::PPPInterface::initialize() 00059 { 00060 nanostack_lock(); 00061 00062 if (register_phy() < 0) { 00063 nanostack_unlock(); 00064 return NSAPI_ERROR_DEVICE_ERROR ; 00065 } 00066 00067 nanostack_unlock(); 00068 00069 return NSAPI_ERROR_OK ; 00070 } 00071 00072 nsapi_error_t Nanostack::PPPInterface::bringup(bool dhcp, const char *ip, 00073 const char *netmask, const char *gw, 00074 nsapi_ip_stack_t stack, bool blocking) 00075 { 00076 if (stack == IPV4_STACK) { 00077 return NSAPI_ERROR_UNSUPPORTED ; 00078 } 00079 00080 _blocking = blocking; 00081 00082 if (link_state_up) { 00083 connect_enet_tasklet(); 00084 } 00085 00086 if (blocking) { 00087 uint8_t retries = 10; 00088 while (_connect_status != NSAPI_STATUS_GLOBAL_UP ) { 00089 int32_t count = connect_semaphore.try_acquire_for(3000); 00090 if (count <= 0 && retries-- == 0) { 00091 return NSAPI_ERROR_DHCP_FAILURE ; // sort of... 00092 } 00093 // Not up until global up 00094 if (_connect_status == NSAPI_STATUS_LOCAL_UP ) { 00095 _connect_status = NSAPI_STATUS_CONNECTING ; 00096 } 00097 } 00098 } 00099 00100 return NSAPI_ERROR_OK ; 00101 } 00102 00103 nsapi_error_t Nanostack::PPPInterface::connect_enet_tasklet() 00104 { 00105 if (enet_tasklet_connected) { 00106 return NSAPI_ERROR_OK ; 00107 } 00108 00109 enet_tasklet_connected = true; 00110 00111 nanostack_lock(); 00112 00113 if (interface_id < 0) { 00114 enet_tasklet_init(); 00115 __mesh_handler_set_callback(this); 00116 interface_id = enet_tasklet_ppp_network_init(_device_id); 00117 } 00118 int8_t status = -1; 00119 if (interface_id >= 0) { 00120 status = enet_tasklet_connect(&__mesh_handler_c_callback, interface_id); 00121 } 00122 00123 nanostack_unlock(); 00124 00125 if (status == -1) { 00126 return NSAPI_ERROR_DEVICE_ERROR ; 00127 } else if (status == -2) { 00128 return NSAPI_ERROR_NO_MEMORY ; 00129 } else if (status == -3) { 00130 return NSAPI_ERROR_ALREADY ; 00131 } else if (status != 0) { 00132 return NSAPI_ERROR_DEVICE_ERROR ; 00133 } 00134 00135 return NSAPI_ERROR_OK ; 00136 } 00137 00138 nsapi_error_t Nanostack::PPPInterface::bringdown() 00139 { 00140 nanostack_lock(); 00141 int8_t status = enet_tasklet_disconnect(true); 00142 enet_tasklet_connected = false; 00143 nanostack_unlock(); 00144 00145 if (status == -1) { 00146 return NSAPI_ERROR_DEVICE_ERROR ; 00147 } else if (status == -2) { 00148 return NSAPI_ERROR_NO_MEMORY ; 00149 } else if (status == -3) { 00150 return NSAPI_ERROR_ALREADY ; 00151 } else if (status != 0) { 00152 return NSAPI_ERROR_DEVICE_ERROR ; 00153 } 00154 00155 if (_blocking) { 00156 int32_t count = disconnect_semaphore.try_acquire_for(30000); 00157 00158 if (count <= 0) { 00159 return NSAPI_ERROR_TIMEOUT ; 00160 } 00161 } 00162 return NSAPI_ERROR_OK ; 00163 } 00164 00165 void Nanostack::PPPInterface::link_state_changed(bool up) 00166 { 00167 link_state_up = up; 00168 00169 // If application callback is set 00170 if (link_state_cb) { 00171 link_state_cb(up, _device_id); 00172 } else { 00173 if (up) { 00174 connect_enet_tasklet(); 00175 } 00176 } 00177 } 00178 00179 void Nanostack::PPPInterface::set_link_state_changed_callback(link_state_cb_t new_link_state_cb) 00180 { 00181 link_state_cb = new_link_state_cb; 00182 } 00183 00184 // GAH! no handles on the callback. Force a single interface 00185 static PPPPhy *single_phy; 00186 00187 extern "C" 00188 { 00189 static int8_t ppp_phy_interface_state_control(phy_interface_state_e, uint8_t) 00190 { 00191 return -1; 00192 } 00193 00194 static int8_t ppp_phy_tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle, data_protocol_e data_flow) 00195 { 00196 return single_phy->tx(data_ptr, data_len, tx_handle, data_flow); 00197 } 00198 00199 PPPPhy::PPPPhy(NanostackMemoryManager &mem, PPP &m) : memory_manager(mem), ppp(m), link_state_change_cb(NULL), active(false), powered_up(false), device_id(-1) 00200 { 00201 } 00202 00203 void PPPPhy::ppp_phy_rx(net_stack_mem_buf_t *mem) 00204 { 00205 if (!active) { 00206 memory_manager.free(mem); 00207 return; 00208 } 00209 00210 const uint8_t *ptr = NULL; 00211 uint8_t *tmpbuf = NULL; 00212 uint32_t total_len; 00213 00214 if (memory_manager.get_next(mem) == NULL) { 00215 // Easy contiguous case 00216 ptr = static_cast<const uint8_t *>(memory_manager.get_ptr(mem)); 00217 total_len = memory_manager.get_len(mem); 00218 } else { 00219 // Nanostack can't accept chunked data - make temporary contiguous copy 00220 total_len = memory_manager.get_total_len(mem); 00221 ptr = tmpbuf = static_cast<uint8_t *>(ns_dyn_mem_temporary_alloc(total_len)); 00222 if (tmpbuf) { 00223 memory_manager.copy_from_buf(tmpbuf, total_len, mem); 00224 } 00225 } 00226 00227 if (ptr && phy.phy_rx_cb) { 00228 phy.phy_rx_cb(ptr, total_len, 0xff, 0, device_id); 00229 } 00230 ns_dyn_mem_free(tmpbuf); 00231 memory_manager.free(mem); 00232 } 00233 00234 } // extern "C" 00235 00236 int8_t PPPPhy::tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle, data_protocol_e data_flow) 00237 { 00238 if (!active) { 00239 return -1; 00240 } 00241 00242 net_stack_mem_buf_t *mem = memory_manager.alloc_pool(data_len, 0); 00243 if (!mem) { 00244 return -1; 00245 } 00246 memory_manager.copy_to_buf(mem, data_ptr, data_len); 00247 00248 // They take ownership - their responsibility to free 00249 ppp.link_out(mem, IPV6_STACK); 00250 00251 return 0; 00252 } 00253 00254 int8_t PPPPhy::phy_register() 00255 { 00256 active = true; 00257 00258 if (device_id < 0) { 00259 phy.PHY_MAC = iid64; 00260 phy.address_write = NULL; 00261 phy.driver_description = const_cast<char *>("PPP"); 00262 phy.link_type = PHY_LINK_PPP; 00263 phy.phy_MTU = 0; 00264 phy.phy_header_length = 0; 00265 phy.phy_tail_length = 0; 00266 phy.state_control = ppp_phy_interface_state_control; 00267 phy.tx = ppp_phy_tx; 00268 phy.phy_rx_cb = NULL; 00269 phy.phy_tx_done_cb = NULL; 00270 00271 ppp.set_memory_manager(memory_manager); 00272 ppp.set_link_input_cb(mbed::callback(this, &PPPPhy::ppp_phy_rx)); 00273 if (link_state_change_cb) { 00274 ppp.set_link_state_cb(mbed::callback(this, &PPPPhy::link_state_cb)); 00275 } 00276 00277 device_id = arm_net_phy_register(&phy); 00278 00279 if (device_id < 0) { 00280 return -1; 00281 } 00282 } 00283 00284 return device_id; 00285 } 00286 00287 void PPPPhy::phy_power_on() 00288 { 00289 if (!powered_up) { 00290 if (!ppp.power_up()) { 00291 return; 00292 } 00293 phy.phy_MTU = get_mtu(); 00294 powered_up = true; 00295 active = true; 00296 } 00297 } 00298 00299 void PPPPhy::phy_power_off() 00300 { 00301 if (powered_up) { 00302 ppp.power_down(); 00303 powered_up = false; 00304 } 00305 active = false; 00306 } 00307 00308 void PPPPhy::set_link_state_change_cb(link_state_change_cb_t cb) 00309 { 00310 link_state_change_cb = cb; 00311 } 00312 00313 void PPPPhy::link_state_cb(bool up) 00314 { 00315 // Read negotiated parameters from PPP 00316 if (up) { 00317 get_iid64(iid64); 00318 } 00319 00320 // Call upper level callback if set 00321 if (link_state_change_cb) { 00322 link_state_change_cb(up); 00323 } 00324 } 00325 00326 void PPPPhy::get_iid64(uint8_t *iid64) 00327 { 00328 if (!iid64) { 00329 return; 00330 } 00331 00332 // Read link local IPv6 address 00333 const nsapi_addr_t *ipv6_ll_addr = ppp.get_ip_address(NSAPI_IPv6 ); 00334 if (ipv6_ll_addr) { 00335 memcpy(iid64, &ipv6_ll_addr->bytes[8], 8); 00336 } 00337 } 00338 00339 uint16_t PPPPhy::get_mtu() 00340 { 00341 return ppp.get_mtu_size(); 00342 } 00343 00344 nsapi_error_t Nanostack::add_ppp_interface(PPP &ppp, bool default_if, Nanostack::PPPInterface **interface_out) 00345 { 00346 if (!single_phy) { 00347 single_phy = new (std::nothrow) PPPPhy(this->memory_manager, ppp); 00348 if (!single_phy) { 00349 return NSAPI_ERROR_NO_MEMORY ; 00350 } 00351 } 00352 00353 static Nanostack::PPPInterface *interface = NULL; 00354 00355 if (interface == NULL) { 00356 interface = new (std::nothrow) Nanostack::PPPInterface(*single_phy); 00357 if (!interface) { 00358 return NSAPI_ERROR_NO_MEMORY ; 00359 } 00360 00361 single_phy->set_link_state_change_cb(mbed::callback(interface, &Nanostack::PPPInterface::link_state_changed)); 00362 } 00363 00364 interface->initialize(); 00365 00366 single_phy->phy_power_on(); 00367 00368 *interface_out = interface; 00369 00370 return NSAPI_ERROR_OK ; 00371 } 00372 00373 nsapi_error_t Nanostack::add_ppp_interface(PPP &ppp, bool default_if, OnboardNetworkStack::Interface **interface_out) 00374 { 00375 Nanostack::PPPInterface *interface; 00376 nsapi_error_t err = add_ppp_interface(ppp, default_if, &interface); 00377 *interface_out = interface; 00378 return err; 00379 } 00380 00381 nsapi_error_t Nanostack::remove_ppp_interface(OnboardNetworkStack::Interface **interface_out) 00382 { 00383 single_phy->phy_power_off(); 00384 00385 return NSAPI_ERROR_OK ; 00386 }
Generated on Tue Jul 12 2022 13:54:36 by
