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.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
lwip_stack.c
00001 /* LWIP implementation of NetworkInterfaceAPI 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may 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, 00012 * WITHOUT 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 "nsapi.h" 00018 #include "mbed_interface.h" 00019 #include <stdio.h> 00020 #include <stdbool.h> 00021 #include <string.h> 00022 00023 #include "eth_arch.h" 00024 #include "lwip/opt.h" 00025 #include "lwip/api.h" 00026 #include "lwip/inet.h" 00027 #include "lwip/netif.h" 00028 #include "lwip/dhcp.h" 00029 #include "lwip/tcpip.h" 00030 #include "lwip/tcp.h" 00031 #include "lwip/ip.h" 00032 00033 00034 /* Static arena of sockets */ 00035 static struct lwip_socket { 00036 bool in_use; 00037 00038 struct netconn *conn; 00039 struct netbuf *buf; 00040 u16_t offset; 00041 00042 void (*cb)(void *); 00043 void *data; 00044 } lwip_arena[MEMP_NUM_NETCONN]; 00045 00046 static void lwip_arena_init(void) 00047 { 00048 memset(lwip_arena, 0, sizeof lwip_arena); 00049 } 00050 00051 static struct lwip_socket *lwip_arena_alloc(void) 00052 { 00053 sys_prot_t prot = sys_arch_protect(); 00054 00055 for (int i = 0; i < MEMP_NUM_NETCONN; i++) { 00056 if (!lwip_arena[i].in_use) { 00057 struct lwip_socket *s = &lwip_arena[i]; 00058 memset(s, 0, sizeof *s); 00059 s->in_use = true; 00060 sys_arch_unprotect(prot); 00061 return s; 00062 } 00063 } 00064 00065 sys_arch_unprotect(prot); 00066 return 0; 00067 } 00068 00069 static void lwip_arena_dealloc(struct lwip_socket *s) 00070 { 00071 s->in_use = false; 00072 } 00073 00074 static void lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) 00075 { 00076 sys_prot_t prot = sys_arch_protect(); 00077 00078 for (int i = 0; i < MEMP_NUM_NETCONN; i++) { 00079 if (lwip_arena[i].in_use 00080 && lwip_arena[i].conn == nc 00081 && lwip_arena[i].cb) { 00082 lwip_arena[i].cb(lwip_arena[i].data); 00083 } 00084 } 00085 00086 sys_arch_unprotect(prot); 00087 } 00088 00089 00090 /* TCP/IP and Network Interface Initialisation */ 00091 static struct netif lwip_netif; 00092 00093 static char lwip_ip_addr[NSAPI_IP_SIZE] = "\0"; 00094 static char lwip_mac_addr[NSAPI_MAC_SIZE] = "\0"; 00095 00096 static sys_sem_t lwip_tcpip_inited; 00097 static void lwip_tcpip_init_irq(void *eh) 00098 { 00099 sys_sem_signal(&lwip_tcpip_inited); 00100 } 00101 00102 static sys_sem_t lwip_netif_linked; 00103 static void lwip_netif_link_irq(struct netif *lwip_netif) 00104 { 00105 if (netif_is_link_up(lwip_netif)) { 00106 sys_sem_signal(&lwip_netif_linked); 00107 } 00108 } 00109 00110 static sys_sem_t lwip_netif_up; 00111 static void lwip_netif_status_irq(struct netif *lwip_netif) 00112 { 00113 if (netif_is_up(lwip_netif)) { 00114 strcpy(lwip_ip_addr, inet_ntoa(lwip_netif->ip_addr)); 00115 sys_sem_signal(&lwip_netif_up); 00116 } 00117 } 00118 00119 static void lwip_set_mac_address(void) 00120 { 00121 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) 00122 snprintf(lwip_mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", 00123 MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2, 00124 MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5); 00125 #else 00126 char mac[6]; 00127 mbed_mac_address(mac); 00128 snprintf(lwip_mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", 00129 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 00130 #endif 00131 } 00132 00133 00134 /* LWIP interface implementation */ 00135 const char *lwip_get_mac_address(void) 00136 { 00137 return lwip_mac_addr[0] ? lwip_mac_addr : 0; 00138 } 00139 00140 const char *lwip_get_ip_address(void) 00141 { 00142 return lwip_ip_addr[0] ? lwip_ip_addr : 0; 00143 } 00144 00145 int lwip_bringup(void) 00146 { 00147 // Check if we've already connected 00148 if (!lwip_get_mac_address()) { 00149 // Set up network 00150 lwip_set_mac_address(); 00151 00152 sys_sem_new(&lwip_tcpip_inited, 0); 00153 sys_sem_new(&lwip_netif_linked, 0); 00154 sys_sem_new(&lwip_netif_up, 0); 00155 00156 tcpip_init(lwip_tcpip_init_irq, NULL); 00157 sys_arch_sem_wait(&lwip_tcpip_inited, 0); 00158 00159 memset(&lwip_netif, 0, sizeof lwip_netif); 00160 netif_add(&lwip_netif, 0, 0, 0, NULL, eth_arch_enetif_init, tcpip_input); 00161 netif_set_default(&lwip_netif); 00162 00163 netif_set_link_callback (&lwip_netif, lwip_netif_link_irq); 00164 netif_set_status_callback(&lwip_netif, lwip_netif_status_irq); 00165 00166 eth_arch_enable_interrupts(); 00167 } 00168 00169 // Zero out socket set 00170 lwip_arena_init(); 00171 00172 // Connect to the network 00173 dhcp_start(&lwip_netif); 00174 00175 // Wait for an IP Address 00176 u32_t ret = sys_arch_sem_wait(&lwip_netif_up, 15000); 00177 if (ret == SYS_ARCH_TIMEOUT) { 00178 return NSAPI_ERROR_DHCP_FAILURE; 00179 } 00180 00181 return 0; 00182 } 00183 00184 void lwip_bringdown(void) 00185 { 00186 // Disconnect from the network 00187 dhcp_release(&lwip_netif); 00188 dhcp_stop(&lwip_netif); 00189 lwip_ip_addr[0] = '\0'; 00190 } 00191 00192 00193 /* LWIP error remapping */ 00194 static int lwip_err_remap(err_t err) { 00195 switch (err) { 00196 case ERR_OK: 00197 return 0; 00198 case ERR_MEM: 00199 return NSAPI_ERROR_NO_MEMORY; 00200 case ERR_CONN: 00201 case ERR_CLSD: 00202 return NSAPI_ERROR_NO_CONNECTION; 00203 case ERR_TIMEOUT: 00204 case ERR_RTE: 00205 case ERR_INPROGRESS: 00206 case ERR_WOULDBLOCK: 00207 return NSAPI_ERROR_WOULD_BLOCK; 00208 case ERR_VAL: 00209 case ERR_USE: 00210 case ERR_ISCONN: 00211 case ERR_ARG: 00212 return NSAPI_ERROR_PARAMETER; 00213 default: 00214 return NSAPI_ERROR_DEVICE_ERROR; 00215 } 00216 } 00217 00218 00219 /* LWIP network stack implementation */ 00220 static nsapi_addr_t lwip_getaddr(nsapi_stack_t *stack) 00221 { 00222 if (!lwip_get_ip_address()) { 00223 return (nsapi_addr_t){0}; 00224 } 00225 00226 nsapi_addr_t addr; 00227 addr.version = NSAPI_IPv4; 00228 inet_aton(lwip_get_ip_address(), (ip_addr_t *)addr.bytes); 00229 return addr; 00230 } 00231 00232 static int lwip_gethostbyname(nsapi_stack_t *stack, nsapi_addr_t *addr, const char *host) 00233 { 00234 err_t err = netconn_gethostbyname(host, (ip_addr_t *)addr->bytes); 00235 if (err != ERR_OK) { 00236 return NSAPI_ERROR_DNS_FAILURE; 00237 } 00238 00239 addr->version = NSAPI_IPv4; 00240 return 0; 00241 } 00242 00243 static int lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) 00244 { 00245 struct lwip_socket *s = lwip_arena_alloc(); 00246 if (!s) { 00247 return NSAPI_ERROR_NO_SOCKET; 00248 } 00249 00250 s->conn = netconn_new_with_callback( 00251 proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP, 00252 lwip_socket_callback); 00253 00254 if (!s->conn) { 00255 lwip_arena_dealloc(s); 00256 return NSAPI_ERROR_NO_SOCKET; 00257 } 00258 00259 netconn_set_recvtimeout(s->conn, 1); 00260 *(struct lwip_socket **)handle = s; 00261 return 0; 00262 } 00263 00264 static int lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle) 00265 { 00266 struct lwip_socket *s = (struct lwip_socket *)handle; 00267 00268 err_t err = netconn_delete(s->conn); 00269 lwip_arena_dealloc(s); 00270 return lwip_err_remap(err); 00271 } 00272 00273 00274 static int lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 00275 { 00276 struct lwip_socket *s = (struct lwip_socket *)handle; 00277 if (addr.version != NSAPI_IPv4) { 00278 return NSAPI_ERROR_PARAMETER; 00279 } 00280 00281 if ((s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || 00282 (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { 00283 return NSAPI_ERROR_PARAMETER; 00284 } 00285 00286 err_t err = netconn_bind(s->conn, (ip_addr_t *)addr.bytes, port); 00287 return lwip_err_remap(err); 00288 } 00289 00290 static int lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog) 00291 { 00292 struct lwip_socket *s = (struct lwip_socket *)handle; 00293 00294 err_t err = netconn_listen_with_backlog(s->conn, backlog); 00295 return lwip_err_remap(err); 00296 } 00297 00298 static int lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 00299 { 00300 struct lwip_socket *s = (struct lwip_socket *)handle; 00301 if (addr.version != NSAPI_IPv4) { 00302 return NSAPI_ERROR_PARAMETER; 00303 } 00304 00305 netconn_set_nonblocking(s->conn, false); 00306 err_t err = netconn_connect(s->conn, (ip_addr_t *)addr.bytes, port); 00307 netconn_set_nonblocking(s->conn, true); 00308 00309 return lwip_err_remap(err); 00310 } 00311 00312 static int lwip_socket_accept(nsapi_stack_t *stack, nsapi_socket_t server, nsapi_socket_t *handle, nsapi_addr_t *addr, uint16_t *port) 00313 { 00314 struct lwip_socket *s = (struct lwip_socket *)server; 00315 struct lwip_socket *ns = lwip_arena_alloc(); 00316 if (!ns) { 00317 return NSAPI_ERROR_NO_SOCKET; 00318 } 00319 00320 err_t err = netconn_accept(s->conn, &ns->conn); 00321 if (err != ERR_OK) { 00322 lwip_arena_dealloc(ns); 00323 return lwip_err_remap(err); 00324 } 00325 00326 netconn_set_recvtimeout(ns->conn, 1); 00327 *(struct lwip_socket **)handle = ns; 00328 00329 (void) netconn_peer(ns->conn, (ip_addr_t *)addr->bytes, port); 00330 addr->version = NSAPI_IPv4; 00331 00332 return 0; 00333 } 00334 00335 static int lwip_socket_send(nsapi_stack_t *stack, nsapi_socket_t handle, const void *data, unsigned size) 00336 { 00337 struct lwip_socket *s = (struct lwip_socket *)handle; 00338 00339 err_t err = netconn_write(s->conn, data, size, NETCONN_COPY); 00340 if (err != ERR_OK) { 00341 return lwip_err_remap(err); 00342 } 00343 00344 return size; 00345 } 00346 00347 static int lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, unsigned size) 00348 { 00349 struct lwip_socket *s = (struct lwip_socket *)handle; 00350 00351 if (!s->buf) { 00352 err_t err = netconn_recv(s->conn, &s->buf); 00353 s->offset = 0; 00354 00355 if (err != ERR_OK) { 00356 return (err == ERR_CLSD) ? 0 : lwip_err_remap(err); 00357 } 00358 } 00359 00360 u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); 00361 s->offset += recv; 00362 00363 if (s->offset >= netbuf_len(s->buf)) { 00364 netbuf_delete(s->buf); 00365 s->buf = 0; 00366 } 00367 00368 return recv; 00369 } 00370 00371 static int lwip_socket_sendto(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port, const void *data, unsigned size) 00372 { 00373 struct lwip_socket *s = (struct lwip_socket *)handle; 00374 if (addr.version != NSAPI_IPv4) { 00375 return NSAPI_ERROR_PARAMETER; 00376 } 00377 00378 struct netbuf *buf = netbuf_new(); 00379 err_t err = netbuf_ref(buf, data, (u16_t)size); 00380 if (err != ERR_OK) { 00381 netbuf_free(buf); 00382 return lwip_err_remap(err);; 00383 } 00384 00385 err = netconn_sendto(s->conn, buf, (ip_addr_t *)addr.bytes, port); 00386 netbuf_delete(buf); 00387 if (err != ERR_OK) { 00388 return lwip_err_remap(err); 00389 } 00390 00391 return size; 00392 } 00393 00394 static int lwip_socket_recvfrom(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t *addr, uint16_t *port, void *data, unsigned size) 00395 { 00396 struct lwip_socket *s = (struct lwip_socket *)handle; 00397 00398 struct netbuf *buf; 00399 err_t err = netconn_recv(s->conn, &buf); 00400 if (err != ERR_OK) { 00401 return lwip_err_remap(err); 00402 } 00403 00404 addr->version = NSAPI_IPv4; 00405 memcpy(addr->bytes, netbuf_fromaddr(buf), sizeof addr->bytes); 00406 *port = netbuf_fromport(buf); 00407 00408 u16_t recv = netbuf_copy(buf, data, (u16_t)size); 00409 netbuf_delete(buf); 00410 00411 return recv; 00412 } 00413 00414 static int lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) 00415 { 00416 struct lwip_socket *s = (struct lwip_socket *)handle; 00417 00418 switch (optname) { 00419 case NSAPI_KEEPALIVE: 00420 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00421 return NSAPI_ERROR_UNSUPPORTED; 00422 } 00423 00424 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; 00425 return 0; 00426 00427 case NSAPI_KEEPIDLE: 00428 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00429 return NSAPI_ERROR_UNSUPPORTED; 00430 } 00431 00432 s->conn->pcb.tcp->keep_idle = *(int*)optval; 00433 return 0; 00434 00435 case NSAPI_KEEPINTVL: 00436 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 00437 return NSAPI_ERROR_UNSUPPORTED; 00438 } 00439 00440 s->conn->pcb.tcp->keep_intvl = *(int*)optval; 00441 return 0; 00442 00443 case NSAPI_REUSEADDR: 00444 if (optlen != sizeof(int)) { 00445 return NSAPI_ERROR_UNSUPPORTED; 00446 } 00447 00448 if (*(int *)optval) { 00449 s->conn->pcb.tcp->so_options |= SOF_REUSEADDR; 00450 } else { 00451 s->conn->pcb.tcp->so_options &= ~SOF_REUSEADDR; 00452 } 00453 return 0; 00454 00455 default: 00456 return NSAPI_ERROR_UNSUPPORTED; 00457 } 00458 } 00459 00460 static void lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data) 00461 { 00462 struct lwip_socket *s = (struct lwip_socket *)handle; 00463 00464 s->cb = callback; 00465 s->data = data; 00466 } 00467 00468 00469 /* LWIP network stack */ 00470 const nsapi_stack_api_t lwip_stack_api = { 00471 .get_ip_address = lwip_getaddr, 00472 .gethostbyname = lwip_gethostbyname, 00473 .socket_open = lwip_socket_open, 00474 .socket_close = lwip_socket_close, 00475 .socket_bind = lwip_socket_bind, 00476 .socket_listen = lwip_socket_listen, 00477 .socket_connect = lwip_socket_connect, 00478 .socket_accept = lwip_socket_accept, 00479 .socket_send = lwip_socket_send, 00480 .socket_recv = lwip_socket_recv, 00481 .socket_sendto = lwip_socket_sendto, 00482 .socket_recvfrom = lwip_socket_recvfrom, 00483 .setsockopt = lwip_setsockopt, 00484 .socket_attach = lwip_socket_attach, 00485 }; 00486 00487 nsapi_stack_t lwip_stack = { 00488 .stack_api = &lwip_stack_api, 00489 };
Generated on Tue Jul 12 2022 12:28:36 by
