mbed-os for GR-LYCHEE

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Committer:
dkato
Date:
Fri Feb 02 05:42:23 2018 +0000
Revision:
0:f782d9c66c49
mbed-os for GR-LYCHEE

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:f782d9c66c49 1 /* LWIP implementation of NetworkInterfaceAPI
dkato 0:f782d9c66c49 2 * Copyright (c) 2015 ARM Limited
dkato 0:f782d9c66c49 3 *
dkato 0:f782d9c66c49 4 * Licensed under the Apache License, Version 2.0 (the "License");
dkato 0:f782d9c66c49 5 * you may not use this file except in compliance with the License.
dkato 0:f782d9c66c49 6 * You may obtain a copy of the License at
dkato 0:f782d9c66c49 7 *
dkato 0:f782d9c66c49 8 * http://www.apache.org/licenses/LICENSE-2.0
dkato 0:f782d9c66c49 9 *
dkato 0:f782d9c66c49 10 * Unless required by applicable law or agreed to in writing, software
dkato 0:f782d9c66c49 11 * distributed under the License is distributed on an "AS IS" BASIS,
dkato 0:f782d9c66c49 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dkato 0:f782d9c66c49 13 * See the License for the specific language governing permissions and
dkato 0:f782d9c66c49 14 * limitations under the License.
dkato 0:f782d9c66c49 15 */
dkato 0:f782d9c66c49 16
dkato 0:f782d9c66c49 17 #include "nsapi.h"
dkato 0:f782d9c66c49 18 #include "mbed_interface.h"
dkato 0:f782d9c66c49 19 #include <stdio.h>
dkato 0:f782d9c66c49 20 #include <stdbool.h>
dkato 0:f782d9c66c49 21 #include <string.h>
dkato 0:f782d9c66c49 22
dkato 0:f782d9c66c49 23 #include "eth_arch.h"
dkato 0:f782d9c66c49 24 #include "lwip/opt.h"
dkato 0:f782d9c66c49 25 #include "lwip/api.h"
dkato 0:f782d9c66c49 26 #include "lwip/inet.h"
dkato 0:f782d9c66c49 27 #include "lwip/netif.h"
dkato 0:f782d9c66c49 28 #include "lwip/dhcp.h"
dkato 0:f782d9c66c49 29 #include "lwip/tcpip.h"
dkato 0:f782d9c66c49 30 #include "lwip/tcp.h"
dkato 0:f782d9c66c49 31 #include "lwip/ip.h"
dkato 0:f782d9c66c49 32 #include "lwip/mld6.h"
dkato 0:f782d9c66c49 33 #include "lwip/dns.h"
dkato 0:f782d9c66c49 34 #include "lwip/udp.h"
dkato 0:f782d9c66c49 35
dkato 0:f782d9c66c49 36 #include "emac_api.h"
dkato 0:f782d9c66c49 37
dkato 0:f782d9c66c49 38 #if DEVICE_EMAC
dkato 0:f782d9c66c49 39 #define MBED_NETIF_INIT_FN emac_lwip_if_init
dkato 0:f782d9c66c49 40 #else
dkato 0:f782d9c66c49 41 #define MBED_NETIF_INIT_FN eth_arch_enetif_init
dkato 0:f782d9c66c49 42 #endif
dkato 0:f782d9c66c49 43
dkato 0:f782d9c66c49 44 #define DHCP_TIMEOUT 15000
dkato 0:f782d9c66c49 45
dkato 0:f782d9c66c49 46 /* Static arena of sockets */
dkato 0:f782d9c66c49 47 static struct lwip_socket {
dkato 0:f782d9c66c49 48 bool in_use;
dkato 0:f782d9c66c49 49
dkato 0:f782d9c66c49 50 struct netconn *conn;
dkato 0:f782d9c66c49 51 struct netbuf *buf;
dkato 0:f782d9c66c49 52 u16_t offset;
dkato 0:f782d9c66c49 53
dkato 0:f782d9c66c49 54 void (*cb)(void *);
dkato 0:f782d9c66c49 55 void *data;
dkato 0:f782d9c66c49 56 } lwip_arena[MEMP_NUM_NETCONN];
dkato 0:f782d9c66c49 57
dkato 0:f782d9c66c49 58 static bool lwip_connected = false;
dkato 0:f782d9c66c49 59
dkato 0:f782d9c66c49 60 static void mbed_lwip_arena_init(void)
dkato 0:f782d9c66c49 61 {
dkato 0:f782d9c66c49 62 memset(lwip_arena, 0, sizeof lwip_arena);
dkato 0:f782d9c66c49 63 }
dkato 0:f782d9c66c49 64
dkato 0:f782d9c66c49 65 static struct lwip_socket *mbed_lwip_arena_alloc(void)
dkato 0:f782d9c66c49 66 {
dkato 0:f782d9c66c49 67 sys_prot_t prot = sys_arch_protect();
dkato 0:f782d9c66c49 68
dkato 0:f782d9c66c49 69 for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
dkato 0:f782d9c66c49 70 if (!lwip_arena[i].in_use) {
dkato 0:f782d9c66c49 71 struct lwip_socket *s = &lwip_arena[i];
dkato 0:f782d9c66c49 72 memset(s, 0, sizeof *s);
dkato 0:f782d9c66c49 73 s->in_use = true;
dkato 0:f782d9c66c49 74 sys_arch_unprotect(prot);
dkato 0:f782d9c66c49 75 return s;
dkato 0:f782d9c66c49 76 }
dkato 0:f782d9c66c49 77 }
dkato 0:f782d9c66c49 78
dkato 0:f782d9c66c49 79 sys_arch_unprotect(prot);
dkato 0:f782d9c66c49 80 return 0;
dkato 0:f782d9c66c49 81 }
dkato 0:f782d9c66c49 82
dkato 0:f782d9c66c49 83 static void mbed_lwip_arena_dealloc(struct lwip_socket *s)
dkato 0:f782d9c66c49 84 {
dkato 0:f782d9c66c49 85 s->in_use = false;
dkato 0:f782d9c66c49 86 }
dkato 0:f782d9c66c49 87
dkato 0:f782d9c66c49 88 static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
dkato 0:f782d9c66c49 89 {
dkato 0:f782d9c66c49 90 // Filter send minus events
dkato 0:f782d9c66c49 91 if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) {
dkato 0:f782d9c66c49 92 return;
dkato 0:f782d9c66c49 93 }
dkato 0:f782d9c66c49 94
dkato 0:f782d9c66c49 95 sys_prot_t prot = sys_arch_protect();
dkato 0:f782d9c66c49 96
dkato 0:f782d9c66c49 97 for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
dkato 0:f782d9c66c49 98 if (lwip_arena[i].in_use
dkato 0:f782d9c66c49 99 && lwip_arena[i].conn == nc
dkato 0:f782d9c66c49 100 && lwip_arena[i].cb) {
dkato 0:f782d9c66c49 101 lwip_arena[i].cb(lwip_arena[i].data);
dkato 0:f782d9c66c49 102 }
dkato 0:f782d9c66c49 103 }
dkato 0:f782d9c66c49 104
dkato 0:f782d9c66c49 105 sys_arch_unprotect(prot);
dkato 0:f782d9c66c49 106 }
dkato 0:f782d9c66c49 107
dkato 0:f782d9c66c49 108
dkato 0:f782d9c66c49 109 /* TCP/IP and Network Interface Initialisation */
dkato 0:f782d9c66c49 110 static struct netif lwip_netif;
dkato 0:f782d9c66c49 111 static bool lwip_dhcp = false;
dkato 0:f782d9c66c49 112 static char lwip_mac_address[NSAPI_MAC_SIZE];
dkato 0:f782d9c66c49 113
dkato 0:f782d9c66c49 114 #if !LWIP_IPV4 || !LWIP_IPV6
dkato 0:f782d9c66c49 115 static bool all_zeros(const uint8_t *p, int len)
dkato 0:f782d9c66c49 116 {
dkato 0:f782d9c66c49 117 for (int i = 0; i < len; i++) {
dkato 0:f782d9c66c49 118 if (p[i]) {
dkato 0:f782d9c66c49 119 return false;
dkato 0:f782d9c66c49 120 }
dkato 0:f782d9c66c49 121 }
dkato 0:f782d9c66c49 122
dkato 0:f782d9c66c49 123 return true;
dkato 0:f782d9c66c49 124 }
dkato 0:f782d9c66c49 125 #endif
dkato 0:f782d9c66c49 126
dkato 0:f782d9c66c49 127 static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in)
dkato 0:f782d9c66c49 128 {
dkato 0:f782d9c66c49 129 #if LWIP_IPV6
dkato 0:f782d9c66c49 130 if (in->version == NSAPI_IPv6) {
dkato 0:f782d9c66c49 131 IP_SET_TYPE(out, IPADDR_TYPE_V6);
dkato 0:f782d9c66c49 132 MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t));
dkato 0:f782d9c66c49 133 return true;
dkato 0:f782d9c66c49 134 }
dkato 0:f782d9c66c49 135 #if !LWIP_IPV4
dkato 0:f782d9c66c49 136 /* For bind() and other purposes, need to accept "null" of other type */
dkato 0:f782d9c66c49 137 /* (People use IPv4 0.0.0.0 as a general null) */
dkato 0:f782d9c66c49 138 if (in->version == NSAPI_UNSPEC ||
dkato 0:f782d9c66c49 139 (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) {
dkato 0:f782d9c66c49 140 ip_addr_set_zero_ip6(out);
dkato 0:f782d9c66c49 141 return true;
dkato 0:f782d9c66c49 142 }
dkato 0:f782d9c66c49 143 #endif
dkato 0:f782d9c66c49 144 #endif
dkato 0:f782d9c66c49 145
dkato 0:f782d9c66c49 146 #if LWIP_IPV4
dkato 0:f782d9c66c49 147 if (in->version == NSAPI_IPv4) {
dkato 0:f782d9c66c49 148 IP_SET_TYPE(out, IPADDR_TYPE_V4);
dkato 0:f782d9c66c49 149 MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t));
dkato 0:f782d9c66c49 150 return true;
dkato 0:f782d9c66c49 151 }
dkato 0:f782d9c66c49 152 #if !LWIP_IPV6
dkato 0:f782d9c66c49 153 /* For symmetry with above, accept IPv6 :: as a general null */
dkato 0:f782d9c66c49 154 if (in->version == NSAPI_UNSPEC ||
dkato 0:f782d9c66c49 155 (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) {
dkato 0:f782d9c66c49 156 ip_addr_set_zero_ip4(out);
dkato 0:f782d9c66c49 157 return true;
dkato 0:f782d9c66c49 158 }
dkato 0:f782d9c66c49 159 #endif
dkato 0:f782d9c66c49 160 #endif
dkato 0:f782d9c66c49 161
dkato 0:f782d9c66c49 162 #if LWIP_IPV4 && LWIP_IPV6
dkato 0:f782d9c66c49 163 if (in->version == NSAPI_UNSPEC) {
dkato 0:f782d9c66c49 164 #if IP_VERSION_PREF == PREF_IPV4
dkato 0:f782d9c66c49 165 ip_addr_set_zero_ip4(out);
dkato 0:f782d9c66c49 166 #else
dkato 0:f782d9c66c49 167 ip_addr_set_zero_ip6(out);
dkato 0:f782d9c66c49 168 #endif
dkato 0:f782d9c66c49 169 return true;
dkato 0:f782d9c66c49 170 }
dkato 0:f782d9c66c49 171 #endif
dkato 0:f782d9c66c49 172
dkato 0:f782d9c66c49 173 return false;
dkato 0:f782d9c66c49 174 }
dkato 0:f782d9c66c49 175
dkato 0:f782d9c66c49 176 static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in)
dkato 0:f782d9c66c49 177 {
dkato 0:f782d9c66c49 178 #if LWIP_IPV6
dkato 0:f782d9c66c49 179 if (IP_IS_V6(in)) {
dkato 0:f782d9c66c49 180 out->version = NSAPI_IPv6;
dkato 0:f782d9c66c49 181 MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t));
dkato 0:f782d9c66c49 182 return true;
dkato 0:f782d9c66c49 183 }
dkato 0:f782d9c66c49 184 #endif
dkato 0:f782d9c66c49 185 #if LWIP_IPV4
dkato 0:f782d9c66c49 186 if (IP_IS_V4(in)) {
dkato 0:f782d9c66c49 187 out->version = NSAPI_IPv4;
dkato 0:f782d9c66c49 188 MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t));
dkato 0:f782d9c66c49 189 return true;
dkato 0:f782d9c66c49 190 }
dkato 0:f782d9c66c49 191 #endif
dkato 0:f782d9c66c49 192 return false;
dkato 0:f782d9c66c49 193 }
dkato 0:f782d9c66c49 194
dkato 0:f782d9c66c49 195 static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif)
dkato 0:f782d9c66c49 196 {
dkato 0:f782d9c66c49 197 #if LWIP_IPV4
dkato 0:f782d9c66c49 198 if (!netif_is_up(netif)) {
dkato 0:f782d9c66c49 199 return NULL;
dkato 0:f782d9c66c49 200 }
dkato 0:f782d9c66c49 201
dkato 0:f782d9c66c49 202 if (!ip4_addr_isany(netif_ip4_addr(netif))) {
dkato 0:f782d9c66c49 203 return netif_ip_addr4(netif);
dkato 0:f782d9c66c49 204 }
dkato 0:f782d9c66c49 205 #endif
dkato 0:f782d9c66c49 206
dkato 0:f782d9c66c49 207 return NULL;
dkato 0:f782d9c66c49 208 }
dkato 0:f782d9c66c49 209
dkato 0:f782d9c66c49 210 static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif)
dkato 0:f782d9c66c49 211 {
dkato 0:f782d9c66c49 212 #if LWIP_IPV6
dkato 0:f782d9c66c49 213 if (!netif_is_up(netif)) {
dkato 0:f782d9c66c49 214 return NULL;
dkato 0:f782d9c66c49 215 }
dkato 0:f782d9c66c49 216
dkato 0:f782d9c66c49 217 for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
dkato 0:f782d9c66c49 218 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
dkato 0:f782d9c66c49 219 !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
dkato 0:f782d9c66c49 220 return netif_ip_addr6(netif, i);
dkato 0:f782d9c66c49 221 }
dkato 0:f782d9c66c49 222 }
dkato 0:f782d9c66c49 223 #endif
dkato 0:f782d9c66c49 224
dkato 0:f782d9c66c49 225 return NULL;
dkato 0:f782d9c66c49 226
dkato 0:f782d9c66c49 227 }
dkato 0:f782d9c66c49 228
dkato 0:f782d9c66c49 229 const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif)
dkato 0:f782d9c66c49 230 {
dkato 0:f782d9c66c49 231 const ip_addr_t *pref_ip_addr = 0;
dkato 0:f782d9c66c49 232 const ip_addr_t *npref_ip_addr = 0;
dkato 0:f782d9c66c49 233
dkato 0:f782d9c66c49 234 #if IP_VERSION_PREF == PREF_IPV4
dkato 0:f782d9c66c49 235 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
dkato 0:f782d9c66c49 236 npref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
dkato 0:f782d9c66c49 237 #else
dkato 0:f782d9c66c49 238 pref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
dkato 0:f782d9c66c49 239 npref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
dkato 0:f782d9c66c49 240 #endif
dkato 0:f782d9c66c49 241
dkato 0:f782d9c66c49 242 if (pref_ip_addr) {
dkato 0:f782d9c66c49 243 return pref_ip_addr;
dkato 0:f782d9c66c49 244 } else if (npref_ip_addr && any_addr) {
dkato 0:f782d9c66c49 245 return npref_ip_addr;
dkato 0:f782d9c66c49 246 }
dkato 0:f782d9c66c49 247
dkato 0:f782d9c66c49 248 return NULL;
dkato 0:f782d9c66c49 249 }
dkato 0:f782d9c66c49 250
dkato 0:f782d9c66c49 251 void add_dns_addr(struct netif *lwip_netif)
dkato 0:f782d9c66c49 252 {
dkato 0:f782d9c66c49 253 // Do nothing if not brought up
dkato 0:f782d9c66c49 254 const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif);
dkato 0:f782d9c66c49 255 if (!ip_addr) {
dkato 0:f782d9c66c49 256 return;
dkato 0:f782d9c66c49 257 }
dkato 0:f782d9c66c49 258
dkato 0:f782d9c66c49 259 // Check for existing dns server
dkato 0:f782d9c66c49 260 for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
dkato 0:f782d9c66c49 261 const ip_addr_t *dns_ip_addr = dns_getserver(numdns);
dkato 0:f782d9c66c49 262 if (!ip_addr_isany(dns_ip_addr)) {
dkato 0:f782d9c66c49 263 return;
dkato 0:f782d9c66c49 264 }
dkato 0:f782d9c66c49 265 }
dkato 0:f782d9c66c49 266
dkato 0:f782d9c66c49 267 #if LWIP_IPV6
dkato 0:f782d9c66c49 268 if (IP_IS_V6(ip_addr)) {
dkato 0:f782d9c66c49 269 /* 2001:4860:4860::8888 google */
dkato 0:f782d9c66c49 270 ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
dkato 0:f782d9c66c49 271 PP_HTONL(0x20014860UL),
dkato 0:f782d9c66c49 272 PP_HTONL(0x48600000UL),
dkato 0:f782d9c66c49 273 PP_HTONL(0x00000000UL),
dkato 0:f782d9c66c49 274 PP_HTONL(0x00008888UL));
dkato 0:f782d9c66c49 275 dns_setserver(0, &ipv6_dns_addr);
dkato 0:f782d9c66c49 276 }
dkato 0:f782d9c66c49 277 #endif
dkato 0:f782d9c66c49 278
dkato 0:f782d9c66c49 279 #if LWIP_IPV4
dkato 0:f782d9c66c49 280 if (IP_IS_V4(ip_addr)) {
dkato 0:f782d9c66c49 281 /* 8.8.8.8 google */
dkato 0:f782d9c66c49 282 ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808);
dkato 0:f782d9c66c49 283 dns_setserver(0, &ipv4_dns_addr);
dkato 0:f782d9c66c49 284 }
dkato 0:f782d9c66c49 285 #endif
dkato 0:f782d9c66c49 286 }
dkato 0:f782d9c66c49 287
dkato 0:f782d9c66c49 288 static sys_sem_t lwip_tcpip_inited;
dkato 0:f782d9c66c49 289 static void mbed_lwip_tcpip_init_irq(void *eh)
dkato 0:f782d9c66c49 290 {
dkato 0:f782d9c66c49 291 sys_sem_signal(&lwip_tcpip_inited);
dkato 0:f782d9c66c49 292 }
dkato 0:f782d9c66c49 293
dkato 0:f782d9c66c49 294 static sys_sem_t lwip_netif_linked;
dkato 0:f782d9c66c49 295 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif)
dkato 0:f782d9c66c49 296 {
dkato 0:f782d9c66c49 297 if (netif_is_link_up(lwip_netif)) {
dkato 0:f782d9c66c49 298 sys_sem_signal(&lwip_netif_linked);
dkato 0:f782d9c66c49 299 }
dkato 0:f782d9c66c49 300 }
dkato 0:f782d9c66c49 301
dkato 0:f782d9c66c49 302 static sys_sem_t lwip_netif_has_addr;
dkato 0:f782d9c66c49 303 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif)
dkato 0:f782d9c66c49 304 {
dkato 0:f782d9c66c49 305 static bool any_addr = true;
dkato 0:f782d9c66c49 306
dkato 0:f782d9c66c49 307 if (netif_is_up(lwip_netif)) {
dkato 0:f782d9c66c49 308 // Indicates that has address
dkato 0:f782d9c66c49 309 if (any_addr == true && mbed_lwip_get_ip_addr(true, lwip_netif)) {
dkato 0:f782d9c66c49 310 sys_sem_signal(&lwip_netif_has_addr);
dkato 0:f782d9c66c49 311 any_addr = false;
dkato 0:f782d9c66c49 312 return;
dkato 0:f782d9c66c49 313 }
dkato 0:f782d9c66c49 314
dkato 0:f782d9c66c49 315 // Indicates that has preferred address
dkato 0:f782d9c66c49 316 if (mbed_lwip_get_ip_addr(false, lwip_netif)) {
dkato 0:f782d9c66c49 317 sys_sem_signal(&lwip_netif_has_addr);
dkato 0:f782d9c66c49 318 }
dkato 0:f782d9c66c49 319 } else {
dkato 0:f782d9c66c49 320 any_addr = true;
dkato 0:f782d9c66c49 321 }
dkato 0:f782d9c66c49 322 }
dkato 0:f782d9c66c49 323
dkato 0:f782d9c66c49 324 static void mbed_lwip_set_mac_address(void)
dkato 0:f782d9c66c49 325 {
dkato 0:f782d9c66c49 326 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
dkato 0:f782d9c66c49 327 snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
dkato 0:f782d9c66c49 328 MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2,
dkato 0:f782d9c66c49 329 MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5);
dkato 0:f782d9c66c49 330 #else
dkato 0:f782d9c66c49 331 char mac[6];
dkato 0:f782d9c66c49 332 mbed_mac_address(mac);
dkato 0:f782d9c66c49 333 snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
dkato 0:f782d9c66c49 334 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
dkato 0:f782d9c66c49 335 #endif
dkato 0:f782d9c66c49 336 }
dkato 0:f782d9c66c49 337
dkato 0:f782d9c66c49 338 /* LWIP interface implementation */
dkato 0:f782d9c66c49 339 const char *mbed_lwip_get_mac_address(void)
dkato 0:f782d9c66c49 340 {
dkato 0:f782d9c66c49 341 return lwip_mac_address[0] ? lwip_mac_address : 0;
dkato 0:f782d9c66c49 342 }
dkato 0:f782d9c66c49 343
dkato 0:f782d9c66c49 344 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen)
dkato 0:f782d9c66c49 345 {
dkato 0:f782d9c66c49 346 const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
dkato 0:f782d9c66c49 347 if (!addr) {
dkato 0:f782d9c66c49 348 return NULL;
dkato 0:f782d9c66c49 349 }
dkato 0:f782d9c66c49 350 #if LWIP_IPV6
dkato 0:f782d9c66c49 351 if (IP_IS_V6(addr)) {
dkato 0:f782d9c66c49 352 return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
dkato 0:f782d9c66c49 353 }
dkato 0:f782d9c66c49 354 #endif
dkato 0:f782d9c66c49 355 #if LWIP_IPV4
dkato 0:f782d9c66c49 356 if (IP_IS_V4(addr)) {
dkato 0:f782d9c66c49 357 return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
dkato 0:f782d9c66c49 358 }
dkato 0:f782d9c66c49 359 #endif
dkato 0:f782d9c66c49 360 return NULL;
dkato 0:f782d9c66c49 361 }
dkato 0:f782d9c66c49 362
dkato 0:f782d9c66c49 363 const char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen)
dkato 0:f782d9c66c49 364 {
dkato 0:f782d9c66c49 365 #if LWIP_IPV4
dkato 0:f782d9c66c49 366 const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif);
dkato 0:f782d9c66c49 367 if (!ip4_addr_isany(addr)) {
dkato 0:f782d9c66c49 368 return ip4addr_ntoa_r(addr, buf, buflen);
dkato 0:f782d9c66c49 369 } else {
dkato 0:f782d9c66c49 370 return NULL;
dkato 0:f782d9c66c49 371 }
dkato 0:f782d9c66c49 372 #else
dkato 0:f782d9c66c49 373 return NULL;
dkato 0:f782d9c66c49 374 #endif
dkato 0:f782d9c66c49 375 }
dkato 0:f782d9c66c49 376
dkato 0:f782d9c66c49 377 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen)
dkato 0:f782d9c66c49 378 {
dkato 0:f782d9c66c49 379 #if LWIP_IPV4
dkato 0:f782d9c66c49 380 const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif);
dkato 0:f782d9c66c49 381 if (!ip4_addr_isany(addr)) {
dkato 0:f782d9c66c49 382 return ip4addr_ntoa_r(addr, buf, buflen);
dkato 0:f782d9c66c49 383 } else {
dkato 0:f782d9c66c49 384 return NULL;
dkato 0:f782d9c66c49 385 }
dkato 0:f782d9c66c49 386 #else
dkato 0:f782d9c66c49 387 return NULL;
dkato 0:f782d9c66c49 388 #endif
dkato 0:f782d9c66c49 389 }
dkato 0:f782d9c66c49 390
dkato 0:f782d9c66c49 391 nsapi_error_t mbed_lwip_init(emac_interface_t *emac)
dkato 0:f782d9c66c49 392 {
dkato 0:f782d9c66c49 393 // Check if we've already brought up lwip
dkato 0:f782d9c66c49 394 if (!mbed_lwip_get_mac_address()) {
dkato 0:f782d9c66c49 395 // Set up network
dkato 0:f782d9c66c49 396 mbed_lwip_set_mac_address();
dkato 0:f782d9c66c49 397
dkato 0:f782d9c66c49 398 sys_sem_new(&lwip_tcpip_inited, 0);
dkato 0:f782d9c66c49 399 sys_sem_new(&lwip_netif_linked, 0);
dkato 0:f782d9c66c49 400 sys_sem_new(&lwip_netif_has_addr, 0);
dkato 0:f782d9c66c49 401
dkato 0:f782d9c66c49 402 tcpip_init(mbed_lwip_tcpip_init_irq, NULL);
dkato 0:f782d9c66c49 403 sys_arch_sem_wait(&lwip_tcpip_inited, 0);
dkato 0:f782d9c66c49 404
dkato 0:f782d9c66c49 405 memset(&lwip_netif, 0, sizeof lwip_netif);
dkato 0:f782d9c66c49 406 if (!netif_add(&lwip_netif,
dkato 0:f782d9c66c49 407 #if LWIP_IPV4
dkato 0:f782d9c66c49 408 0, 0, 0,
dkato 0:f782d9c66c49 409 #endif
dkato 0:f782d9c66c49 410 emac, MBED_NETIF_INIT_FN, tcpip_input)) {
dkato 0:f782d9c66c49 411 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:f782d9c66c49 412 }
dkato 0:f782d9c66c49 413
dkato 0:f782d9c66c49 414 netif_set_default(&lwip_netif);
dkato 0:f782d9c66c49 415
dkato 0:f782d9c66c49 416 netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq);
dkato 0:f782d9c66c49 417 netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq);
dkato 0:f782d9c66c49 418
dkato 0:f782d9c66c49 419 #if !DEVICE_EMAC
dkato 0:f782d9c66c49 420 eth_arch_enable_interrupts();
dkato 0:f782d9c66c49 421 #endif
dkato 0:f782d9c66c49 422 }
dkato 0:f782d9c66c49 423
dkato 0:f782d9c66c49 424 return NSAPI_ERROR_OK;
dkato 0:f782d9c66c49 425 }
dkato 0:f782d9c66c49 426
dkato 0:f782d9c66c49 427 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
dkato 0:f782d9c66c49 428 {
dkato 0:f782d9c66c49 429 // Check if we've already connected
dkato 0:f782d9c66c49 430 if (lwip_connected) {
dkato 0:f782d9c66c49 431 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 432 }
dkato 0:f782d9c66c49 433
dkato 0:f782d9c66c49 434 if(mbed_lwip_init(NULL) != NSAPI_ERROR_OK) {
dkato 0:f782d9c66c49 435 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:f782d9c66c49 436 }
dkato 0:f782d9c66c49 437
dkato 0:f782d9c66c49 438 // Zero out socket set
dkato 0:f782d9c66c49 439 mbed_lwip_arena_init();
dkato 0:f782d9c66c49 440
dkato 0:f782d9c66c49 441 #if LWIP_IPV6
dkato 0:f782d9c66c49 442 netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/);
dkato 0:f782d9c66c49 443 #if LWIP_IPV6_MLD
dkato 0:f782d9c66c49 444 /*
dkato 0:f782d9c66c49 445 * For hardware/netifs that implement MAC filtering.
dkato 0:f782d9c66c49 446 * All-nodes link-local is handled by default, so we must let the hardware know
dkato 0:f782d9c66c49 447 * to allow multicast packets in.
dkato 0:f782d9c66c49 448 * Should set mld_mac_filter previously. */
dkato 0:f782d9c66c49 449 if (lwip_netif.mld_mac_filter != NULL) {
dkato 0:f782d9c66c49 450 ip6_addr_t ip6_allnodes_ll;
dkato 0:f782d9c66c49 451 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
dkato 0:f782d9c66c49 452 lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
dkato 0:f782d9c66c49 453 }
dkato 0:f782d9c66c49 454 #endif /* LWIP_IPV6_MLD */
dkato 0:f782d9c66c49 455
dkato 0:f782d9c66c49 456 #if LWIP_IPV6_AUTOCONFIG
dkato 0:f782d9c66c49 457 /* IPv6 address autoconfiguration not enabled by default */
dkato 0:f782d9c66c49 458 lwip_netif.ip6_autoconfig_enabled = 1;
dkato 0:f782d9c66c49 459 #endif /* LWIP_IPV6_AUTOCONFIG */
dkato 0:f782d9c66c49 460
dkato 0:f782d9c66c49 461 #endif
dkato 0:f782d9c66c49 462
dkato 0:f782d9c66c49 463 u32_t ret;
dkato 0:f782d9c66c49 464
dkato 0:f782d9c66c49 465 if (!netif_is_link_up(&lwip_netif)) {
dkato 0:f782d9c66c49 466 ret = sys_arch_sem_wait(&lwip_netif_linked, 15000);
dkato 0:f782d9c66c49 467
dkato 0:f782d9c66c49 468 if (ret == SYS_ARCH_TIMEOUT) {
dkato 0:f782d9c66c49 469 return NSAPI_ERROR_NO_CONNECTION;
dkato 0:f782d9c66c49 470 }
dkato 0:f782d9c66c49 471 }
dkato 0:f782d9c66c49 472
dkato 0:f782d9c66c49 473 #if LWIP_IPV4
dkato 0:f782d9c66c49 474 if (!dhcp) {
dkato 0:f782d9c66c49 475 ip4_addr_t ip_addr;
dkato 0:f782d9c66c49 476 ip4_addr_t netmask_addr;
dkato 0:f782d9c66c49 477 ip4_addr_t gw_addr;
dkato 0:f782d9c66c49 478
dkato 0:f782d9c66c49 479 if (!inet_aton(ip, &ip_addr) ||
dkato 0:f782d9c66c49 480 !inet_aton(netmask, &netmask_addr) ||
dkato 0:f782d9c66c49 481 !inet_aton(gw, &gw_addr)) {
dkato 0:f782d9c66c49 482 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 483 }
dkato 0:f782d9c66c49 484
dkato 0:f782d9c66c49 485 netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
dkato 0:f782d9c66c49 486 }
dkato 0:f782d9c66c49 487 #endif
dkato 0:f782d9c66c49 488
dkato 0:f782d9c66c49 489 netif_set_up(&lwip_netif);
dkato 0:f782d9c66c49 490
dkato 0:f782d9c66c49 491 #if LWIP_IPV4
dkato 0:f782d9c66c49 492 // Connect to the network
dkato 0:f782d9c66c49 493 lwip_dhcp = dhcp;
dkato 0:f782d9c66c49 494
dkato 0:f782d9c66c49 495 if (lwip_dhcp) {
dkato 0:f782d9c66c49 496 err_t err = dhcp_start(&lwip_netif);
dkato 0:f782d9c66c49 497 if (err) {
dkato 0:f782d9c66c49 498 return NSAPI_ERROR_DHCP_FAILURE;
dkato 0:f782d9c66c49 499 }
dkato 0:f782d9c66c49 500 }
dkato 0:f782d9c66c49 501 #endif
dkato 0:f782d9c66c49 502
dkato 0:f782d9c66c49 503 // If doesn't have address
dkato 0:f782d9c66c49 504 if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) {
dkato 0:f782d9c66c49 505 ret = sys_arch_sem_wait(&lwip_netif_has_addr, 15000);
dkato 0:f782d9c66c49 506 if (ret == SYS_ARCH_TIMEOUT) {
dkato 0:f782d9c66c49 507 return NSAPI_ERROR_DHCP_FAILURE;
dkato 0:f782d9c66c49 508 }
dkato 0:f782d9c66c49 509 }
dkato 0:f782d9c66c49 510
dkato 0:f782d9c66c49 511 #if ADDR_TIMEOUT
dkato 0:f782d9c66c49 512 // If address is not for preferred stack waits a while to see
dkato 0:f782d9c66c49 513 // if preferred stack address is acquired
dkato 0:f782d9c66c49 514 if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) {
dkato 0:f782d9c66c49 515 ret = sys_arch_sem_wait(&lwip_netif_has_addr, ADDR_TIMEOUT * 1000);
dkato 0:f782d9c66c49 516 }
dkato 0:f782d9c66c49 517 #endif
dkato 0:f782d9c66c49 518
dkato 0:f782d9c66c49 519 add_dns_addr(&lwip_netif);
dkato 0:f782d9c66c49 520
dkato 0:f782d9c66c49 521 lwip_connected = true;
dkato 0:f782d9c66c49 522 return 0;
dkato 0:f782d9c66c49 523 }
dkato 0:f782d9c66c49 524
dkato 0:f782d9c66c49 525 #if LWIP_IPV6
dkato 0:f782d9c66c49 526 void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif)
dkato 0:f782d9c66c49 527 {
dkato 0:f782d9c66c49 528 for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
dkato 0:f782d9c66c49 529 netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID);
dkato 0:f782d9c66c49 530 }
dkato 0:f782d9c66c49 531 }
dkato 0:f782d9c66c49 532 #endif
dkato 0:f782d9c66c49 533
dkato 0:f782d9c66c49 534 nsapi_error_t mbed_lwip_bringdown(void)
dkato 0:f782d9c66c49 535 {
dkato 0:f782d9c66c49 536 // Check if we've connected
dkato 0:f782d9c66c49 537 if (!lwip_connected) {
dkato 0:f782d9c66c49 538 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 539 }
dkato 0:f782d9c66c49 540
dkato 0:f782d9c66c49 541 #if LWIP_IPV4
dkato 0:f782d9c66c49 542 // Disconnect from the network
dkato 0:f782d9c66c49 543 if (lwip_dhcp) {
dkato 0:f782d9c66c49 544 dhcp_release(&lwip_netif);
dkato 0:f782d9c66c49 545 dhcp_stop(&lwip_netif);
dkato 0:f782d9c66c49 546 lwip_dhcp = false;
dkato 0:f782d9c66c49 547 }
dkato 0:f782d9c66c49 548 #endif
dkato 0:f782d9c66c49 549
dkato 0:f782d9c66c49 550 netif_set_down(&lwip_netif);
dkato 0:f782d9c66c49 551
dkato 0:f782d9c66c49 552 #if LWIP_IPV6
dkato 0:f782d9c66c49 553 mbed_lwip_clear_ipv6_addresses(&lwip_netif);
dkato 0:f782d9c66c49 554 #endif
dkato 0:f782d9c66c49 555
dkato 0:f782d9c66c49 556 sys_sem_free(&lwip_netif_has_addr);
dkato 0:f782d9c66c49 557 sys_sem_new(&lwip_netif_has_addr, 0);
dkato 0:f782d9c66c49 558 lwip_connected = false;
dkato 0:f782d9c66c49 559 return 0;
dkato 0:f782d9c66c49 560 }
dkato 0:f782d9c66c49 561
dkato 0:f782d9c66c49 562 /* LWIP error remapping */
dkato 0:f782d9c66c49 563 static nsapi_error_t mbed_lwip_err_remap(err_t err) {
dkato 0:f782d9c66c49 564 switch (err) {
dkato 0:f782d9c66c49 565 case ERR_OK:
dkato 0:f782d9c66c49 566 case ERR_CLSD:
dkato 0:f782d9c66c49 567 return 0;
dkato 0:f782d9c66c49 568 case ERR_MEM:
dkato 0:f782d9c66c49 569 return NSAPI_ERROR_NO_MEMORY;
dkato 0:f782d9c66c49 570 case ERR_CONN:
dkato 0:f782d9c66c49 571 case ERR_RST:
dkato 0:f782d9c66c49 572 case ERR_ABRT:
dkato 0:f782d9c66c49 573 return NSAPI_ERROR_NO_CONNECTION;
dkato 0:f782d9c66c49 574 case ERR_TIMEOUT:
dkato 0:f782d9c66c49 575 case ERR_RTE:
dkato 0:f782d9c66c49 576 case ERR_INPROGRESS:
dkato 0:f782d9c66c49 577 case ERR_WOULDBLOCK:
dkato 0:f782d9c66c49 578 return NSAPI_ERROR_WOULD_BLOCK;
dkato 0:f782d9c66c49 579 case ERR_VAL:
dkato 0:f782d9c66c49 580 case ERR_USE:
dkato 0:f782d9c66c49 581 case ERR_ISCONN:
dkato 0:f782d9c66c49 582 case ERR_ARG:
dkato 0:f782d9c66c49 583 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 584 default:
dkato 0:f782d9c66c49 585 return NSAPI_ERROR_DEVICE_ERROR;
dkato 0:f782d9c66c49 586 }
dkato 0:f782d9c66c49 587 }
dkato 0:f782d9c66c49 588
dkato 0:f782d9c66c49 589 /* LWIP network stack implementation */
dkato 0:f782d9c66c49 590 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version)
dkato 0:f782d9c66c49 591 {
dkato 0:f782d9c66c49 592 ip_addr_t lwip_addr;
dkato 0:f782d9c66c49 593
dkato 0:f782d9c66c49 594 #if LWIP_IPV4 && LWIP_IPV6
dkato 0:f782d9c66c49 595 u8_t addr_type;
dkato 0:f782d9c66c49 596 if (version == NSAPI_UNSPEC) {
dkato 0:f782d9c66c49 597 const ip_addr_t *ip_addr;
dkato 0:f782d9c66c49 598 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
dkato 0:f782d9c66c49 599 if (IP_IS_V6(ip_addr)) {
dkato 0:f782d9c66c49 600 addr_type = NETCONN_DNS_IPV6;
dkato 0:f782d9c66c49 601 } else {
dkato 0:f782d9c66c49 602 addr_type = NETCONN_DNS_IPV4;
dkato 0:f782d9c66c49 603 }
dkato 0:f782d9c66c49 604 } else if (version == NSAPI_IPv4) {
dkato 0:f782d9c66c49 605 addr_type = NETCONN_DNS_IPV4;
dkato 0:f782d9c66c49 606 } else if (version == NSAPI_IPv6) {
dkato 0:f782d9c66c49 607 addr_type = NETCONN_DNS_IPV6;
dkato 0:f782d9c66c49 608 }
dkato 0:f782d9c66c49 609 err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type);
dkato 0:f782d9c66c49 610 #elif LWIP_IPV4
dkato 0:f782d9c66c49 611 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) {
dkato 0:f782d9c66c49 612 return NSAPI_ERROR_DNS_FAILURE;
dkato 0:f782d9c66c49 613 }
dkato 0:f782d9c66c49 614 err_t err = netconn_gethostbyname(host, &lwip_addr);
dkato 0:f782d9c66c49 615 #elif LWIP_IPV6
dkato 0:f782d9c66c49 616 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) {
dkato 0:f782d9c66c49 617 return NSAPI_ERROR_DNS_FAILURE;
dkato 0:f782d9c66c49 618 }
dkato 0:f782d9c66c49 619 err_t err = netconn_gethostbyname(host, &lwip_addr);
dkato 0:f782d9c66c49 620 #endif
dkato 0:f782d9c66c49 621
dkato 0:f782d9c66c49 622 if (err != ERR_OK) {
dkato 0:f782d9c66c49 623 return NSAPI_ERROR_DNS_FAILURE;
dkato 0:f782d9c66c49 624 }
dkato 0:f782d9c66c49 625
dkato 0:f782d9c66c49 626 convert_lwip_addr_to_mbed(addr, &lwip_addr);
dkato 0:f782d9c66c49 627
dkato 0:f782d9c66c49 628 return 0;
dkato 0:f782d9c66c49 629 }
dkato 0:f782d9c66c49 630
dkato 0:f782d9c66c49 631 static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr)
dkato 0:f782d9c66c49 632 {
dkato 0:f782d9c66c49 633 // Shift all dns servers down to give precedence to new server
dkato 0:f782d9c66c49 634 for (int i = DNS_MAX_SERVERS-1; i > 0; i--) {
dkato 0:f782d9c66c49 635 dns_setserver(i, dns_getserver(i-1));
dkato 0:f782d9c66c49 636 }
dkato 0:f782d9c66c49 637
dkato 0:f782d9c66c49 638 ip_addr_t ip_addr;
dkato 0:f782d9c66c49 639 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
dkato 0:f782d9c66c49 640 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 641 }
dkato 0:f782d9c66c49 642
dkato 0:f782d9c66c49 643 dns_setserver(0, &ip_addr);
dkato 0:f782d9c66c49 644 return 0;
dkato 0:f782d9c66c49 645 }
dkato 0:f782d9c66c49 646
dkato 0:f782d9c66c49 647 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto)
dkato 0:f782d9c66c49 648 {
dkato 0:f782d9c66c49 649 // check if network is connected
dkato 0:f782d9c66c49 650 if (!lwip_connected) {
dkato 0:f782d9c66c49 651 return NSAPI_ERROR_NO_CONNECTION;
dkato 0:f782d9c66c49 652 }
dkato 0:f782d9c66c49 653
dkato 0:f782d9c66c49 654 // allocate a socket
dkato 0:f782d9c66c49 655 struct lwip_socket *s = mbed_lwip_arena_alloc();
dkato 0:f782d9c66c49 656 if (!s) {
dkato 0:f782d9c66c49 657 return NSAPI_ERROR_NO_SOCKET;
dkato 0:f782d9c66c49 658 }
dkato 0:f782d9c66c49 659
dkato 0:f782d9c66c49 660 u8_t lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP;
dkato 0:f782d9c66c49 661
dkato 0:f782d9c66c49 662 #if LWIP_IPV6 && LWIP_IPV4
dkato 0:f782d9c66c49 663 const ip_addr_t *ip_addr;
dkato 0:f782d9c66c49 664 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
dkato 0:f782d9c66c49 665
dkato 0:f782d9c66c49 666 if (IP_IS_V6(ip_addr)) {
dkato 0:f782d9c66c49 667 // Enable IPv6 (or dual-stack). LWIP dual-stack support is
dkato 0:f782d9c66c49 668 // currently incomplete as of 2.0.0rc2 - eg we will only be able
dkato 0:f782d9c66c49 669 // to do a UDP sendto to an address matching the type selected
dkato 0:f782d9c66c49 670 // here. Matching "get_ip_addr" and DNS logic, use v4 if
dkato 0:f782d9c66c49 671 // available.
dkato 0:f782d9c66c49 672 lwip_proto |= NETCONN_TYPE_IPV6;
dkato 0:f782d9c66c49 673 }
dkato 0:f782d9c66c49 674 #elif LWIP_IPV6
dkato 0:f782d9c66c49 675 lwip_proto |= NETCONN_TYPE_IPV6;
dkato 0:f782d9c66c49 676 #endif
dkato 0:f782d9c66c49 677
dkato 0:f782d9c66c49 678 s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback);
dkato 0:f782d9c66c49 679
dkato 0:f782d9c66c49 680 if (!s->conn) {
dkato 0:f782d9c66c49 681 mbed_lwip_arena_dealloc(s);
dkato 0:f782d9c66c49 682 return NSAPI_ERROR_NO_SOCKET;
dkato 0:f782d9c66c49 683 }
dkato 0:f782d9c66c49 684
dkato 0:f782d9c66c49 685 netconn_set_recvtimeout(s->conn, 1);
dkato 0:f782d9c66c49 686 *(struct lwip_socket **)handle = s;
dkato 0:f782d9c66c49 687 return 0;
dkato 0:f782d9c66c49 688 }
dkato 0:f782d9c66c49 689
dkato 0:f782d9c66c49 690 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle)
dkato 0:f782d9c66c49 691 {
dkato 0:f782d9c66c49 692 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 693
dkato 0:f782d9c66c49 694 netbuf_delete(s->buf);
dkato 0:f782d9c66c49 695 err_t err = netconn_delete(s->conn);
dkato 0:f782d9c66c49 696 mbed_lwip_arena_dealloc(s);
dkato 0:f782d9c66c49 697 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 698 }
dkato 0:f782d9c66c49 699
dkato 0:f782d9c66c49 700 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
dkato 0:f782d9c66c49 701 {
dkato 0:f782d9c66c49 702 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 703 ip_addr_t ip_addr;
dkato 0:f782d9c66c49 704
dkato 0:f782d9c66c49 705 if ((s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) ||
dkato 0:f782d9c66c49 706 (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) {
dkato 0:f782d9c66c49 707 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 708 }
dkato 0:f782d9c66c49 709
dkato 0:f782d9c66c49 710 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
dkato 0:f782d9c66c49 711 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 712 }
dkato 0:f782d9c66c49 713
dkato 0:f782d9c66c49 714 err_t err = netconn_bind(s->conn, &ip_addr, port);
dkato 0:f782d9c66c49 715 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 716 }
dkato 0:f782d9c66c49 717
dkato 0:f782d9c66c49 718 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog)
dkato 0:f782d9c66c49 719 {
dkato 0:f782d9c66c49 720 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 721
dkato 0:f782d9c66c49 722 err_t err = netconn_listen_with_backlog(s->conn, backlog);
dkato 0:f782d9c66c49 723 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 724 }
dkato 0:f782d9c66c49 725
dkato 0:f782d9c66c49 726 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
dkato 0:f782d9c66c49 727 {
dkato 0:f782d9c66c49 728 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 729 ip_addr_t ip_addr;
dkato 0:f782d9c66c49 730
dkato 0:f782d9c66c49 731 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
dkato 0:f782d9c66c49 732 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 733 }
dkato 0:f782d9c66c49 734
dkato 0:f782d9c66c49 735 netconn_set_nonblocking(s->conn, false);
dkato 0:f782d9c66c49 736 err_t err = netconn_connect(s->conn, &ip_addr, port);
dkato 0:f782d9c66c49 737 netconn_set_nonblocking(s->conn, true);
dkato 0:f782d9c66c49 738
dkato 0:f782d9c66c49 739 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 740 }
dkato 0:f782d9c66c49 741
dkato 0:f782d9c66c49 742 static nsapi_error_t mbed_lwip_socket_accept(nsapi_stack_t *stack, nsapi_socket_t server, nsapi_socket_t *handle, nsapi_addr_t *addr, uint16_t *port)
dkato 0:f782d9c66c49 743 {
dkato 0:f782d9c66c49 744 struct lwip_socket *s = (struct lwip_socket *)server;
dkato 0:f782d9c66c49 745 struct lwip_socket *ns = mbed_lwip_arena_alloc();
dkato 0:f782d9c66c49 746 if (!ns) {
dkato 0:f782d9c66c49 747 return NSAPI_ERROR_NO_SOCKET;
dkato 0:f782d9c66c49 748 }
dkato 0:f782d9c66c49 749
dkato 0:f782d9c66c49 750 err_t err = netconn_accept(s->conn, &ns->conn);
dkato 0:f782d9c66c49 751 if (err != ERR_OK) {
dkato 0:f782d9c66c49 752 mbed_lwip_arena_dealloc(ns);
dkato 0:f782d9c66c49 753 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 754 }
dkato 0:f782d9c66c49 755
dkato 0:f782d9c66c49 756 netconn_set_recvtimeout(ns->conn, 1);
dkato 0:f782d9c66c49 757 *(struct lwip_socket **)handle = ns;
dkato 0:f782d9c66c49 758
dkato 0:f782d9c66c49 759 ip_addr_t peer_addr;
dkato 0:f782d9c66c49 760 (void) netconn_peer(ns->conn, &peer_addr, port);
dkato 0:f782d9c66c49 761 convert_lwip_addr_to_mbed(addr, &peer_addr);
dkato 0:f782d9c66c49 762
dkato 0:f782d9c66c49 763 netconn_set_nonblocking(ns->conn, true);
dkato 0:f782d9c66c49 764
dkato 0:f782d9c66c49 765 return 0;
dkato 0:f782d9c66c49 766 }
dkato 0:f782d9c66c49 767
dkato 0:f782d9c66c49 768 static nsapi_size_or_error_t mbed_lwip_socket_send(nsapi_stack_t *stack, nsapi_socket_t handle, const void *data, nsapi_size_t size)
dkato 0:f782d9c66c49 769 {
dkato 0:f782d9c66c49 770 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 771 size_t bytes_written = 0;
dkato 0:f782d9c66c49 772
dkato 0:f782d9c66c49 773 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written);
dkato 0:f782d9c66c49 774 if (err != ERR_OK) {
dkato 0:f782d9c66c49 775 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 776 }
dkato 0:f782d9c66c49 777
dkato 0:f782d9c66c49 778 return (nsapi_size_or_error_t)bytes_written;
dkato 0:f782d9c66c49 779 }
dkato 0:f782d9c66c49 780
dkato 0:f782d9c66c49 781 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size)
dkato 0:f782d9c66c49 782 {
dkato 0:f782d9c66c49 783 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 784
dkato 0:f782d9c66c49 785 if (!s->buf) {
dkato 0:f782d9c66c49 786 err_t err = netconn_recv(s->conn, &s->buf);
dkato 0:f782d9c66c49 787 s->offset = 0;
dkato 0:f782d9c66c49 788
dkato 0:f782d9c66c49 789 if (err != ERR_OK) {
dkato 0:f782d9c66c49 790 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 791 }
dkato 0:f782d9c66c49 792 }
dkato 0:f782d9c66c49 793
dkato 0:f782d9c66c49 794 u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset);
dkato 0:f782d9c66c49 795 s->offset += recv;
dkato 0:f782d9c66c49 796
dkato 0:f782d9c66c49 797 if (s->offset >= netbuf_len(s->buf)) {
dkato 0:f782d9c66c49 798 netbuf_delete(s->buf);
dkato 0:f782d9c66c49 799 s->buf = 0;
dkato 0:f782d9c66c49 800 }
dkato 0:f782d9c66c49 801
dkato 0:f782d9c66c49 802 return recv;
dkato 0:f782d9c66c49 803 }
dkato 0:f782d9c66c49 804
dkato 0:f782d9c66c49 805 static nsapi_size_or_error_t mbed_lwip_socket_sendto(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port, const void *data, nsapi_size_t size)
dkato 0:f782d9c66c49 806 {
dkato 0:f782d9c66c49 807 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 808 ip_addr_t ip_addr;
dkato 0:f782d9c66c49 809
dkato 0:f782d9c66c49 810 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
dkato 0:f782d9c66c49 811 return NSAPI_ERROR_PARAMETER;
dkato 0:f782d9c66c49 812 }
dkato 0:f782d9c66c49 813
dkato 0:f782d9c66c49 814 struct netbuf *buf = netbuf_new();
dkato 0:f782d9c66c49 815 err_t err = netbuf_ref(buf, data, (u16_t)size);
dkato 0:f782d9c66c49 816 if (err != ERR_OK) {
dkato 0:f782d9c66c49 817 netbuf_free(buf);
dkato 0:f782d9c66c49 818 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 819 }
dkato 0:f782d9c66c49 820
dkato 0:f782d9c66c49 821 err = netconn_sendto(s->conn, buf, &ip_addr, port);
dkato 0:f782d9c66c49 822 netbuf_delete(buf);
dkato 0:f782d9c66c49 823 if (err != ERR_OK) {
dkato 0:f782d9c66c49 824 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 825 }
dkato 0:f782d9c66c49 826
dkato 0:f782d9c66c49 827 return size;
dkato 0:f782d9c66c49 828 }
dkato 0:f782d9c66c49 829
dkato 0:f782d9c66c49 830 static nsapi_size_or_error_t mbed_lwip_socket_recvfrom(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t *addr, uint16_t *port, void *data, nsapi_size_t size)
dkato 0:f782d9c66c49 831 {
dkato 0:f782d9c66c49 832 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 833 struct netbuf *buf;
dkato 0:f782d9c66c49 834
dkato 0:f782d9c66c49 835 err_t err = netconn_recv(s->conn, &buf);
dkato 0:f782d9c66c49 836 if (err != ERR_OK) {
dkato 0:f782d9c66c49 837 return mbed_lwip_err_remap(err);
dkato 0:f782d9c66c49 838 }
dkato 0:f782d9c66c49 839
dkato 0:f782d9c66c49 840 convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf));
dkato 0:f782d9c66c49 841 *port = netbuf_fromport(buf);
dkato 0:f782d9c66c49 842
dkato 0:f782d9c66c49 843 u16_t recv = netbuf_copy(buf, data, (u16_t)size);
dkato 0:f782d9c66c49 844 netbuf_delete(buf);
dkato 0:f782d9c66c49 845
dkato 0:f782d9c66c49 846 return recv;
dkato 0:f782d9c66c49 847 }
dkato 0:f782d9c66c49 848
dkato 0:f782d9c66c49 849 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
dkato 0:f782d9c66c49 850 {
dkato 0:f782d9c66c49 851 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 852
dkato 0:f782d9c66c49 853 switch (optname) {
dkato 0:f782d9c66c49 854 case NSAPI_KEEPALIVE:
dkato 0:f782d9c66c49 855 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
dkato 0:f782d9c66c49 856 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:f782d9c66c49 857 }
dkato 0:f782d9c66c49 858
dkato 0:f782d9c66c49 859 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE;
dkato 0:f782d9c66c49 860 return 0;
dkato 0:f782d9c66c49 861
dkato 0:f782d9c66c49 862 case NSAPI_KEEPIDLE:
dkato 0:f782d9c66c49 863 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
dkato 0:f782d9c66c49 864 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:f782d9c66c49 865 }
dkato 0:f782d9c66c49 866
dkato 0:f782d9c66c49 867 s->conn->pcb.tcp->keep_idle = *(int*)optval;
dkato 0:f782d9c66c49 868 return 0;
dkato 0:f782d9c66c49 869
dkato 0:f782d9c66c49 870 case NSAPI_KEEPINTVL:
dkato 0:f782d9c66c49 871 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
dkato 0:f782d9c66c49 872 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:f782d9c66c49 873 }
dkato 0:f782d9c66c49 874
dkato 0:f782d9c66c49 875 s->conn->pcb.tcp->keep_intvl = *(int*)optval;
dkato 0:f782d9c66c49 876 return 0;
dkato 0:f782d9c66c49 877
dkato 0:f782d9c66c49 878 case NSAPI_REUSEADDR:
dkato 0:f782d9c66c49 879 if (optlen != sizeof(int)) {
dkato 0:f782d9c66c49 880 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:f782d9c66c49 881 }
dkato 0:f782d9c66c49 882
dkato 0:f782d9c66c49 883 if (*(int *)optval) {
dkato 0:f782d9c66c49 884 s->conn->pcb.tcp->so_options |= SOF_REUSEADDR;
dkato 0:f782d9c66c49 885 } else {
dkato 0:f782d9c66c49 886 s->conn->pcb.tcp->so_options &= ~SOF_REUSEADDR;
dkato 0:f782d9c66c49 887 }
dkato 0:f782d9c66c49 888 return 0;
dkato 0:f782d9c66c49 889
dkato 0:f782d9c66c49 890 default:
dkato 0:f782d9c66c49 891 return NSAPI_ERROR_UNSUPPORTED;
dkato 0:f782d9c66c49 892 }
dkato 0:f782d9c66c49 893 }
dkato 0:f782d9c66c49 894
dkato 0:f782d9c66c49 895 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data)
dkato 0:f782d9c66c49 896 {
dkato 0:f782d9c66c49 897 struct lwip_socket *s = (struct lwip_socket *)handle;
dkato 0:f782d9c66c49 898
dkato 0:f782d9c66c49 899 s->cb = callback;
dkato 0:f782d9c66c49 900 s->data = data;
dkato 0:f782d9c66c49 901 }
dkato 0:f782d9c66c49 902
dkato 0:f782d9c66c49 903 /* LWIP network stack */
dkato 0:f782d9c66c49 904 const nsapi_stack_api_t lwip_stack_api = {
dkato 0:f782d9c66c49 905 .gethostbyname = mbed_lwip_gethostbyname,
dkato 0:f782d9c66c49 906 .add_dns_server = mbed_lwip_add_dns_server,
dkato 0:f782d9c66c49 907 .socket_open = mbed_lwip_socket_open,
dkato 0:f782d9c66c49 908 .socket_close = mbed_lwip_socket_close,
dkato 0:f782d9c66c49 909 .socket_bind = mbed_lwip_socket_bind,
dkato 0:f782d9c66c49 910 .socket_listen = mbed_lwip_socket_listen,
dkato 0:f782d9c66c49 911 .socket_connect = mbed_lwip_socket_connect,
dkato 0:f782d9c66c49 912 .socket_accept = mbed_lwip_socket_accept,
dkato 0:f782d9c66c49 913 .socket_send = mbed_lwip_socket_send,
dkato 0:f782d9c66c49 914 .socket_recv = mbed_lwip_socket_recv,
dkato 0:f782d9c66c49 915 .socket_sendto = mbed_lwip_socket_sendto,
dkato 0:f782d9c66c49 916 .socket_recvfrom = mbed_lwip_socket_recvfrom,
dkato 0:f782d9c66c49 917 .setsockopt = mbed_lwip_setsockopt,
dkato 0:f782d9c66c49 918 .socket_attach = mbed_lwip_socket_attach,
dkato 0:f782d9c66c49 919 };
dkato 0:f782d9c66c49 920
dkato 0:f782d9c66c49 921 nsapi_stack_t lwip_stack = {
dkato 0:f782d9c66c49 922 .stack_api = &lwip_stack_api,
dkato 0:f782d9c66c49 923 };