joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_stack.c Source File

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 };