LWIPBP3595Interface library for mbed-os.

Dependents:   LWIPBP3595Interface_STA_for_mbed-os

Fork of LWIPBP3595Interface by Rohm

Committer:
dkato
Date:
Thu Nov 24 09:13:23 2016 +0000
Revision:
5:d03489ec5033
Parent:
3:2ff2514e4fca
Child:
6:993197aaf5a4
Supports mbed os 5.2.3.

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