diff options
Diffstat (limited to 'drivers/cyw43/cyw43_lwip.c')
| -rw-r--r-- | drivers/cyw43/cyw43_lwip.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/drivers/cyw43/cyw43_lwip.c b/drivers/cyw43/cyw43_lwip.c new file mode 100644 index 000000000..8f4223029 --- /dev/null +++ b/drivers/cyw43/cyw43_lwip.c @@ -0,0 +1,197 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "py/mphal.h" +#include "lib/netutils/netutils.h" +#include "lwip/etharp.h" +#include "lwip/dns.h" +#include "lwip/apps/mdns.h" +#include "drivers/cyw43/cyw43.h" + +STATIC void cyw43_ethernet_trace(cyw43_t *self, struct netif *netif, size_t len, const void *data, unsigned int flags) { + bool is_tx = flags & NETUTILS_TRACE_IS_TX; + if ((is_tx && (self->trace_flags & CYW43_TRACE_ETH_TX)) + || (!is_tx && (self->trace_flags & CYW43_TRACE_ETH_RX))) { + const uint8_t *buf; + if (len == (size_t)-1) { + // data is a pbuf + const struct pbuf *pbuf = data; + buf = pbuf->payload; + len = pbuf->len; // restricted to print only the first chunk of the pbuf + } else { + // data is actual data buffer + buf = data; + } + + if (self->trace_flags & CYW43_TRACE_MAC) { + printf("[% 8d] ETH%cX itf=%c%c len=%u", mp_hal_ticks_ms(), is_tx ? 'T' : 'R', netif->name[0], netif->name[1], len); + printf(" MAC type=%d subtype=%d data=", buf[0] >> 2 & 3, buf[0] >> 4); + for (size_t i = 0; i < len; ++i) { + printf(" %02x", buf[i]); + } + printf("\n"); + return; + } + + if (self->trace_flags & CYW43_TRACE_ETH_FULL) { + flags |= NETUTILS_TRACE_PAYLOAD; + } + netutils_ethernet_trace(MP_PYTHON_PRINTER, len, buf, flags); + } +} + +STATIC err_t cyw43_netif_output(struct netif *netif, struct pbuf *p) { + cyw43_t *self = netif->state; + if (self->trace_flags != 0) { + cyw43_ethernet_trace(self, netif, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE); + } + int itf = netif->name[1] - '0'; + int ret = cyw43_send_ethernet(self, itf, p->tot_len, (void*)p, true); + if (ret) { + printf("[CYW43] send_ethernet failed: %d\n", ret); + return ERR_IF; + } + return ERR_OK; +} + +STATIC err_t cyw43_netif_init(struct netif *netif) { + netif->linkoutput = cyw43_netif_output; + netif->output = etharp_output; + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; + cyw43_wifi_get_mac(netif->state, netif->name[1] - '0', netif->hwaddr); + netif->hwaddr_len = sizeof(netif->hwaddr); + return ERR_OK; +} + +void cyw43_tcpip_init(cyw43_t *self, int itf) { + ip_addr_t ipconfig[4]; + #if LWIP_IPV6 + #define IP(x) ((x).u_addr.ip4) + #else + #define IP(x) (x) + #endif + if (itf == 0) { + // need to zero out to get isconnected() working + IP4_ADDR(&IP(ipconfig[0]), 0, 0, 0, 0); + IP4_ADDR(&IP(ipconfig[2]), 192, 168, 0, 1); + } else { + IP4_ADDR(&IP(ipconfig[0]), 192, 168, 4, 1); + IP4_ADDR(&IP(ipconfig[2]), 192, 168, 4, 1); + } + IP4_ADDR(&IP(ipconfig[1]), 255, 255, 255, 0); + IP4_ADDR(&IP(ipconfig[3]), 8, 8, 8, 8); + #undef IP + + struct netif *n = &self->netif[itf]; + n->name[0] = 'w'; + n->name[1] = '0' + itf; + #if LWIP_IPV6 + netif_add(n, &ipconfig[0].u_addr.ip4, &ipconfig[1].u_addr.ip4, &ipconfig[2].u_addr.ip4, self, cyw43_netif_init, ethernet_input); + #else + netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, cyw43_netif_init, netif_input); + #endif + netif_set_hostname(n, "PYBD"); + netif_set_default(n); + netif_set_up(n); + + if (itf == CYW43_ITF_STA) { + dns_setserver(0, &ipconfig[3]); + dhcp_set_struct(n, &self->dhcp_client); + dhcp_start(n); + } else { + dhcp_server_init(&self->dhcp_server, &ipconfig[0], &ipconfig[1]); + } + + #if LWIP_MDNS_RESPONDER + // TODO better to call after IP address is set + char mdns_hostname[9]; + memcpy(&mdns_hostname[0], "PYBD", 4); + mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, &mdns_hostname[4]); + mdns_hostname[8] = '\0'; + mdns_resp_add_netif(n, mdns_hostname, 60); + #endif +} + +void cyw43_tcpip_deinit(cyw43_t *self, int itf) { + struct netif *n = &self->netif[itf]; + if (itf == CYW43_ITF_STA) { + dhcp_stop(n); + } else { + dhcp_server_deinit(&self->dhcp_server); + } + #if LWIP_MDNS_RESPONDER + mdns_resp_remove_netif(n); + #endif + for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { + if (netif == n) { + netif_remove(netif); + netif->ip_addr.addr = 0; + netif->flags = 0; + } + } +} + +void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) { + cyw43_t *self = cb_data; + struct netif *netif = &self->netif[itf]; + if (self->trace_flags) { + cyw43_ethernet_trace(self, netif, len, buf, NETUTILS_TRACE_NEWLINE); + } + if (netif->flags & NETIF_FLAG_LINK_UP) { + struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != NULL) { + pbuf_take(p, buf, len); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } + } +} + +void cyw43_tcpip_set_link_up(cyw43_t *self, int itf) { + netif_set_link_up(&self->netif[itf]); +} + +void cyw43_tcpip_set_link_down(cyw43_t *self, int itf) { + netif_set_link_down(&self->netif[itf]); +} + +int cyw43_tcpip_link_status(cyw43_t *self, int itf) { + struct netif *netif = &self->netif[itf]; + if ((netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) + == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) { + if (netif->ip_addr.addr != 0) { + return CYW43_LINK_UP; + } else { + return CYW43_LINK_NOIP; + } + } else { + return cyw43_wifi_link_status(self, itf); + } +} |
