/* * 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 #include #include "py/mphal.h" #include "shared/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", (int)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); } }