LWIPBP3595Interface library for mbed-os.

Dependents:   LWIPBP3595Interface_STA_for_mbed-os

Fork of LWIPBP3595Interface by Rohm

Committer:
dkato
Date:
Thu Oct 27 09:30:15 2016 +0000
Revision:
3:2ff2514e4fca
Parent:
2:c7e325599570
Child:
5:d03489ec5033
Supports mbed os 5.2.

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