Damien George
6 years ago
6 changed files with 1072 additions and 0 deletions
@ -0,0 +1,17 @@ |
|||||
|
CYW43xx WiFi SoC driver |
||||
|
======================= |
||||
|
|
||||
|
This is a driver for the CYW43xx WiFi SoC. |
||||
|
|
||||
|
There are four layers to the driver: |
||||
|
|
||||
|
1. SDIO bus interface, provided by the host device/system. |
||||
|
|
||||
|
2. Low-level CYW43xx interface, managing the bus, control messages, Ethernet |
||||
|
frames and asynchronous events. Includes download of SoC firmware. The |
||||
|
header file `cyw43_ll.h` defines the interface to this layer. |
||||
|
|
||||
|
3. Mid-level CYW43xx control, to control and set WiFi parameters and manage |
||||
|
events. See `cyw43_ctrl.c`. |
||||
|
|
||||
|
4. TCP/IP bindings to lwIP. See `cyw43_lwip.c`. |
@ -0,0 +1,135 @@ |
|||||
|
/*
|
||||
|
* 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. |
||||
|
*/ |
||||
|
#ifndef MICROPY_INCLUDED_STM32_CYW43_H |
||||
|
#define MICROPY_INCLUDED_STM32_CYW43_H |
||||
|
|
||||
|
#include "lwip/netif.h" |
||||
|
#include "lwip/dhcp.h" |
||||
|
#include "lib/netutils/dhcpserver.h" |
||||
|
#include "drivers/cyw43/cyw43_ll.h" |
||||
|
|
||||
|
// For trace_flags
|
||||
|
#define CYW43_TRACE_ASYNC_EV (0x0001) |
||||
|
#define CYW43_TRACE_ETH_TX (0x0002) |
||||
|
#define CYW43_TRACE_ETH_RX (0x0004) |
||||
|
#define CYW43_TRACE_ETH_FULL (0x0008) |
||||
|
#define CYW43_TRACE_MAC (0x0010) |
||||
|
|
||||
|
// Return value of cyw43_wifi_link_status
|
||||
|
#define CYW43_LINK_DOWN (0) |
||||
|
#define CYW43_LINK_JOIN (1) |
||||
|
#define CYW43_LINK_NOIP (2) |
||||
|
#define CYW43_LINK_UP (3) |
||||
|
#define CYW43_LINK_FAIL (-1) |
||||
|
#define CYW43_LINK_NONET (-2) |
||||
|
#define CYW43_LINK_BADAUTH (-3) |
||||
|
|
||||
|
typedef struct _cyw43_t { |
||||
|
cyw43_ll_t cyw43_ll; |
||||
|
|
||||
|
uint8_t itf_state; |
||||
|
uint32_t trace_flags; |
||||
|
|
||||
|
// State for async events
|
||||
|
volatile uint32_t wifi_scan_state; |
||||
|
uint32_t wifi_join_state; |
||||
|
void *wifi_scan_env; |
||||
|
int (*wifi_scan_cb)(void*, const cyw43_ev_scan_result_t*); |
||||
|
|
||||
|
// Pending things to do
|
||||
|
bool pend_disassoc; |
||||
|
bool pend_rejoin; |
||||
|
bool pend_rejoin_wpa; |
||||
|
|
||||
|
// AP settings
|
||||
|
uint8_t ap_channel; |
||||
|
uint8_t ap_auth; |
||||
|
uint8_t ap_ssid_len; |
||||
|
uint8_t ap_key_len; |
||||
|
uint8_t ap_ssid[32]; |
||||
|
uint8_t ap_key[64]; |
||||
|
|
||||
|
// lwIP data
|
||||
|
struct netif netif[2]; |
||||
|
struct dhcp dhcp_client; |
||||
|
dhcp_server_t dhcp_server; |
||||
|
} cyw43_t; |
||||
|
|
||||
|
extern cyw43_t cyw43_state; |
||||
|
extern void (*cyw43_poll)(void); |
||||
|
extern uint32_t cyw43_sleep; |
||||
|
|
||||
|
void cyw43_init(cyw43_t *self); |
||||
|
void cyw43_deinit(cyw43_t *self); |
||||
|
|
||||
|
int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface); |
||||
|
int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf); |
||||
|
|
||||
|
int cyw43_wifi_pm(cyw43_t *self, uint32_t pm); |
||||
|
int cyw43_wifi_link_status(cyw43_t *self, int itf); |
||||
|
void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up); |
||||
|
int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]); |
||||
|
int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)); |
||||
|
|
||||
|
static inline bool cyw43_wifi_scan_active(cyw43_t *self) { |
||||
|
return self->wifi_scan_state == 1; |
||||
|
} |
||||
|
|
||||
|
int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel); |
||||
|
int cyw43_wifi_leave(cyw43_t *self, int itf); |
||||
|
|
||||
|
static inline void cyw43_wifi_ap_get_ssid(cyw43_t *self, size_t *len, const uint8_t **buf) { |
||||
|
*len = self->ap_ssid_len; |
||||
|
*buf = self->ap_ssid; |
||||
|
} |
||||
|
|
||||
|
static inline void cyw43_wifi_ap_set_channel(cyw43_t *self, uint32_t channel) { |
||||
|
self->ap_channel = channel; |
||||
|
} |
||||
|
|
||||
|
static inline void cyw43_wifi_ap_set_ssid(cyw43_t *self, size_t len, const uint8_t *buf) { |
||||
|
self->ap_ssid_len = MIN(len, sizeof(self->ap_ssid)); |
||||
|
memcpy(self->ap_ssid, buf, self->ap_ssid_len); |
||||
|
} |
||||
|
|
||||
|
static inline void cyw43_wifi_ap_set_password(cyw43_t *self, size_t len, const uint8_t *buf) { |
||||
|
self->ap_key_len = MIN(len, sizeof(self->ap_key)); |
||||
|
memcpy(self->ap_key, buf, self->ap_key_len); |
||||
|
} |
||||
|
|
||||
|
static inline void cyw43_wifi_ap_set_auth(cyw43_t *self, uint32_t auth) { |
||||
|
self->ap_auth = auth; |
||||
|
} |
||||
|
|
||||
|
void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs); |
||||
|
|
||||
|
void cyw43_tcpip_init(cyw43_t *self, int itf); |
||||
|
void cyw43_tcpip_deinit(cyw43_t *self, int itf); |
||||
|
void cyw43_tcpip_set_link_up(cyw43_t *self, int itf); |
||||
|
void cyw43_tcpip_set_link_down(cyw43_t *self, int itf); |
||||
|
int cyw43_tcpip_link_status(cyw43_t *self, int itf); |
||||
|
|
||||
|
#endif // MICROPY_INCLUDED_STM32_CYW43_H
|
@ -0,0 +1,588 @@ |
|||||
|
/*
|
||||
|
* 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 "drivers/cyw43/cyw43.h" |
||||
|
#include "pendsv.h" |
||||
|
#include "sdio.h" |
||||
|
|
||||
|
#define CYW_ENTER MICROPY_PY_LWIP_ENTER |
||||
|
#define CYW_EXIT MICROPY_PY_LWIP_EXIT |
||||
|
|
||||
|
#ifdef pyb_pin_WL_HOST_WAKE |
||||
|
#define USE_SDIOIT (0) |
||||
|
#else |
||||
|
#define USE_SDIOIT (1) |
||||
|
#endif |
||||
|
|
||||
|
#define CYW43_SLEEP_MAX (50) |
||||
|
|
||||
|
#define WIFI_JOIN_STATE_ACTIVE (0x0001) |
||||
|
#define WIFI_JOIN_STATE_FAIL (0x0002) |
||||
|
#define WIFI_JOIN_STATE_NONET (0x0003) |
||||
|
#define WIFI_JOIN_STATE_BADAUTH (0x0004) |
||||
|
#define WIFI_JOIN_STATE_AUTH (0x0200) |
||||
|
#define WIFI_JOIN_STATE_LINK (0x0400) |
||||
|
#define WIFI_JOIN_STATE_KEYED (0x0800) |
||||
|
#define WIFI_JOIN_STATE_ALL (0x0e01) |
||||
|
|
||||
|
cyw43_t cyw43_state; |
||||
|
void (*cyw43_poll)(void); |
||||
|
uint32_t cyw43_sleep; |
||||
|
|
||||
|
STATIC void cyw43_poll_func(void); |
||||
|
STATIC void cyw43_wifi_ap_init(cyw43_t *self); |
||||
|
STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up); |
||||
|
|
||||
|
static inline uint32_t cyw43_get_be16(const uint8_t *buf) { |
||||
|
return buf[0] << 8 | buf[1]; |
||||
|
} |
||||
|
|
||||
|
static inline uint32_t cyw43_get_be32(const uint8_t *buf) { |
||||
|
return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; |
||||
|
} |
||||
|
|
||||
|
static inline void cyw43_delay_ms(uint32_t ms) { |
||||
|
mp_hal_delay_ms(ms); |
||||
|
} |
||||
|
|
||||
|
/*******************************************************************************/ |
||||
|
// Initialisation and polling
|
||||
|
|
||||
|
void cyw43_init(cyw43_t *self) { |
||||
|
#ifdef pyb_pin_WL_HOST_WAKE |
||||
|
mp_hal_pin_config(pyb_pin_WL_HOST_WAKE, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); |
||||
|
#endif |
||||
|
mp_hal_pin_config(pyb_pin_WL_REG_ON, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); |
||||
|
mp_hal_pin_low(pyb_pin_WL_REG_ON); |
||||
|
#ifdef pyb_pin_WL_RFSW_VDD |
||||
|
mp_hal_pin_config(pyb_pin_WL_RFSW_VDD, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power
|
||||
|
mp_hal_pin_low(pyb_pin_WL_RFSW_VDD); |
||||
|
#endif |
||||
|
|
||||
|
cyw43_ll_init(&self->cyw43_ll, self); |
||||
|
|
||||
|
self->itf_state = 0; |
||||
|
self->wifi_scan_state = 0; |
||||
|
self->wifi_join_state = 0; |
||||
|
self->pend_disassoc = false; |
||||
|
self->pend_rejoin= false; |
||||
|
self->pend_rejoin_wpa = false; |
||||
|
self->ap_channel = 3; |
||||
|
self->ap_ssid_len = 0; |
||||
|
self->ap_key_len = 0; |
||||
|
|
||||
|
cyw43_poll = NULL; |
||||
|
} |
||||
|
|
||||
|
void cyw43_deinit(cyw43_t *self) { |
||||
|
CYW_ENTER |
||||
|
|
||||
|
cyw43_ll_bus_sleep(&self->cyw43_ll, true); |
||||
|
cyw43_delay_ms(2); |
||||
|
cyw43_tcpip_deinit(self, 0); |
||||
|
cyw43_tcpip_deinit(self, 1); |
||||
|
|
||||
|
self->itf_state = 0; |
||||
|
|
||||
|
// Disable async polling
|
||||
|
SDMMC1->MASK &= ~SDMMC_MASK_SDIOITIE; |
||||
|
cyw43_poll = NULL; |
||||
|
|
||||
|
#ifdef pyb_pin_WL_RFSW_VDD |
||||
|
// Turn the RF-switch off
|
||||
|
mp_hal_pin_low(pyb_pin_WL_RFSW_VDD); |
||||
|
#endif |
||||
|
|
||||
|
// Power down the WL chip and the SDIO bus
|
||||
|
mp_hal_pin_low(pyb_pin_WL_REG_ON); |
||||
|
sdio_deinit(); |
||||
|
|
||||
|
CYW_EXIT |
||||
|
} |
||||
|
|
||||
|
STATIC int cyw43_ensure_up(cyw43_t *self) { |
||||
|
if (cyw43_poll != NULL) { |
||||
|
cyw43_ll_bus_sleep(&self->cyw43_ll, false); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
CYW_ENTER |
||||
|
|
||||
|
// Disable the netif if it was previously up
|
||||
|
cyw43_tcpip_deinit(self, CYW43_ITF_STA); |
||||
|
cyw43_tcpip_deinit(self, CYW43_ITF_AP); |
||||
|
self->itf_state = 0; |
||||
|
|
||||
|
// Reset and power up the WL chip
|
||||
|
mp_hal_pin_low(pyb_pin_WL_REG_ON); |
||||
|
cyw43_delay_ms(20); |
||||
|
mp_hal_pin_high(pyb_pin_WL_REG_ON); |
||||
|
cyw43_delay_ms(50); |
||||
|
|
||||
|
// Initialise SDIO bus
|
||||
|
// IRQ priority only needs to be higher than CYW_ENTER/EXIT protection (PENDSV)
|
||||
|
sdio_init(NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0)); |
||||
|
|
||||
|
// Initialise the low-level driver
|
||||
|
uint8_t mac[6]; |
||||
|
mp_hal_get_mac(MP_HAL_MAC_WLAN0, mac); |
||||
|
int ret = cyw43_ll_bus_init(&self->cyw43_ll, mac); |
||||
|
|
||||
|
if (ret != 0) { |
||||
|
CYW_EXIT |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
// Enable async events from low-level driver
|
||||
|
cyw43_sleep = CYW43_SLEEP_MAX; |
||||
|
cyw43_poll = cyw43_poll_func; |
||||
|
#if USE_SDIOIT |
||||
|
SDMMC1->MASK |= SDMMC_MASK_SDIOITIE; |
||||
|
#else |
||||
|
extern void extint_set(const pin_obj_t *pin, uint32_t mode); |
||||
|
extint_set(pyb_pin_WL_HOST_WAKE, GPIO_MODE_IT_FALLING); |
||||
|
#endif |
||||
|
|
||||
|
CYW_EXIT |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
// This function must always be executed at the level where CYW_ENTER is effectively active
|
||||
|
STATIC void cyw43_poll_func(void) { |
||||
|
if (cyw43_poll == NULL) { |
||||
|
// Poll scheduled during deinit, just ignore it
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
cyw43_t *self = &cyw43_state; |
||||
|
cyw43_ll_process_packets(&self->cyw43_ll); |
||||
|
|
||||
|
if (self->pend_disassoc) { |
||||
|
self->pend_disassoc = false; |
||||
|
cyw43_ll_ioctl(&self->cyw43_ll, CYW43_IOCTL_SET_DISASSOC, 0, NULL, CYW43_ITF_STA); |
||||
|
} |
||||
|
|
||||
|
if (self->pend_rejoin_wpa) { |
||||
|
self->pend_rejoin_wpa = false; |
||||
|
cyw43_ll_wifi_set_wpa_auth(&self->cyw43_ll); |
||||
|
} |
||||
|
|
||||
|
if (self->pend_rejoin) { |
||||
|
self->pend_rejoin = false; |
||||
|
cyw43_ll_wifi_rejoin(&self->cyw43_ll); |
||||
|
self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; |
||||
|
} |
||||
|
|
||||
|
if (cyw43_sleep == 0) { |
||||
|
cyw43_ll_bus_sleep(&self->cyw43_ll, true); |
||||
|
#if !USE_SDIOIT |
||||
|
sdio_deinit(); // save power while WLAN bus sleeps
|
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
#if USE_SDIOIT |
||||
|
SDMMC1->MASK |= SDMMC_MASK_SDIOITIE; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
/*******************************************************************************/ |
||||
|
// Callback interface to low-level driver
|
||||
|
|
||||
|
int cyw43_cb_read_host_interrupt_pin(void *cb_data) { |
||||
|
#ifdef pyb_pin_WL_HOST_WAKE |
||||
|
return mp_hal_pin_read(pyb_pin_WL_HOST_WAKE); |
||||
|
#else |
||||
|
return mp_hal_pin_read(pyb_pin_WL_SDIO_1); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
void cyw43_cb_ensure_awake(void *cb_data) { |
||||
|
cyw43_sleep = CYW43_SLEEP_MAX; |
||||
|
#if !USE_SDIOIT |
||||
|
if (__HAL_RCC_SDMMC1_IS_CLK_DISABLED()) { |
||||
|
__HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral
|
||||
|
sdio_enable_high_speed_4bit(); |
||||
|
} |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
STATIC const char *cyw43_async_event_name_table[89] = { |
||||
|
[0 ... 88] = NULL, |
||||
|
[CYW43_EV_SET_SSID] = "SET_SSID", |
||||
|
[CYW43_EV_JOIN] = "JOIN", |
||||
|
[CYW43_EV_AUTH] = "AUTH", |
||||
|
[CYW43_EV_DEAUTH_IND] = "DEAUTH_IND", |
||||
|
[CYW43_EV_ASSOC] = "ASSOC", |
||||
|
[CYW43_EV_DISASSOC] = "DISASSOC", |
||||
|
[CYW43_EV_DISASSOC_IND] = "DISASSOC_IND", |
||||
|
[CYW43_EV_LINK] = "LINK", |
||||
|
[CYW43_EV_PSK_SUP] = "PSK_SUP", |
||||
|
[CYW43_EV_ESCAN_RESULT] = "ESCAN_RESULT", |
||||
|
[CYW43_EV_CSA_COMPLETE_IND] = "CSA_COMPLETE_IND", |
||||
|
[CYW43_EV_ASSOC_REQ_IE] = "ASSOC_REQ_IE", |
||||
|
[CYW43_EV_ASSOC_RESP_IE] = "ASSOC_RESP_IE", |
||||
|
}; |
||||
|
|
||||
|
STATIC void cyw43_dump_async_event(const cyw43_async_event_t *ev) { |
||||
|
printf("[% 8d] ASYNC(%04x,", |
||||
|
mp_hal_ticks_ms(), |
||||
|
(unsigned int)ev->flags |
||||
|
); |
||||
|
if (ev->event_type < MP_ARRAY_SIZE(cyw43_async_event_name_table) |
||||
|
&& cyw43_async_event_name_table[ev->event_type] != NULL) { |
||||
|
printf("%s", cyw43_async_event_name_table[ev->event_type]); |
||||
|
} else { |
||||
|
printf("%u", (unsigned int)ev->event_type); |
||||
|
} |
||||
|
printf(",%u,%u,%u)\n", |
||||
|
(unsigned int)ev->status, |
||||
|
(unsigned int)ev->reason, |
||||
|
(unsigned int)ev->interface |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev) { |
||||
|
cyw43_t *self = cb_data; |
||||
|
|
||||
|
if (self->trace_flags & CYW43_TRACE_ASYNC_EV) { |
||||
|
cyw43_dump_async_event(ev); |
||||
|
} |
||||
|
|
||||
|
if (ev->event_type == CYW43_EV_ESCAN_RESULT && self->wifi_scan_state == 1) { |
||||
|
// Escan result event
|
||||
|
if (ev->status == 8) { |
||||
|
// Partial result
|
||||
|
int ret = self->wifi_scan_cb(self->wifi_scan_env, &ev->u.scan_result); |
||||
|
if (ret != 0) { |
||||
|
// TODO need to abort scan, or just ignore any more results
|
||||
|
} |
||||
|
} else if (ev->status == 0) { |
||||
|
// Scan complete
|
||||
|
self->wifi_scan_state = 2; |
||||
|
} |
||||
|
|
||||
|
} else if (ev->event_type == CYW43_EV_DISASSOC) { |
||||
|
cyw43_tcpip_set_link_down(self, CYW43_ITF_STA); |
||||
|
self->wifi_join_state = 0x0000; |
||||
|
|
||||
|
/*
|
||||
|
} else if (ev->event_type == CYW43_EV_DISASSOC_IND) { |
||||
|
if (ev->interface == CYW43_ITF_AP) { |
||||
|
// Station disassociated with our AP, let DHCP server know so it can free the IP address
|
||||
|
dhcp_server_disassoc(&self->dhcp_server, buf + 24); |
||||
|
} |
||||
|
*/ |
||||
|
|
||||
|
// WiFi join events
|
||||
|
} else if (ev->event_type == CYW43_EV_PRUNE) { |
||||
|
if (ev->status == 0 && ev->reason == 8) { |
||||
|
// RSN mismatch, retry join with WPA auth
|
||||
|
self->pend_rejoin = true; |
||||
|
self->pend_rejoin_wpa = true; |
||||
|
pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); |
||||
|
} |
||||
|
} else if (ev->event_type == CYW43_EV_SET_SSID) { |
||||
|
if (ev->status == 0) { |
||||
|
// Success setting SSID
|
||||
|
} else if (ev->status == 3 && ev->reason == 0) { |
||||
|
self->wifi_join_state = WIFI_JOIN_STATE_NONET; |
||||
|
// No matching SSID found (could be out of range, or down)
|
||||
|
} else { |
||||
|
// Other failure setting SSID
|
||||
|
self->wifi_join_state = WIFI_JOIN_STATE_FAIL; |
||||
|
} |
||||
|
} else if (ev->event_type == CYW43_EV_AUTH) { |
||||
|
if (ev->status == 0) { |
||||
|
self->wifi_join_state |= WIFI_JOIN_STATE_AUTH; |
||||
|
} else if (ev->status == 6) { |
||||
|
// Unsolicited auth packet, ignore it
|
||||
|
} else { |
||||
|
// Cannot authenticate
|
||||
|
self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH; |
||||
|
} |
||||
|
} else if (ev->event_type == CYW43_EV_DEAUTH_IND) { |
||||
|
if (ev->status == 0 && ev->reason == 2) { |
||||
|
// Deauth, probably because password was wrong; disassociate
|
||||
|
self->pend_disassoc = true; |
||||
|
pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); |
||||
|
} |
||||
|
} else if (ev->event_type == CYW43_EV_LINK) { |
||||
|
if (ev->status == 0) { |
||||
|
if (ev->flags & 1) { |
||||
|
// Link is up
|
||||
|
if (ev->interface == CYW43_ITF_STA) { |
||||
|
self->wifi_join_state |= WIFI_JOIN_STATE_LINK; |
||||
|
} else { |
||||
|
cyw43_tcpip_set_link_up(self, ev->interface); |
||||
|
} |
||||
|
} else { |
||||
|
// Link is down
|
||||
|
cyw43_tcpip_set_link_down(self, ev->interface); |
||||
|
} |
||||
|
} |
||||
|
} else if (ev->event_type == CYW43_EV_PSK_SUP) { |
||||
|
if (ev->status == 6) { // WLC_SUP_KEYED
|
||||
|
self->wifi_join_state |= WIFI_JOIN_STATE_KEYED; |
||||
|
} else if ((ev->status == 4 || ev->status == 8 || ev->status == 11) && ev->reason == 15) { |
||||
|
// Timeout waiting for key exchange M1/M3/G1
|
||||
|
// Probably at edge of the cell, retry
|
||||
|
self->pend_rejoin = true; |
||||
|
pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); |
||||
|
} else { |
||||
|
// PSK_SUP failure
|
||||
|
self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (self->wifi_join_state == WIFI_JOIN_STATE_ALL) { |
||||
|
// STA connected
|
||||
|
self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; |
||||
|
cyw43_tcpip_set_link_up(self, CYW43_ITF_STA); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*******************************************************************************/ |
||||
|
// Ioctl and Ethernet interface
|
||||
|
|
||||
|
int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
CYW_ENTER |
||||
|
ret = cyw43_ll_ioctl(&self->cyw43_ll, cmd, len, buf, iface); |
||||
|
CYW_EXIT |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
CYW_ENTER |
||||
|
ret = cyw43_ll_send_ethernet(&self->cyw43_ll, itf, len, buf, is_pbuf); |
||||
|
CYW_EXIT |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/*******************************************************************************/ |
||||
|
// WiFi control
|
||||
|
|
||||
|
STATIC int cyw43_wifi_on(cyw43_t *self, uint32_t country) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
#ifdef pyb_pin_WL_RFSW_VDD |
||||
|
// Turn the RF-switch on
|
||||
|
mp_hal_pin_high(pyb_pin_WL_RFSW_VDD); |
||||
|
#endif |
||||
|
|
||||
|
CYW_ENTER |
||||
|
ret = cyw43_ll_wifi_on(&self->cyw43_ll, country); |
||||
|
CYW_EXIT |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int cyw43_wifi_pm(cyw43_t *self, uint32_t pm_in) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
// pm_in: 0x00adbrrm
|
||||
|
uint32_t pm = pm_in & 0xf; |
||||
|
uint32_t pm_sleep_ret = (pm_in >> 4) & 0xff; |
||||
|
uint32_t li_bcn = (pm_in >> 12) & 0xf; |
||||
|
uint32_t li_dtim = (pm_in >> 16) & 0xf; |
||||
|
uint32_t li_assoc = (pm_in >> 20) & 0xf; |
||||
|
|
||||
|
CYW_ENTER |
||||
|
ret = cyw43_ll_wifi_pm(&self->cyw43_ll, pm, pm_sleep_ret, li_bcn, li_dtim, li_assoc); |
||||
|
CYW_EXIT |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]) { |
||||
|
mp_hal_get_mac(MP_HAL_MAC_WLAN0, &mac[0]); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
#define MAKE_COUNTRY(a, b, rev) ((a) | (b) << 8 | (rev) << 16) |
||||
|
|
||||
|
void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up) { |
||||
|
if (up) { |
||||
|
if (self->itf_state == 0) { |
||||
|
uint32_t country; |
||||
|
extern char pyb_country_code[2]; |
||||
|
if (pyb_country_code[0] == '\0' || pyb_country_code[1] == '\0') { |
||||
|
country = MAKE_COUNTRY('X', 'X', 17); // default to world-wide (passive ch 12-14)
|
||||
|
} else { |
||||
|
country = MAKE_COUNTRY(pyb_country_code[0], pyb_country_code[1], 0); |
||||
|
} |
||||
|
cyw43_wifi_on(self, country); |
||||
|
cyw43_wifi_pm(self, 10 << 20 | 1 << 16 | 1 << 12 | 20 << 4 | 2); |
||||
|
} |
||||
|
if (itf == CYW43_ITF_AP) { |
||||
|
cyw43_wifi_ap_init(self); |
||||
|
cyw43_wifi_ap_set_up(self, true); |
||||
|
} |
||||
|
if ((self->itf_state & (1 << itf)) == 0) { |
||||
|
CYW_ENTER |
||||
|
cyw43_tcpip_deinit(self, itf); |
||||
|
cyw43_tcpip_init(self, itf); |
||||
|
self->itf_state |= 1 << itf; |
||||
|
CYW_EXIT |
||||
|
} |
||||
|
} else { |
||||
|
if (itf == CYW43_ITF_AP) { |
||||
|
cyw43_wifi_ap_set_up(self, false); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)) { |
||||
|
if (self->itf_state == 0) { |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
cyw43_ensure_up(self); |
||||
|
|
||||
|
CYW_ENTER |
||||
|
|
||||
|
// Set state and callback data
|
||||
|
self->wifi_scan_state = 1; |
||||
|
self->wifi_scan_env = env; |
||||
|
self->wifi_scan_cb = result_cb; |
||||
|
|
||||
|
// Start the scan
|
||||
|
int ret = cyw43_ll_wifi_scan(&self->cyw43_ll, opts); |
||||
|
|
||||
|
CYW_EXIT |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int cyw43_wifi_link_status(cyw43_t *self, int itf) { |
||||
|
if (itf == CYW43_ITF_STA) { |
||||
|
int s = self->wifi_join_state & 0xf; |
||||
|
if (s == WIFI_JOIN_STATE_ACTIVE) { |
||||
|
return CYW43_LINK_JOIN; |
||||
|
} else if (s == WIFI_JOIN_STATE_FAIL) { |
||||
|
return CYW43_LINK_FAIL; |
||||
|
} else if (s == WIFI_JOIN_STATE_NONET) { |
||||
|
return CYW43_LINK_NONET; |
||||
|
} else if (s == WIFI_JOIN_STATE_BADAUTH) { |
||||
|
return CYW43_LINK_BADAUTH; |
||||
|
} else { |
||||
|
return CYW43_LINK_DOWN; |
||||
|
} |
||||
|
} else { |
||||
|
return CYW43_LINK_DOWN; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*******************************************************************************/ |
||||
|
// WiFi STA
|
||||
|
|
||||
|
int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
CYW_ENTER |
||||
|
|
||||
|
ret = cyw43_ll_wifi_join(&self->cyw43_ll, ssid_len, ssid, key_len, key, auth_type, bssid, channel); |
||||
|
|
||||
|
if (ret == 0) { |
||||
|
// Wait for responses: EV_AUTH, EV_LINK, EV_SET_SSID, EV_PSK_SUP
|
||||
|
// Will get EV_DEAUTH_IND if password is invalid
|
||||
|
self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; |
||||
|
|
||||
|
if (auth_type == 0) { |
||||
|
// For open security we don't need EV_PSK_SUP, so set that flag indicator now
|
||||
|
self->wifi_join_state |= WIFI_JOIN_STATE_KEYED; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
CYW_EXIT |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
int cyw43_wifi_leave(cyw43_t *self, int itf) { |
||||
|
// Disassociate with SSID
|
||||
|
return cyw43_ioctl(self, CYW43_IOCTL_SET_DISASSOC, 0, NULL, itf); |
||||
|
} |
||||
|
|
||||
|
/*******************************************************************************/ |
||||
|
// WiFi AP
|
||||
|
|
||||
|
STATIC void cyw43_wifi_ap_init(cyw43_t *self) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
CYW_ENTER |
||||
|
cyw43_ll_wifi_ap_init(&self->cyw43_ll, self->ap_ssid_len, self->ap_ssid, self->ap_auth, self->ap_key_len, self->ap_key, self->ap_channel); |
||||
|
CYW_EXIT |
||||
|
} |
||||
|
|
||||
|
STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
CYW_ENTER |
||||
|
cyw43_ll_wifi_ap_set_up(&self->cyw43_ll, up); |
||||
|
CYW_EXIT |
||||
|
} |
||||
|
|
||||
|
void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs) { |
||||
|
int ret = cyw43_ensure_up(self); |
||||
|
if (ret) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
CYW_ENTER |
||||
|
cyw43_ll_wifi_ap_get_stas(&self->cyw43_ll, num_stas, macs); |
||||
|
CYW_EXIT |
||||
|
} |
@ -0,0 +1,135 @@ |
|||||
|
/*
|
||||
|
* 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. |
||||
|
*/ |
||||
|
#ifndef MICROPY_INCLUDED_STM32_CYW43_LL_H |
||||
|
#define MICROPY_INCLUDED_STM32_CYW43_LL_H |
||||
|
|
||||
|
// IOCTL commands
|
||||
|
#define CYW43_IOCTL_GET_SSID (0x32) |
||||
|
#define CYW43_IOCTL_GET_CHANNEL (0x3a) |
||||
|
#define CYW43_IOCTL_SET_DISASSOC (0x69) |
||||
|
#define CYW43_IOCTL_GET_ANTDIV (0x7e) |
||||
|
#define CYW43_IOCTL_SET_ANTDIV (0x81) |
||||
|
#define CYW43_IOCTL_SET_MONITOR (0xd9) |
||||
|
#define CYW43_IOCTL_GET_VAR (0x20c) |
||||
|
#define CYW43_IOCTL_SET_VAR (0x20f) |
||||
|
|
||||
|
// Async events, event_type field
|
||||
|
#define CYW43_EV_SET_SSID (0) |
||||
|
#define CYW43_EV_JOIN (1) |
||||
|
#define CYW43_EV_AUTH (3) |
||||
|
#define CYW43_EV_DEAUTH_IND (6) |
||||
|
#define CYW43_EV_ASSOC (7) |
||||
|
#define CYW43_EV_DISASSOC (11) |
||||
|
#define CYW43_EV_DISASSOC_IND (12) |
||||
|
#define CYW43_EV_LINK (16) |
||||
|
#define CYW43_EV_PRUNE (23) |
||||
|
#define CYW43_EV_PSK_SUP (46) |
||||
|
#define CYW43_EV_ESCAN_RESULT (69) |
||||
|
#define CYW43_EV_CSA_COMPLETE_IND (80) |
||||
|
#define CYW43_EV_ASSOC_REQ_IE (87) |
||||
|
#define CYW43_EV_ASSOC_RESP_IE (88) |
||||
|
|
||||
|
enum { |
||||
|
CYW43_ITF_STA, |
||||
|
CYW43_ITF_AP, |
||||
|
}; |
||||
|
|
||||
|
typedef struct _cyw43_ev_scan_result_t { |
||||
|
uint32_t _0[5]; |
||||
|
uint8_t bssid[6]; |
||||
|
uint16_t _1[2]; |
||||
|
uint8_t ssid_len; |
||||
|
uint8_t ssid[32]; |
||||
|
uint32_t _2[5]; |
||||
|
uint16_t channel; |
||||
|
uint16_t _3; |
||||
|
uint8_t auth_mode; |
||||
|
int16_t rssi; |
||||
|
} cyw43_ev_scan_result_t; |
||||
|
|
||||
|
typedef struct _cyw43_async_event_t { |
||||
|
uint16_t _0; |
||||
|
uint16_t flags; |
||||
|
uint32_t event_type; |
||||
|
uint32_t status; |
||||
|
uint32_t reason; |
||||
|
uint8_t _1[30]; |
||||
|
uint8_t interface; |
||||
|
uint8_t _2; |
||||
|
union { |
||||
|
cyw43_ev_scan_result_t scan_result; |
||||
|
} u; |
||||
|
} cyw43_async_event_t; |
||||
|
|
||||
|
typedef struct _cyw43_wifi_scan_options_t { |
||||
|
uint32_t version; |
||||
|
uint16_t action; |
||||
|
uint16_t _; |
||||
|
uint32_t ssid_len; // 0 to select all
|
||||
|
uint8_t ssid[32]; |
||||
|
uint8_t bssid[6]; |
||||
|
int8_t bss_type; // fill with 0xff to select all
|
||||
|
int8_t scan_type; // 0=active, 1=passive
|
||||
|
int32_t nprobes; |
||||
|
int32_t active_time; |
||||
|
int32_t passive_time; |
||||
|
int32_t home_time; |
||||
|
int32_t channel_num; |
||||
|
uint16_t channel_list[1]; |
||||
|
} cyw43_wifi_scan_options_t; |
||||
|
|
||||
|
typedef struct _cyw43_ll_t { |
||||
|
uint32_t opaque[528]; |
||||
|
} cyw43_ll_t; |
||||
|
|
||||
|
void cyw43_ll_init(cyw43_ll_t *self, void *cb_data); |
||||
|
void cyw43_ll_deinit(cyw43_ll_t *self); |
||||
|
|
||||
|
int cyw43_ll_bus_init(cyw43_ll_t *self, const uint8_t *mac); |
||||
|
void cyw43_ll_bus_sleep(cyw43_ll_t *self, bool can_sleep); |
||||
|
void cyw43_ll_process_packets(cyw43_ll_t *self); |
||||
|
int cyw43_ll_ioctl(cyw43_ll_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface); |
||||
|
int cyw43_ll_send_ethernet(cyw43_ll_t *self, int itf, size_t len, const void *buf, bool is_pbuf); |
||||
|
|
||||
|
int cyw43_ll_wifi_on(cyw43_ll_t *self, uint32_t country); |
||||
|
int cyw43_ll_wifi_pm(cyw43_ll_t *self, uint32_t pm, uint32_t pm_sleep_ret, uint32_t li_bcn, uint32_t li_dtim, uint32_t li_assoc); |
||||
|
int cyw43_ll_wifi_scan(cyw43_ll_t *self, cyw43_wifi_scan_options_t *opts); |
||||
|
|
||||
|
int cyw43_ll_wifi_join(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel); |
||||
|
void cyw43_ll_wifi_set_wpa_auth(cyw43_ll_t *self); |
||||
|
void cyw43_ll_wifi_rejoin(cyw43_ll_t *self); |
||||
|
|
||||
|
int cyw43_ll_wifi_ap_init(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, uint32_t auth, size_t key_len, const uint8_t *key, uint32_t channel); |
||||
|
int cyw43_ll_wifi_ap_set_up(cyw43_ll_t *self, bool up); |
||||
|
int cyw43_ll_wifi_ap_get_stas(cyw43_ll_t *self, int *num_stas, uint8_t *macs); |
||||
|
|
||||
|
// Callbacks to be provided by mid-level interface
|
||||
|
int cyw43_cb_read_host_interrupt_pin(void *cb_data); |
||||
|
void cyw43_cb_ensure_awake(void *cb_data); |
||||
|
void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev); |
||||
|
void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf); |
||||
|
|
||||
|
#endif // MICROPY_INCLUDED_STM32_CYW43_LL_H
|
@ -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); |
||||
|
} |
||||
|
} |
Binary file not shown.
Loading…
Reference in new issue