LWIPBP3595Interface library for mbed-os.

Dependents:   LWIPBP3595Interface_STA_for_mbed-os

Fork of LWIPBP3595Interface by Rohm

Committer:
dkato
Date:
Tue Mar 28 09:50:17 2017 +0000
Revision:
6:993197aaf5a4
Parent:
5:d03489ec5033
Fixed static IP address setting.

Who changed what in which revision?

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