From 89203a799d627b0657d03bcd14c6aba91cb2d162 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Sun, 19 Aug 2018 16:52:09 +0200 Subject: [PATCH 1/2] nrf: Add support for sockets using cc3100. --- ports/nrf/Makefile | 26 + ports/nrf/boards/pca10040/mpconfigboard.h | 3 + ports/nrf/drivers/wifi/cc3100_drv.c | 146 ++ ports/nrf/drivers/wifi/cc3100_drv.h | 42 + ports/nrf/drivers/wifi/user.h | 1023 ++++++++++++ ports/nrf/main.c | 9 + ports/nrf/modules/machine/pin.c | 49 +- ports/nrf/modules/machine/pin.h | 8 + ports/nrf/modules/machine/spi.c | 40 +- ports/nrf/modules/machine/spi.h | 40 + ports/nrf/modules/network/modnetwork.c | 180 +++ ports/nrf/modules/network/modnetwork.h | 114 ++ ports/nrf/modules/network/modnwcc31k.c | 1749 +++++++++++++++++++++ ports/nrf/modules/network/modnwcc31k.h | 107 ++ ports/nrf/mpconfigport.h | 38 + 15 files changed, 3520 insertions(+), 54 deletions(-) create mode 100644 ports/nrf/drivers/wifi/cc3100_drv.c create mode 100644 ports/nrf/drivers/wifi/cc3100_drv.h create mode 100644 ports/nrf/drivers/wifi/user.h create mode 100644 ports/nrf/modules/network/modnetwork.c create mode 100644 ports/nrf/modules/network/modnetwork.h create mode 100644 ports/nrf/modules/network/modnwcc31k.c create mode 100644 ports/nrf/modules/network/modnwcc31k.h diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 6ca83f1e6e331..85fff5e8df032 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -58,8 +58,11 @@ INC += -I./modules/music INC += -I./modules/random INC += -I./modules/ble INC += -I./modules/board +INC += -I./modules/socket +INC += -I./modules/network INC += -I../../lib/mp-readline INC += -I./drivers/bluetooth +INC += -I./drivers/wifi INC += -I./drivers INC += -I../../lib/nrfx/ INC += -I../../lib/nrfx/drivers @@ -158,6 +161,7 @@ SRC_LIB += $(addprefix lib/,\ utils/pyexec.c \ utils/interrupt_char.c \ timeutils/timeutils.c \ + netutils/netutils.c \ ) ifeq ($(MICROPY_FATFS), 1) @@ -199,6 +203,7 @@ SRC_C += \ drivers/ticker.c \ drivers/bluetooth/ble_drv.c \ drivers/bluetooth/ble_uart.c \ + drivers/wifi/cc3100_drv.c \ DRIVERS_SRC_C += $(addprefix modules/,\ machine/modmachine.c \ @@ -230,8 +235,29 @@ DRIVERS_SRC_C += $(addprefix modules/,\ music/musictunes.c \ ble/modble.c \ random/modrandom.c \ + socket/modusocket.c \ + network/modnetwork.c \ + network/modnwcc31k.c \ ) +ifeq ($(MICROPY_PY_CC31K),1) +CC3100_DIR=drivers/cc3100 +INC += -I$(TOP)/$(CC3100_DIR)/inc +CFLAGS_MOD += -DMICROPY_PY_CC31K=1 +SRC_MOD += $(addprefix $(CC3100_DIR)/src/,\ + device.c \ + driver.c \ + flowcont.c \ + fs.c \ + netapp.c \ + netcfg.c \ + nonos.c \ + socket.c \ + spawn.c \ + wlan.c \ + ) +endif + # Custom micropython startup file with smaller interrupt vector table # than the file provided in nrfx. SRC_C += \ diff --git a/ports/nrf/boards/pca10040/mpconfigboard.h b/ports/nrf/boards/pca10040/mpconfigboard.h index 82b74d9284916..b11c99c3544a3 100644 --- a/ports/nrf/boards/pca10040/mpconfigboard.h +++ b/ports/nrf/boards/pca10040/mpconfigboard.h @@ -38,6 +38,9 @@ #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) +#define MICROPY_PY_USOCKET (1) +#define MICROPY_PY_NETWORK (1) + #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_PULLUP (1) diff --git a/ports/nrf/drivers/wifi/cc3100_drv.c b/ports/nrf/drivers/wifi/cc3100_drv.c new file mode 100644 index 0000000000000..78688bf989f8f --- /dev/null +++ b/ports/nrf/drivers/wifi/cc3100_drv.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Glenn Ruben Bakke + * + * 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 "py/mpconfig.h" + +#if (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) +#include "cc3100_drv.h" +#include "nrf_gpio.h" +#include "nrf_gpiote.h" +#include "pin.h" +#include "spi.h" +#include "mphalport.h" + +#if NRFX_SPI_ENABLED +#include "nrfx_spi.h" +#else +#include "nrfx_spim.h" +#endif + +#define CS_LOW() nrf_gpio_pin_clear(mp_pin_cs->pin) +#define CS_HIGH() nrf_gpio_pin_set(mp_pin_cs->pin) + +STATIC const machine_hard_spi_obj_t * mp_spi = NULL; + +STATIC const pin_obj_t * mp_pin_cs = NULL; +STATIC const pin_obj_t * mp_pin_en = NULL; +STATIC const pin_obj_t * mp_pin_irq = NULL; + +STATIC volatile irq_handler_t mp_cc3100_irq_handler = NULL; + +STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj; + +STATIC mp_obj_t irq_callback(mp_obj_t pin_obj) { + if (mp_cc3100_irq_handler) + { + mp_cc3100_irq_handler(0); + } + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback); + +void cc3100_drv_enable(void) { + nrf_gpio_pin_set(mp_pin_en->pin); +} + +void cc3100_drv_disable(void) { + nrf_gpio_pin_clear(mp_pin_en->pin); +} + +void cc3100_drv_init(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) { + machine_hard_spi_obj_t * spi_obj = spi; + + mp_spi = spi_obj; + mp_pin_cs = pin_cs; + mp_pin_en = pin_en; + mp_pin_irq = pin_irq; +} + +int cc3100_drv_open(char * interface, unsigned long flags) { + nrf_gpio_cfg_output(mp_pin_cs->pin); + nrf_gpio_cfg_output(mp_pin_en->pin); + + nrf_gpio_pin_set(mp_pin_cs->pin); + nrf_gpio_cfg_input(mp_pin_irq->pin, NRF_GPIO_PIN_PULLUP); + + // register interrupt handler + extint_register(mp_pin_irq->pin, NRF_GPIOTE_POLARITY_LOTOHI, NRF_GPIO_PIN_PULLDOWN, (mp_obj_t)&irq_callback_obj); + extint_enable(mp_pin_irq->pin); + + nrf_gpio_pin_clear(mp_pin_en->pin); + mp_hal_delay_ms(500); + + return 0; +} + +int cc3100_drv_close(int handle) { + return -1; +} + +int cc3100_drv_read(int handle, unsigned char * p_buffer, int len) { + nrfx_spi_xfer_desc_t xfer_desc = { + .p_tx_buffer = NULL, + .tx_length = 0, + .p_rx_buffer = p_buffer, + .rx_length = len + }; + + CS_LOW(); + (void)nrfx_spi_xfer(mp_spi->p_spi, &xfer_desc, 0); + CS_HIGH(); + + return 0; +} + +int cc3100_drv_write(int handle, unsigned char * p_buffer, int len) { + nrfx_spi_xfer_desc_t xfer_desc = { + .p_tx_buffer = p_buffer, + .tx_length = len, + .p_rx_buffer = NULL, + .rx_length = 0 + }; + + CS_LOW(); + (void)nrfx_spi_xfer(mp_spi->p_spi, &xfer_desc, 0); + CS_HIGH(); + + return 0; +} + +int cc3100_drv_irq_handler_register(irq_handler_t handler, void * p_val) { + mp_cc3100_irq_handler = handler; + + return 0; +} + +void cc3100_drv_irq_handler_mask(void) { +} + +void cc3100_drv_irq_handler_unmask(void) { +} + +#endif // (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) diff --git a/ports/nrf/drivers/wifi/cc3100_drv.h b/ports/nrf/drivers/wifi/cc3100_drv.h new file mode 100644 index 0000000000000..2638e9b4be946 --- /dev/null +++ b/ports/nrf/drivers/wifi/cc3100_drv.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Glenn Ruben Bakke + * + * 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 CC3100_DRV_H +#define CC3100_DRV_H + +typedef void (*irq_handler_t)(void *p_val); + +void cc3100_drv_enable(void); +void cc3100_drv_disable(void); +void cc3100_drv_init(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq); +int cc3100_drv_open(char * interface, unsigned long flags); +int cc3100_drv_close(int handle); +int cc3100_drv_read(int handle, unsigned char * p_buffer, int len); +int cc3100_drv_write(int handle, unsigned char * p_buffer, int len); +int cc3100_drv_irq_handler_register(irq_handler_t handler, void * p_val); +void cc3100_drv_irq_handler_mask(void); +void cc3100_drv_irq_handler_unmask(void); + +#endif // CC3100_DRV_H diff --git a/ports/nrf/drivers/wifi/user.h b/ports/nrf/drivers/wifi/user.h new file mode 100644 index 0000000000000..169935b9f62c8 --- /dev/null +++ b/ports/nrf/drivers/wifi/user.h @@ -0,0 +1,1023 @@ +/* + * user.h - CC31xx/CC32xx Host Driver Implementation + * + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + + +#ifndef __USER_H__ +#define __USER_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + ****************************************************************************** + + \defgroup porting_user_include Porting - User Include Files + + This section IS NOT REQUIRED in case user provided primitives are handled + in makefiles or project configurations (IDE) + + PORTING ACTION: + - Include all required header files for the definition of: + -# Transport layer library API (e.g. SPI, UART) + -# OS primitives definitions (e.g. Task spawn, Semaphores) + -# Memory management primitives (e.g. alloc, free) + + ****************************************************************************** + */ + +#include +#include "cc3100_drv.h" + +typedef void (*irq_handler_t)(void *pVal); + + +typedef irq_handler_t SL_P_EVENT_HANDLER; +/*! + \def MAX_CONCURRENT_ACTIONS + + \brief Defines the maximum number of concurrent action in the system + Min:1 , Max: 32 + + Actions which has async events as return, can be + + \sa + + \note In case there are not enough resources for the actions needed in the system, + error is received: POOL_IS_EMPTY + one option is to increase MAX_CONCURRENT_ACTIONS + (improves performance but results in memory consumption) + Other option is to call the API later (decrease performance) + + \warning In case of setting to one, recommend to use non-blocking recv\recvfrom to allow + multiple socket recv +*/ +#define MAX_CONCURRENT_ACTIONS 10 + +/*! + ****************************************************************************** + + \defgroup porting_capabilities Porting - Capabilities Set + + This section IS NOT REQUIRED in case one of the following pre defined + capabilities set is in use: + - SL_TINY + - SL_SMALL + - SL_FULL + + PORTING ACTION: + - Define one of the pre-defined capabilities set or uncomment the + relevant definitions below to select the required capabilities + + @{ + + ******************************************************************************* + */ + +/*! + \def SL_INC_ARG_CHECK + + \brief Defines whether the SimpleLink driver perform argument check + or not + + When defined, the SimpleLink driver perform argument check on + function call. Removing this define could reduce some code + size and improve slightly the performances but may impact in + unpredictable behavior in case of invalid arguments + + \sa + + \note belongs to \ref porting_sec + + \warning Removing argument check may cause unpredictable behavior in + case of invalid arguments. + In this case the user is responsible to argument validity + (for example all handlers must not be NULL) +*/ +#define SL_INC_ARG_CHECK + + +/*! + \def SL_INC_STD_BSD_API_NAMING + + \brief Defines whether SimpleLink driver should expose standard BSD + APIs or not + + When defined, the SimpleLink driver in addtion to its alternative + BSD APIs expose also standard BSD APIs. + Stadrad BSD API includs the following functions: + socket , close , accept , bind , listen , connect , select , + setsockopt , getsockopt , recv , recvfrom , write , send , sendto , + gethostbyname + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define SL_INC_STD_BSD_API_NAMING + + +/*! + \brief Defines whether to include extended API in SimpleLink driver + or not + + When defined, the SimpleLink driver will include also all + exteded API of the included packages + + \sa ext_api + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_EXT_API + +/*! + \brief Defines whether to include WLAN package in SimpleLink driver + or not + + When defined, the SimpleLink driver will include also + the WLAN package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_WLAN_PKG + +/*! + \brief Defines whether to include SOCKET package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also + the SOCKET package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCKET_PKG + +/*! + \brief Defines whether to include NET_APP package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also the + NET_APP package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_NET_APP_PKG + +/*! + \brief Defines whether to include NET_CFG package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also + the NET_CFG package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_NET_CFG_PKG + +/*! + \brief Defines whether to include NVMEM package in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also the + NVMEM package + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_NVMEM_PKG + +/*! + \brief Defines whether to include socket server side APIs + in SimpleLink driver or not + + When defined, the SimpleLink driver will include also socket + server side APIs + + \sa server_side + + \note + + \warning +*/ +#define SL_INC_SOCK_SERVER_SIDE_API + +/*! + \brief Defines whether to include socket client side APIs in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also socket + client side APIs + + \sa client_side + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCK_CLIENT_SIDE_API + +/*! + \brief Defines whether to include socket receive APIs in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also socket + receive side APIs + + \sa recv_api + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCK_RECV_API + +/*! + \brief Defines whether to include socket send APIs in SimpleLink + driver or not + + When defined, the SimpleLink driver will include also socket + send side APIs + + \sa send_api + + \note belongs to \ref porting_sec + + \warning +*/ +#define SL_INC_SOCK_SEND_API + +/*! + + Close the Doxygen group. + @} + + */ + + +/*! + ****************************************************************************** + + \defgroup porting_enable_device Porting - Device Enable/Disable + + The enable/disable API provide mechanism to enable/disable the network processor + + + PORTING ACTION: + - None + @{ + + ****************************************************************************** + */ + +/*! + \brief Preamble to the enabling the Network Processor. + Placeholder to implement any pre-process operations + before enabling networking operations. + + \sa sl_DeviceEnable + + \note belongs to \ref ported_sec + +*/ +#define sl_DeviceEnablePreamble() + +/*! + \brief Enable the Network Processor + + \sa sl_DeviceDisable + + \note belongs to \ref porting_sec + +*/ +#define sl_DeviceEnable cc3100_drv_enable + +/*! + \brief Disable the Network Processor + + \sa sl_DeviceEnable + + \note belongs to \ref porting_sec +*/ +#define sl_DeviceDisable cc3100_drv_disable + +/*! + + Close the Doxygen group. + @} + + */ + +/*! + ****************************************************************************** + + \defgroup porting_interface Porting - Communication Interface + + The simple link device can work with different communication + channels (e.g. spi/uart). Texas Instruments provides single driver + that can work with all these types. This section bind between the + physical communication interface channel and the SimpleLink driver + + + \note Correct and efficient implementation of this driver is critical + for the performances of the SimpleLink device on this platform. + + + PORTING ACTION: + - None + + @{ + + ****************************************************************************** + */ + +#define _SlFd_t int + +/*! + \brief Opens an interface communication port to be used for communicating + with a SimpleLink device + + Given an interface name and option flags, this function opens + the communication port and creates a file descriptor. + This file descriptor is used afterwards to read and write + data from and to this specific communication channel. + The speed, clock polarity, clock phase, chip select and all other + specific attributes of the channel are all should be set to hardcoded + in this function. + + \param ifName - points to the interface name/path. The interface name is an + optional attributes that the simple link driver receives + on opening the driver (sl_Start). + In systems that the spi channel is not implemented as + part of the os device drivers, this parameter could be NULL. + + \param flags - optional flags parameters for future use + + \return upon successful completion, the function shall open the channel + and return a non-negative integer representing the file descriptor. + Otherwise, -1 shall be returned + + \sa sl_IfClose , sl_IfRead , sl_IfWrite + + \note The prototype of the function is as follow: + Fd_t xxx_IfOpen(char* pIfName , unsigned long flags); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfOpen cc3100_drv_open + +/*! + \brief Closes an opened interface communication port + + \param fd - file descriptor of opened communication channel + + \return upon successful completion, the function shall return 0. + Otherwise, -1 shall be returned + + \sa sl_IfOpen , sl_IfRead , sl_IfWrite + + \note The prototype of the function is as follow: + int xxx_IfClose(Fd_t Fd); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfClose cc3100_drv_close + +/*! + \brief Attempts to read up to len bytes from an opened communication channel + into a buffer starting at pBuff. + + \param fd - file descriptor of an opened communication channel + + \param pBuff - pointer to the first location of a buffer that contains enough + space for all expected data + + \param len - number of bytes to read from the communication channel + + \return upon successful completion, the function shall return the number of read bytes. + Otherwise, 0 shall be returned + + \sa sl_IfClose , sl_IfOpen , sl_IfWrite + + + \note The prototype of the function is as follow: + int xxx_IfRead(Fd_t Fd , char* pBuff , int Len); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfRead cc3100_drv_read + +/*! + \brief attempts to write up to len bytes to the SPI channel + + \param fd - file descriptor of an opened communication channel + + \param pBuff - pointer to the first location of a buffer that contains + the data to send over the communication channel + + \param len - number of bytes to write to the communication channel + + \return upon successful completion, the function shall return the number of sent bytes. + therwise, 0 shall be returned + + \sa sl_IfClose , sl_IfOpen , sl_IfRead + + \note This function could be implemented as zero copy and return only upon successful completion + of writing the whole buffer, but in cases that memory allocation is not too tight, the + function could copy the data to internal buffer, return back and complete the write in + parallel to other activities as long as the other SPI activities would be blocked until + the entire buffer write would be completed + + The prototype of the function is as follow: + int xxx_IfWrite(Fd_t Fd , char* pBuff , int Len); + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfWrite cc3100_drv_write + +/*! + \brief register an interrupt handler routine for the host IRQ + + \param InterruptHdl - pointer to interrupt handler routine + + \param pValue - pointer to a memory structure that is passed + to the interrupt handler. + + \return upon successful registration, the function shall return 0. + Otherwise, -1 shall be returned + + \sa + + \note If there is already registered interrupt handler, the function + should overwrite the old handler with the new one + + \note If the handler is a null pointer, the function should un-register the + interrupt handler, and the interrupts can be disabled. + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_IfRegIntHdlr(InterruptHdl , pValue) \ + cc3100_drv_irq_handler_register(InterruptHdl, pValue) +/*! + \brief Masks the Host IRQ + + \sa sl_IfUnMaskIntHdlr + + + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_IfMaskIntHdlr() cc3100_drv_irq_handler_mask() + +/*! + \brief Unmasks the Host IRQ + + \sa sl_IfMaskIntHdlr + + + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_IfUnMaskIntHdlr() cc3100_drv_irq_handler_unmask() + +/*! + \brief Write Handers for statistics debug on write + + \param interface handler - pointer to interrupt handler routine + + + \return no return value + + \sa + + \note An optional hooks for monitoring before and after write info + + \note belongs to \ref porting_sec + + \warning +*/ +/* +#define SL_START_WRITE_STAT +*/ + +#ifdef SL_START_WRITE_STAT +#define sl_IfStartWriteSequence +#define sl_IfEndWriteSequence +#endif +/*! + + Close the Doxygen group. + @} + + */ + +/*! + ****************************************************************************** + + \defgroup porting_mem_mgm Porting - Memory Management + + This section declare in which memory management model the SimpleLink driver + will run: + -# Static + -# Dynamic + + This section IS NOT REQUIRED in case Static model is selected. + + The default memory model is Static + + PORTING ACTION: + - If dynamic model is selected, define the alloc and free functions. + + @{ + + ***************************************************************************** + */ + +/*! + \brief Defines whether the SimpleLink driver is working in dynamic + memory model or not + + When defined, the SimpleLink driver use dynamic allocations + if dynamic allocation is selected malloc and free functions + must be retrieved + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define SL_MEMORY_MGMT_DYNAMIC 0 +#define SL_MEMORY_MGMT_STATIC 1 + +#define SL_MEMORY_MGMT SL_MEMORY_MGMT_STATIC + +#ifdef SL_MEMORY_MGMT_DYNAMIC + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_Malloc(Size) malloc(Size) + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_Free(pMem) free(pMem) + +#endif + +/*! + + Close the Doxygen group. + @} + + */ + +/*! + ****************************************************************************** + + \defgroup porting_os Porting - Operating System + + The simple link driver can run on multi-threaded environment as well + as non-os environment (mail loop) + + This section IS NOT REQUIRED in case you are working on non-os environment. + + If you choose to work in multi-threaded environment under any operating system + you will have to provide some basic adaptation routines to allow the driver + to protect access to resources from different threads (locking object) and + to allow synchronization between threads (sync objects). + + PORTING ACTION: + -# Uncomment SL_PLATFORM_MULTI_THREADED define + -# Bind locking object routines + -# Bind synchronization object routines + -# Optional - Bind spawn thread routine + + @{ + + ****************************************************************************** + */ + +/* +#define SL_PLATFORM_MULTI_THREADED +*/ + +#ifdef SL_PLATFORM_MULTI_THREADED + +/*! + \brief + \sa + \note belongs to \ref porting_sec + \warning +*/ +#define SL_OS_RET_CODE_OK ((int)OSI_OK) + +/*! + \brief + \sa + \note belongs to \ref porting_sec + \warning +*/ +#define SL_OS_WAIT_FOREVER ((OsiTime_t)OSI_WAIT_FOREVER) + +/*! + \brief + \sa + \note belongs to \ref porting_sec + \warning +*/ +#define SL_OS_NO_WAIT ((OsiTime_t)OSI_NO_WAIT) + +/*! + \brief type definition for a time value + + \note On each porting or platform the type could be whatever is needed - integer, pointer to structure etc. + + \note belongs to \ref porting_sec +*/ +#define _SlTime_t + +/*! + \brief type definition for a sync object container + + Sync object is object used to synchronize between two threads or thread and interrupt handler. + One thread is waiting on the object and the other thread send a signal, which then + release the waiting thread. + The signal must be able to be sent from interrupt context. + This object is generally implemented by binary semaphore or events. + + \note On each porting or platform the type could be whatever is needed - integer, structure etc. + + \note belongs to \ref porting_sec +*/ +#define _SlSyncObj_t + + +/*! + \brief This function creates a sync object + + The sync object is used for synchronization between diffrent thread or ISR and + a thread. + + \param pSyncObj - pointer to the sync object control block + + \return upon successful creation the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + + \note belongs to \ref porting_sec + \warning +*/ +#define sl_SyncObjCreate(pSyncObj,pName) + + +/*! + \brief This function deletes a sync object + + \param pSyncObj - pointer to the sync object control block + + \return upon successful deletion the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_SyncObjDelete(pSyncObj) + + +/*! + \brief This function generates a sync signal for the object. + + All suspended threads waiting on this sync object are resumed + + \param pSyncObj - pointer to the sync object control block + + \return upon successful signaling the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note the function could be called from ISR context + \warning +*/ +#define sl_SyncObjSignal(pSyncObj) + +/*! + \brief This function generates a sync signal for the object from Interrupt + + This is for RTOS that should signal from IRQ using a dedicated API + + \param pSyncObj - pointer to the sync object control block + + \return upon successful signaling the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note the function could be called from ISR context + \warning +*/ +#define sl_SyncObjSignalFromIRQ(pSyncObj) +/*! + \brief This function waits for a sync signal of the specific sync object + + \param pSyncObj - pointer to the sync object control block + \param Timeout - numeric value specifies the maximum number of mSec to + stay suspended while waiting for the sync signal + Currently, the simple link driver uses only two values: + - OSI_WAIT_FOREVER + - OSI_NO_WAIT + + \return upon successful reception of the signal within the timeout window return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_SyncObjWait(pSyncObj,Timeout) + +/*! + \brief type definition for a locking object container + + Locking object are used to protect a resource from mutual accesses of two or more threads. + The locking object should suppurt reentrant locks by a signal thread. + This object is generally implemented by mutex semaphore + + \note On each porting or platform the type could be whatever is needed - integer, structure etc. + \note belongs to \ref porting_sec +*/ +#define _SlLockObj_t + +/*! + \brief This function creates a locking object. + + The locking object is used for protecting a shared resources between different + threads. + + \param pLockObj - pointer to the locking object control block + + \return upon successful creation the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjCreate(pLockObj,pName) + +/*! + \brief This function deletes a locking object. + + \param pLockObj - pointer to the locking object control block + + \return upon successful deletion the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjDelete(pLockObj) + +/*! + \brief This function locks a locking object. + + All other threads that call this function before this thread calls + the osi_LockObjUnlock would be suspended + + \param pLockObj - pointer to the locking object control block + \param Timeout - numeric value specifies the maximum number of mSec to + stay suspended while waiting for the locking object + Currently, the simple link driver uses only two values: + - OSI_WAIT_FOREVER + - OSI_NO_WAIT + + + \return upon successful reception of the locking object the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjLock(pLockObj,Timeout) + +/*! + \brief This function unlock a locking object. + + \param pLockObj - pointer to the locking object control block + + \return upon successful unlocking the function should return 0 + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +#define sl_LockObjUnlock(pLockObj) + +#endif +/*! + \brief This function call the pEntry callback from a different context + + \param pEntry - pointer to the entry callback function + + \param pValue - pointer to any type of memory structure that would be + passed to pEntry callback from the execution thread. + + \param flags - execution flags - reserved for future usage + + \return upon successful registration of the spawn the function should return 0 + (the function is not blocked till the end of the execution of the function + and could be returned before the execution is actually completed) + Otherwise, a negative value indicating the error code shall be returned + \note belongs to \ref porting_sec + \warning +*/ +/* +#define SL_PLATFORM_EXTERNAL_SPAWN +*/ + +#ifdef SL_PLATFORM_EXTERNAL_SPAWN +#define sl_Spawn(pEntry,pValue,flags) +#endif + +/*! + + Close the Doxygen group. + @} + + */ + + +/*! + ****************************************************************************** + + \defgroup porting_events Porting - Event Handlers + + This section includes the asynchronous event handlers routines + + PORTING ACTION: + -Uncomment the required handler and define your routine as the value + of this handler + + @{ + + ****************************************************************************** + */ + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_GeneralEvtHdlr SimpleLinkGeneralEventHandler + +/*! + \brief An event handler for WLAN connection or disconnection indication + This event handles async WLAN events. + Possible events are: + SL_WLAN_CONNECT_EVENT - indicates WLAN is connected + SL_WLAN_DISCONNECT_EVENT - indicates WLAN is disconnected + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_WlanEvtHdlr SimpleLinkWlanEventHandler + +/*! + \brief An event handler for IP address asynchronous event. Usually accepted after new WLAN connection. + This event handles networking events. + Possible events are: + SL_NETAPP_IPV4_ACQUIRED - IP address was acquired (DHCP or Static) + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_NetAppEvtHdlr SimpleLinkNetAppEventHandler + +/*! + \brief A callback for HTTP server events. + Possible events are: + SL_NETAPP_HTTPGETTOKENVALUE - NWP requests to get the value of a specific token + SL_NETAPP_HTTPPOSTTOKENVALUE - NWP post to the host a new value for a specific token + + \param pServerEvent - Contains the relevant event information (SL_NETAPP_HTTPGETTOKENVALUE or SL_NETAPP_HTTPPOSTTOKENVALUE) + + \param pServerResponse - Should be filled by the user with the relevant response information (i.e SL_NETAPP_HTTPSETTOKENVALUE as a response to SL_NETAPP_HTTPGETTOKENVALUE event) + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ + +#define sl_HttpServerCallback SimpleLinkHttpServerCallback + +/*! + \brief + + \sa + + \note belongs to \ref porting_sec + + \warning +*/ +#define sl_SockEvtHdlr SimpleLinkSockEventHandler + + +/*! + + Close the Doxygen group. + @} + + */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __USER_H__ */ diff --git a/ports/nrf/main.c b/ports/nrf/main.c index b9c29e7538d8c..63ec551718dde 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -70,6 +70,10 @@ #include "softpwm.h" #endif +#if MICROPY_PY_NETWORK +#include "modnetwork.h" +#endif + void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { @@ -225,6 +229,11 @@ pin_init0(); pwm_start(); #endif +#if MICROPY_PY_NETWORK + mod_network_init(); +#endif + + #if MICROPY_VFS || MICROPY_MBFS // run boot.py and main.py if they exist. if (mp_import_stat("boot.py") == MP_IMPORT_STAT_FILE) { diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index df4eb471e33b3..73b5e18f3587c 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -535,39 +535,54 @@ STATIC void pin_common_irq_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t mp_call_function_1(pin_handler, (mp_obj_t)pin_obj); } +void extint_register(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t sense, nrf_gpio_pin_pull_t pull, mp_obj_t callback) { + nrfx_gpiote_in_config_t config = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); + config.sense = sense; + config.pull = pull; + + nrfx_err_t err_code = nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); + if (err_code == NRFX_ERROR_INVALID_STATE) { + // Re-init if already configured. + nrfx_gpiote_in_uninit(pin); + nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); + } + + MP_STATE_PORT(pin_irq_handlers)[pin] = callback; +} + +void extint_enable(nrfx_gpiote_pin_t pin) { + nrfx_gpiote_in_event_enable(pin, true); +} + +void extint_disable(nrfx_gpiote_pin_t pin) { + nrfx_gpiote_in_event_disable(pin); +} + STATIC mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum {ARG_handler, ARG_trigger, ARG_wake}; + enum {ARG_handler, ARG_trigger, ARG_wake}; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = mp_const_none} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = NRF_GPIOTE_POLARITY_LOTOHI | NRF_GPIOTE_POLARITY_HITOLO} }, { MP_QSTR_wake, MP_ARG_BOOL, {.u_bool = false} }, }; + pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - nrfx_gpiote_pin_t pin = self->pin; + nrfx_gpiote_pin_t pin = self->pin; + nrf_gpio_pin_pull_t pull = NRF_GPIO_PIN_PULLUP; + nrf_gpiote_polarity_t sense = NRF_GPIOTE_POLARITY_LOTOHI; - nrfx_gpiote_in_config_t config = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); if (args[ARG_trigger].u_int == NRF_GPIOTE_POLARITY_LOTOHI) { - config.sense = NRF_GPIOTE_POLARITY_LOTOHI; + sense = NRF_GPIOTE_POLARITY_LOTOHI; } else if (args[ARG_trigger].u_int == NRF_GPIOTE_POLARITY_HITOLO) { - config.sense = NRF_GPIOTE_POLARITY_HITOLO; + sense = NRF_GPIOTE_POLARITY_HITOLO; } - config.pull = NRF_GPIO_PIN_PULLUP; - nrfx_err_t err_code = nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); - if (err_code == NRFX_ERROR_INVALID_STATE) { - // Re-init if already configured. - nrfx_gpiote_in_uninit(pin); - nrfx_gpiote_in_init(pin, &config, pin_common_irq_handler); - } - - MP_STATE_PORT(pin_irq_handlers)[pin] = args[ARG_handler].u_obj; - - nrfx_gpiote_in_event_enable(pin, true); + extint_register(pin, sense, pull, args[ARG_handler].u_obj); + extint_enable(pin); - // return the irq object return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_irq_obj, 1, pin_irq); diff --git a/ports/nrf/modules/machine/pin.h b/ports/nrf/modules/machine/pin.h index 7004b320b1b6b..bb6d96cd07e33 100644 --- a/ports/nrf/modules/machine/pin.h +++ b/ports/nrf/modules/machine/pin.h @@ -32,6 +32,7 @@ #include MICROPY_PIN_DEFS_PORT_H #include "py/obj.h" +#include "nrfx_gpiote.h" typedef struct { mp_obj_base_t base; @@ -96,4 +97,11 @@ const pin_af_obj_t *pin_find_af(const pin_obj_t *pin, uint8_t fn, uint8_t unit); const pin_af_obj_t *pin_find_af_by_index(const pin_obj_t *pin, mp_uint_t af_idx); const pin_af_obj_t *pin_find_af_by_name(const pin_obj_t *pin, const char *name); +void extint_register(nrfx_gpiote_pin_t pin, + nrf_gpiote_polarity_t sense, + nrf_gpio_pin_pull_t pull, + mp_obj_t callback); +void extint_enable(nrfx_gpiote_pin_t pin); +void extint_disable(nrfx_gpiote_pin_t pin); + #endif // __MICROPY_INCLUDED_NRF5_PIN_H__ diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index ce75b6cafe233..cc8b3e956030e 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -69,40 +69,6 @@ /// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf /// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf -#if NRFX_SPIM_ENABLED - -#define nrfx_spi_t nrfx_spim_t -#define nrfx_spi_config_t nrfx_spim_config_t -#define nrfx_spi_xfer_desc_t nrfx_spim_xfer_desc_t - -#define NRFX_SPI_PIN_NOT_USED NRFX_SPIM_PIN_NOT_USED -#define NRFX_SPI_INSTANCE NRFX_SPIM_INSTANCE -#define NRF_SPI_BIT_ORDER_LSB_FIRST NRF_SPIM_BIT_ORDER_LSB_FIRST -#define NRF_SPI_BIT_ORDER_MSB_FIRST NRF_SPIM_BIT_ORDER_MSB_FIRST -#define NRF_SPI_MODE_0 NRF_SPIM_MODE_0 -#define NRF_SPI_MODE_1 NRF_SPIM_MODE_1 -#define NRF_SPI_MODE_2 NRF_SPIM_MODE_2 -#define NRF_SPI_MODE_3 NRF_SPIM_MODE_3 -#define NRF_SPI_FREQ_125K NRF_SPIM_FREQ_125K -#define NRF_SPI_FREQ_250K NRF_SPIM_FREQ_250K -#define NRF_SPI_FREQ_500K NRF_SPIM_FREQ_500K -#define NRF_SPI_FREQ_1M NRF_SPIM_FREQ_1M -#define NRF_SPI_FREQ_2M NRF_SPIM_FREQ_2M -#define NRF_SPI_FREQ_4M NRF_SPIM_FREQ_4M -#define NRF_SPI_FREQ_8M NRF_SPIM_FREQ_8M - -#define nrfx_spi_init nrfx_spim_init -#define nrfx_spi_uninit nrfx_spim_uninit -#define nrfx_spi_xfer nrfx_spim_xfer - -#endif // NRFX_SPIM_ENABLED - -typedef struct _machine_hard_spi_obj_t { - mp_obj_base_t base; - const nrfx_spi_t * p_spi; // Driver instance - nrfx_spi_config_t * p_config; // pointer to volatile part -} machine_hard_spi_obj_t; - STATIC const nrfx_spi_t machine_spi_instances[] = { NRFX_SPI_INSTANCE(0), NRFX_SPI_INSTANCE(1), @@ -156,9 +122,9 @@ STATIC int spi_find(mp_obj_t id) { void spi_transfer(const machine_hard_spi_obj_t * self, size_t len, const void * src, void * dest) { nrfx_spi_xfer_desc_t xfer_desc = { .p_tx_buffer = src, - .tx_length = len, - .p_rx_buffer = dest, - .rx_length = len + .tx_length = len, + .p_rx_buffer = dest, + .rx_length = len }; nrfx_spi_xfer(self->p_spi, &xfer_desc, 0); diff --git a/ports/nrf/modules/machine/spi.h b/ports/nrf/modules/machine/spi.h index c6f64a19da2a7..3d1761a8dacc1 100644 --- a/ports/nrf/modules/machine/spi.h +++ b/ports/nrf/modules/machine/spi.h @@ -26,9 +26,49 @@ */ #include "py/obj.h" +#if NRFX_SPI_ENABLED +#include "nrfx_spi.h" +#else +#include "nrfx_spim.h" +#endif + +#if NRFX_SPIM_ENABLED + +#define nrfx_spi_t nrfx_spim_t +#define nrfx_spi_config_t nrfx_spim_config_t +#define nrfx_spi_xfer_desc_t nrfx_spim_xfer_desc_t + +#define NRFX_SPI_PIN_NOT_USED NRFX_SPIM_PIN_NOT_USED +#define NRFX_SPI_INSTANCE NRFX_SPIM_INSTANCE +#define NRF_SPI_BIT_ORDER_LSB_FIRST NRF_SPIM_BIT_ORDER_LSB_FIRST +#define NRF_SPI_BIT_ORDER_MSB_FIRST NRF_SPIM_BIT_ORDER_MSB_FIRST +#define NRF_SPI_MODE_0 NRF_SPIM_MODE_0 +#define NRF_SPI_MODE_1 NRF_SPIM_MODE_1 +#define NRF_SPI_MODE_2 NRF_SPIM_MODE_2 +#define NRF_SPI_MODE_3 NRF_SPIM_MODE_3 +#define NRF_SPI_FREQ_125K NRF_SPIM_FREQ_125K +#define NRF_SPI_FREQ_250K NRF_SPIM_FREQ_250K +#define NRF_SPI_FREQ_500K NRF_SPIM_FREQ_500K +#define NRF_SPI_FREQ_1M NRF_SPIM_FREQ_1M +#define NRF_SPI_FREQ_2M NRF_SPIM_FREQ_2M +#define NRF_SPI_FREQ_4M NRF_SPIM_FREQ_4M +#define NRF_SPI_FREQ_8M NRF_SPIM_FREQ_8M + +#define nrfx_spi_init nrfx_spim_init +#define nrfx_spi_uninit nrfx_spim_uninit +#define nrfx_spi_xfer nrfx_spim_xfer + +#endif // NRFX_SPIM_ENABLED + typedef struct _machine_hard_spi_obj_t machine_hard_spi_obj_t; extern const mp_obj_type_t machine_hard_spi_type; +typedef struct _machine_hard_spi_obj_t { + mp_obj_base_t base; + const nrfx_spi_t * p_spi; // Driver instance + nrfx_spi_config_t * p_config; // pointer to volatile part +} machine_hard_spi_obj_t; + void spi_init0(void); void spi_transfer(const machine_hard_spi_obj_t * self, size_t len, diff --git a/ports/nrf/modules/network/modnetwork.c b/ports/nrf/modules/network/modnetwork.c new file mode 100644 index 0000000000000..cf90a78b1a561 --- /dev/null +++ b/ports/nrf/modules/network/modnetwork.c @@ -0,0 +1,180 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 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 + +#include "py/objlist.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "lib/netutils/netutils.h" +#include "modnetwork.h" + +#if MICROPY_PY_NETWORK + +#if MICROPY_PY_LWIP + +#include "lwip/netif.h" +#include "lwip/timeouts.h" +#include "lwip/dns.h" +#include "lwip/dhcp.h" + +u32_t sys_now(void) { + return mp_hal_ticks_ms(); +} + +void pyb_lwip_poll(void) { + // Poll all the NICs for incoming data + for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { + if (netif->flags & NETIF_FLAG_LINK_UP) { + mod_network_nic_type_t *nic = netif->state; + nic->poll_callback(nic, netif); + } + } + // Run the lwIP internal updates + sys_check_timeouts(); +} + +#endif + +/// \module network - network configuration +/// +/// This module provides network drivers and routing configuration. + +void mod_network_init(void) { + mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0); +} + +void mod_network_deinit(void) { +} + +void mod_network_register_nic(mp_obj_t nic) { + for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { + if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) { + // nic already registered + return; + } + } + // nic not registered so add to list + mp_obj_list_append(MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)), nic); +} + +mp_obj_t mod_network_find_nic(const uint8_t *ip) { + // find a NIC that is suited to given IP address + for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { + mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; + // TODO check IP suitability here + //mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); + return nic; + } + + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); +} + +STATIC mp_obj_t network_route(void) { + return MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route); + +STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, + + #if MICROPY_PY_WIZNET5K + { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) }, + #endif + #if MICROPY_PY_CC3K + { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) }, + #endif + #if MICROPY_PY_CC31K + { MP_ROM_QSTR(MP_QSTR_CC31K), MP_ROM_PTR(&mod_network_nic_type_cc31k) }, + #endif + + { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); + +const mp_obj_module_t mp_module_network = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_network_globals, +}; + +/*******************************************************************************/ +// Implementations of network methods that can be used by any interface + +#if MICROPY_PY_LWIP + +mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + // Get IP addresses + const ip_addr_t *dns = dns_getserver(0); + mp_obj_t tuple[4] = { + netutils_format_ipv4_addr((uint8_t*)&netif->ip_addr, NETUTILS_BIG), + netutils_format_ipv4_addr((uint8_t*)&netif->netmask, NETUTILS_BIG), + netutils_format_ipv4_addr((uint8_t*)&netif->gw, NETUTILS_BIG), + netutils_format_ipv4_addr((uint8_t*)dns, NETUTILS_BIG), + }; + return mp_obj_new_tuple(4, tuple); + } else if (args[0] == MP_OBJ_NEW_QSTR(MP_QSTR_dhcp)) { + // Start the DHCP client + if (dhcp_supplied_address(netif)) { + dhcp_renew(netif); + } else { + dhcp_stop(netif); + dhcp_start(netif); + } + + // Wait for DHCP to get IP address + uint32_t start = mp_hal_ticks_ms(); + while (!dhcp_supplied_address(netif)) { + if (mp_hal_ticks_ms() - start > 10000) { + mp_raise_msg(&mp_type_OSError, "timeout waiting for DHCP to get IP address"); + } + mp_hal_delay_ms(100); + } + + return mp_const_none; + } else { + // Release and stop any existing DHCP + dhcp_release(netif); + dhcp_stop(netif); + // Set static IP addresses + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[0], 4, &items); + netutils_parse_ipv4_addr(items[0], (uint8_t*)&netif->ip_addr, NETUTILS_BIG); + netutils_parse_ipv4_addr(items[1], (uint8_t*)&netif->netmask, NETUTILS_BIG); + netutils_parse_ipv4_addr(items[2], (uint8_t*)&netif->gw, NETUTILS_BIG); + ip_addr_t dns; + netutils_parse_ipv4_addr(items[3], (uint8_t*)&dns, NETUTILS_BIG); + dns_setserver(0, &dns); + return mp_const_none; + } +} + +#endif + +#endif // MICROPY_PY_NETWORK diff --git a/ports/nrf/modules/network/modnetwork.h b/ports/nrf/modules/network/modnetwork.h new file mode 100644 index 0000000000000..79fda811f7c49 --- /dev/null +++ b/ports/nrf/modules/network/modnetwork.h @@ -0,0 +1,114 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 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_MODNETWORK_H +#define MICROPY_INCLUDED_STM32_MODNETWORK_H + +#define MOD_NETWORK_IPADDR_BUF_SIZE (4) + +#define MOD_NETWORK_AF_INET (2) +#define MOD_NETWORK_AF_INET6 (10) + +#define MOD_NETWORK_SOCK_STREAM (1) +#define MOD_NETWORK_SOCK_DGRAM (2) +#define MOD_NETWORK_SOCK_RAW (3) + +#define MOD_NETWORK_IPPROTO_TCP (1) +#define MOD_NETWORK_IPPROTO_UDP (2) +#define MOD_NETWORK_IPPROTO_SECURE (3) + +#if MICROPY_PY_LWIP + +struct netif; + +typedef struct _mod_network_nic_type_t { + mp_obj_base_t base; + void (*poll_callback)(void *data, struct netif *netif); +} mod_network_nic_type_t; + +extern const mp_obj_type_t mod_network_nic_type_wiznet5k; + +mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args); + +#else + +struct _mod_network_socket_obj_t; + +typedef struct _mod_network_nic_type_t { + mp_obj_type_t base; + + // API for non-socket operations + int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out, uint8_t family); + + // API for socket operations; return -1 on error + int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno); + void (*close)(struct _mod_network_socket_obj_t *socket); + int (*bind)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); + int (*listen)(struct _mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno); + int (*accept)(struct _mod_network_socket_obj_t *socket, struct _mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno); + int (*connect)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); + mp_uint_t (*send)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno); + mp_uint_t (*recv)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno); + mp_uint_t (*sendto)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); + mp_uint_t (*recvfrom)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); + int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); + int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); + int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); +} mod_network_nic_type_t; + +typedef struct _mod_network_socket_obj_t { + mp_obj_base_t base; + mp_obj_t nic; + mod_network_nic_type_t *nic_type; + union { + struct { + uint8_t domain; + uint8_t type; + int8_t fileno; + uint8_t proto; + } u_param; +#if MICROPY_PY_CC31K + int16_t sd; +#endif + mp_uint_t u_state; + }; +#if MICROPY_PY_CC31K + uint32_t timeout_ms; // 0 for no timeout + bool cert_req; +#endif +} mod_network_socket_obj_t; + +extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; +extern const mod_network_nic_type_t mod_network_nic_type_cc3k; +extern const mod_network_nic_type_t mod_network_nic_type_cc31k; + +#endif + +void mod_network_init(void); +void mod_network_deinit(void); +void mod_network_register_nic(mp_obj_t nic); +mp_obj_t mod_network_find_nic(const uint8_t *ip); + +#endif // MICROPY_INCLUDED_STM32_MODNETWORK_H diff --git a/ports/nrf/modules/network/modnwcc31k.c b/ports/nrf/modules/network/modnwcc31k.c new file mode 100644 index 0000000000000..7b4b695efa12b --- /dev/null +++ b/ports/nrf/modules/network/modnwcc31k.c @@ -0,0 +1,1749 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Daniel Campora + * + * 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 + +#include "py/mpconfig.h" + +#if (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) +#include "simplelink.h" +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mphal.h" +#include "py/mperrno.h" +#include "lib/timeutils/timeutils.h" +#include "lib/netutils/netutils.h" +#include "modnetwork.h" +#include "modnwcc31k.h" +//#include "pybrtc.h" +//#include "debug.h" +#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) +#include "serverstask.h" +#endif +//#include "mpexception.h" +//#include "antenna.h" + +#if MICROPY_PY_CC31K +#include "simplelink.h" +#endif // MICROPY_PY_CC31K + +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mphal.h" +#include "lib/netutils/netutils.h" +#include "modnetwork.h" +#include "modnwcc31k.h" +//#include "mpexception.h" + +#define WLAN_MAX_RX_SIZE 16000 +#define WLAN_MAX_TX_SIZE 1476 + +#define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \ + addr.sa_family = SL_AF_INET; \ + addr.sa_data[0] = port >> 8; \ + addr.sa_data[1] = port; \ + addr.sa_data[2] = ip[0]; \ + addr.sa_data[3] = ip[1]; \ + addr.sa_data[4] = ip[2]; \ + addr.sa_data[5] = ip[3]; + +#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \ + ip[0] = addr.sa_data[2]; \ + ip[1] = addr.sa_data[3]; \ + ip[2] = addr.sa_data[4]; \ + ip[3] = addr.sa_data[5]; + +#define SOCKET_TIMEOUT_QUANTA_MS (20) + +STATIC int convert_sl_errno(int sl_errno) { + return -sl_errno; +} + +// This function is left as non-static so it's not inlined. +int check_timedout(mod_network_socket_obj_t *s, int ret, uint32_t *timeout_ms, int *_errno) { + if (*timeout_ms == 0 || ret != SL_EAGAIN) { + if (s->timeout_ms > 0 && ret == SL_EAGAIN) { + *_errno = MP_ETIMEDOUT; + } else { + *_errno = convert_sl_errno(ret); + } + return -1; + } + mp_hal_delay_ms(SOCKET_TIMEOUT_QUANTA_MS); + if (*timeout_ms < SOCKET_TIMEOUT_QUANTA_MS) { + *timeout_ms = 0; + } else { + *timeout_ms -= SOCKET_TIMEOUT_QUANTA_MS; + } + return 0; +} + +STATIC int cc31k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { + uint32_t ip; + if (family == MOD_NETWORK_AF_INET) { + int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)SL_AF_INET); + out_ip[3] = ip; + out_ip[2] = ip >> 8; + out_ip[1] = ip >> 16; + out_ip[0] = ip >> 24; + return result; + } + return -1; +} + +STATIC int cc31k_socket_socket(mod_network_socket_obj_t *s, int *_errno) { + int domain; + if (s->u_param.domain == MOD_NETWORK_AF_INET) { + domain = SL_AF_INET; + } else { + *_errno = MP_EAFNOSUPPORT; + return -1; + } + + int type; + if (s->u_param.type == MOD_NETWORK_SOCK_STREAM) { + type = SL_SOCK_STREAM; + } else if (s->u_param.type == MOD_NETWORK_SOCK_DGRAM) { + type = SL_SOCK_DGRAM; + } else { + *_errno = MP_EINVAL; + return -1; + } + + int proto; + if (s->u_param.proto == MOD_NETWORK_IPPROTO_TCP) { + proto = SL_IPPROTO_TCP; + } else if (s->u_param.proto == MOD_NETWORK_IPPROTO_UDP) { + proto = SL_IPPROTO_UDP; + } else if (s->u_param.proto == MOD_NETWORK_IPPROTO_SECURE) { + proto = SL_SEC_SOCKET; + } else { + *_errno = MP_EINVAL; + return -1; + } + + int16_t sd = sl_Socket(domain, type, proto); + if (sd < 0) { + *_errno = sd; + return -1; + } + s->sd = sd; + return 0; +} + +STATIC void cc31k_socket_close(mod_network_socket_obj_t *s) { + // this is to prevent the finalizer to close a socket that failed when being created + if (s->sd >= 0) { + modusocket_socket_delete(s->sd); + sl_Close(s->sd); + s->sd = -1; + } +} + +STATIC int cc31k_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { + MAKE_SOCKADDR(addr, ip, port) + int ret = sl_Bind(s->sd, &addr, sizeof(addr)); + if (ret != 0) { + *_errno = ret; + return -1; + } + return 0; +} + +STATIC int cc31k_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) { + int ret = sl_Listen(s->sd, backlog); + if (ret != 0) { + *_errno = ret; + return -1; + } + return 0; +} + +STATIC int cc31k_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) { + // accept incoming connection + int16_t sd; + SlSockAddr_t addr; + SlSocklen_t addr_len = sizeof(addr); + + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + sd = sl_Accept(s->sd, &addr, &addr_len); + if (sd >= 0) { + // save the socket descriptor + s2->sd = sd; + // return ip and port + UNPACK_SOCKADDR(addr, ip, *port); + return 0; + } + if (check_timedout(s, sd, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC int cc31k_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { + MAKE_SOCKADDR(addr, ip, port) + uint32_t timeout_ms = s->timeout_ms; + + // For a non-blocking connect the CC3100 will return SL_EALREADY while the + // connection is in progress. + + for (;;) { + int ret = sl_Connect(s->sd, &addr, sizeof(addr)); + if (ret == 0) { + return 0; + } + + // Check if we are in non-blocking mode and the connection is in progress + if (s->timeout_ms == 0 && ret == SL_EALREADY) { + // To match BSD we return EINPROGRESS here + *_errno = MP_EINPROGRESS; + return -1; + } + + // We are in blocking mode, so if the connection isn't in progress then error out + if (ret != SL_EALREADY) { + *_errno = convert_sl_errno(ret); + return -1; + } + + if (check_timedout(s, SL_EAGAIN, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) { + if (len == 0) { + return 0; + } + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_Send(s->sd, (const void *)buf, len, 0); + if (ret > 0) { + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) { + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_Recv(s->sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0); + if (ret >= 0) { + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { + MAKE_SOCKADDR(addr, ip, port) + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_SendTo(s->sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr)); + if (ret >= 0) { + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC mp_uint_t cc31k_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { + SlSockAddr_t addr; + SlSocklen_t addr_len = sizeof(addr); + uint32_t timeout_ms = s->timeout_ms; + for (;;) { + int ret = sl_RecvFrom(s->sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len); + if (ret >= 0) { + UNPACK_SOCKADDR(addr, ip, *port); + return ret; + } + if (check_timedout(s, ret, &timeout_ms, _errno)) { + return -1; + } + } +} + +STATIC int cc31k_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { + int ret = sl_SetSockOpt(s->sd, level, opt, optval, optlen); + if (ret < 0) { + *_errno = ret; + return -1; + } + return 0; +} + +STATIC int cc31k_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) { + SlSockNonblocking_t option; + if (timeout_s == 0 || timeout_s == -1) { + if (timeout_s == 0) { + // set non-blocking mode + option.NonblockingEnabled = 1; + } else { + // set blocking mode + option.NonblockingEnabled = 0; + } + timeout_s = 0; + } else { + // synthesize timeout via non-blocking behaviour with a loop + option.NonblockingEnabled = 1; + } + + int ret = sl_SetSockOpt(s->sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option)); + if (ret != 0) { + *_errno = convert_sl_errno(ret); + return -1; + } + + s->timeout_ms = timeout_s * 1000; + return 0; +} + +STATIC int cc31k_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) { + mp_int_t ret; + if (request == MP_STREAM_POLL) { + mp_uint_t flags = arg; + ret = 0; + int32_t sd = s->sd; + + // init fds + SlFdSet_t rfds, wfds, xfds; + SL_FD_ZERO(&rfds); + SL_FD_ZERO(&wfds); + SL_FD_ZERO(&xfds); + + // set fds if needed + if (flags & MP_STREAM_POLL_RD) { + SL_FD_SET(sd, &rfds); + } + if (flags & MP_STREAM_POLL_WR) { + SL_FD_SET(sd, &wfds); + } + if (flags & MP_STREAM_POLL_HUP) { + SL_FD_SET(sd, &xfds); + } + + // call simplelink's select with minimum timeout + SlTimeval_t tv; + tv.tv_sec = 0; + tv.tv_usec = 1; + int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv); + + // check for errors + if (nfds == -1) { + *_errno = nfds; + return -1; + } + + // check return of select + if (SL_FD_ISSET(sd, &rfds)) { + ret |= MP_STREAM_POLL_RD; + } + if (SL_FD_ISSET(sd, &wfds)) { + ret |= MP_STREAM_POLL_WR; + } + if (SL_FD_ISSET(sd, &xfds)) { + ret |= MP_STREAM_POLL_HUP; + } + } else if (request == MP_STREAM_CLOSE) { + cc31k_socket_close(s); + ret = 0; + } else { + *_errno = MP_EINVAL; + ret = MP_STREAM_ERROR; + } + return ret; +} + +/****************************************************************************** + DEFINE PRIVATE CONSTANTS + ******************************************************************************/ +#define MOD_NETWORK_MAX_SOCKETS 10 + +/****************************************************************************** + DEFINE PRIVATE TYPES + ******************************************************************************/ +typedef struct { + int16_t sd; + bool user; +} modusocket_sock_t; + +/****************************************************************************** + DEFINE PRIVATE DATA + ******************************************************************************/ +STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, + {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}}; + +/****************************************************************************** + DEFINE PUBLIC FUNCTIONS + ******************************************************************************/ +__attribute__ ((section (".boot"))) +void modusocket_pre_init (void) { +} + +void modusocket_socket_add (int16_t sd, bool user) { + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd < 0) { + modusocket_sockets[i].sd = sd; + modusocket_sockets[i].user = user; + break; + } + } +} + +void modusocket_socket_delete (int16_t sd) { + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd == sd) { + modusocket_sockets[i].sd = -1; + break; + } + } +} + +void modusocket_enter_sleep (void) { + SlFdSet_t socketset; + int16_t maxfd = 0; + + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + int16_t sd; + if ((sd = modusocket_sockets[i].sd) >= 0) { + SL_FD_SET(sd, &socketset); + maxfd = (maxfd > sd) ? maxfd : sd; + } + } + + if (maxfd > 0) { + // wait for any of the sockets to become ready... + sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL); + } +} + +void modusocket_close_all_user_sockets (void) { + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) { + sl_Close(modusocket_sockets[i].sd); + modusocket_sockets[i].sd = -1; + } + } +} + +/****************************************************************************** + DEFINE TYPES + ******************************************************************************/ +// Status bits - These are used to set/reset the corresponding bits in a given variable +typedef enum{ + STATUS_BIT_NWP_INIT = 0, // If this bit is set: Network Processor is + // powered up + + STATUS_BIT_CONNECTION, // If this bit is set: the device is connected to + // the AP or client is connected to device (AP) + + STATUS_BIT_IP_LEASED, // If this bit is set: the device has leased IP to + // any connected client + + STATUS_BIT_IP_ACQUIRED, // If this bit is set: the device has acquired an IP + + STATUS_BIT_SMARTCONFIG_START, // If this bit is set: the SmartConfiguration + // process is started from SmartConfig app + + STATUS_BIT_P2P_DEV_FOUND, // If this bit is set: the device (P2P mode) + // found any p2p-device in scan + + STATUS_BIT_P2P_REQ_RECEIVED, // If this bit is set: the device (P2P mode) + // found any p2p-negotiation request + + STATUS_BIT_CONNECTION_FAILED, // If this bit is set: the device(P2P mode) + // connection to client(or reverse way) is failed + + STATUS_BIT_PING_DONE // If this bit is set: the device has completed + // the ping operation +} e_StatusBits; + +/****************************************************************************** + DEFINE CONSTANTS + ******************************************************************************/ +#define CLR_STATUS_BIT_ALL(status) (status = 0) +#define SET_STATUS_BIT(status, bit) (status |= ( 1 << (bit))) +#define CLR_STATUS_BIT(status, bit) (status &= ~(1 << (bit))) +#define GET_STATUS_BIT(status, bit) (0 != (status & (1 << (bit)))) + +#define IS_NW_PROCSR_ON(status) GET_STATUS_BIT(status, STATUS_BIT_NWP_INIT) +#define IS_CONNECTED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION) +#define IS_IP_LEASED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_LEASED) +#define IS_IP_ACQUIRED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_ACQUIRED) +#define IS_SMART_CFG_START(status) GET_STATUS_BIT(status, STATUS_BIT_SMARTCONFIG_START) +#define IS_P2P_DEV_FOUND(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_DEV_FOUND) +#define IS_P2P_REQ_RCVD(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_REQ_RECEIVED) +#define IS_CONNECT_FAILED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION_FAILED) +#define IS_PING_DONE(status) GET_STATUS_BIT(status, STATUS_BIT_PING_DONE) + +#define MODWLAN_SL_SCAN_ENABLE 1 +#define MODWLAN_SL_SCAN_DISABLE 0 +#define MODWLAN_SL_MAX_NETWORKS 20 + +#define MODWLAN_MAX_NETWORKS 20 +#define MODWLAN_SCAN_PERIOD_S 3600 // 1 hour +#define MODWLAN_WAIT_FOR_SCAN_MS 1050 +#define MODWLAN_CONNECTION_WAIT_MS 2 + +#define ASSERT_ON_ERROR(x) ASSERT((x) >= 0) + +const char mpexception_value_invalid_arguments[] = "invalid argument(s) value"; +const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type"; +const char mpexception_uncaught[] = "uncaught exception"; + +#if defined(DEBUG) +#define ASSERT(expr) assert(expr) +#else +#define ASSERT(expr) (void)(expr) +#endif + +/****************************************************************************** + DECLARE PRIVATE DATA + ******************************************************************************/ +STATIC wlan_obj_t wlan_obj = { + .mode = -1, + .status = 0, + .ip = 0, + .auth = MICROPY_PORT_WLAN_AP_SECURITY, + .channel = MICROPY_PORT_WLAN_AP_CHANNEL, + .ssid = MICROPY_PORT_WLAN_AP_SSID, + .key = MICROPY_PORT_WLAN_AP_KEY, + .mac = {0}, + //.ssid_o = {0}, + //.bssid = {0}, + #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + .servers_enabled = false, + #endif +}; + +//STATIC const mp_irq_methods_t wlan_irq_methods; + +/****************************************************************************** + DECLARE PUBLIC DATA + ******************************************************************************/ +#ifdef SL_PLATFORM_MULTI_THREADED +OsiLockObj_t wlan_LockObj; +#endif + +/****************************************************************************** + DECLARE PRIVATE FUNCTIONS + ******************************************************************************/ +STATIC void wlan_clear_data (void); +STATIC void wlan_reenable (SlWlanMode_t mode); +STATIC void wlan_servers_start (void); +STATIC void wlan_servers_stop (void); +STATIC void wlan_reset (void); +STATIC void wlan_validate_mode (uint mode); +STATIC void wlan_set_mode (uint mode); +STATIC void wlan_validate_ssid_len (uint32_t len); +STATIC void wlan_set_ssid (const char *ssid, uint8_t len, bool add_mac); +STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len); +STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len); +STATIC void wlan_validate_channel (uint8_t channel); +STATIC void wlan_set_channel (uint8_t channel); +#if MICROPY_HW_ANTENNA_DIVERSITY +STATIC void wlan_validate_antenna (uint8_t antenna); +STATIC void wlan_set_antenna (uint8_t antenna); +#endif +STATIC void wlan_sl_disconnect (void); +STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, + const char* key, uint32_t key_len, int32_t timeout); +STATIC void wlan_get_sl_mac (void); +STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out); +//STATIC void wlan_lpds_irq_enable (mp_obj_t self_in); +//STATIC void wlan_lpds_irq_disable (mp_obj_t self_in); +STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid); + +//***************************************************************************** +// +//! \brief The Function Handles WLAN Events +//! +//! \param[in] pWlanEvent - Pointer to WLAN Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) { + if (!pWlanEvent) { + return; + } + + switch(pWlanEvent->Event) + { + case SL_WLAN_CONNECT_EVENT: + { + //slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected; + // copy the new connection data + //memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH); + //memcpy(wlan_obj.ssid_o, pEventData->ssid_name, pEventData->ssid_len); + //wlan_obj.ssid_o[pEventData->ssid_len] = '\0'; + SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); + #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + // we must reset the servers in case that the last connection + // was lost without any notification being received + servers_reset(); + #endif + } + break; + case SL_WLAN_DISCONNECT_EVENT: + CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); + CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED); + #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + servers_reset(); + servers_wlan_cycle_power(); + #endif + break; + case SL_WLAN_STA_CONNECTED_EVENT: + { + //slPeerInfoAsyncResponse_t *pEventData = &pWlanEvent->EventData.APModeStaConnected; + // get the mac address and name of the connected device + //memcpy(wlan_obj.bssid, pEventData->mac, SL_BSSID_LENGTH); + //memcpy(wlan_obj.ssid_o, pEventData->go_peer_device_name, pEventData->go_peer_device_name_len); + //wlan_obj.ssid_o[pEventData->go_peer_device_name_len] = '\0'; + SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); + #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + // we must reset the servers in case that the last connection + // was lost without any notification being received + servers_reset(); + #endif + } + break; + case SL_WLAN_STA_DISCONNECTED_EVENT: + CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); + #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + servers_reset(); + servers_wlan_cycle_power(); + #endif + break; + case SL_WLAN_P2P_DEV_FOUND_EVENT: + // TODO + break; + case SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT: + // TODO + break; + case SL_WLAN_CONNECTION_FAILED_EVENT: + // TODO + break; + default: + break; + } +} + +//***************************************************************************** +// +//! \brief This function handles network events such as IP acquisition, IP +//! leased, IP released etc. +//! +//! \param[in] pNetAppEvent - Pointer to NetApp Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent) { + if(!pNetAppEvent) { + return; + } + + switch(pNetAppEvent->Event) + { + case SL_NETAPP_IPV4_IPACQUIRED_EVENT: + { + SlIpV4AcquiredAsync_t *pEventData = NULL; + + SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED); + + // Ip Acquired Event Data + pEventData = &pNetAppEvent->EventData.ipAcquiredV4; + + // Get the ip + wlan_obj.ip = pEventData->ip; + } + break; + case SL_NETAPP_IPV6_IPACQUIRED_EVENT: + break; + case SL_NETAPP_IP_LEASED_EVENT: + break; + case SL_NETAPP_IP_RELEASED_EVENT: + break; + default: + break; + } +} + +//***************************************************************************** +// +//! \brief This function handles HTTP server events +//! +//! \param[in] pServerEvent - Contains the relevant event information +//! \param[in] pServerResponse - Should be filled by the user with the +//! relevant response information +//! +//! \return None +//! +//**************************************************************************** +void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent, SlHttpServerResponse_t *pHttpResponse) { + if (!pHttpEvent) { + return; + } + + switch (pHttpEvent->Event) { + case SL_NETAPP_HTTPGETTOKENVALUE_EVENT: + break; + case SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT: + break; + default: + break; + } +} + +//***************************************************************************** +// +//! \brief This function handles General Events +//! +//! \param[in] pDevEvent - Pointer to General Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent) { + if (!pDevEvent) { + return; + } +} + +//***************************************************************************** +// +//! This function handles socket events indication +//! +//! \param[in] pSock - Pointer to Socket Event Info +//! +//! \return None +//! +//***************************************************************************** +void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) { + if (!pSock) { + return; + } + + switch( pSock->Event ) { + case SL_SOCKET_TX_FAILED_EVENT: + switch( pSock->socketAsyncEvent.SockTxFailData.status) { + case SL_ECLOSE: + break; + default: + break; + } + break; + case SL_SOCKET_ASYNC_EVENT: + switch(pSock->socketAsyncEvent.SockAsyncData.type) { + case SSL_ACCEPT: + break; + case RX_FRAGMENTATION_TOO_BIG: + break; + case OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED: + break; + default: + break; + } + break; + default: + break; + } +} + +//***************************************************************************** +// SimpleLink Asynchronous Event Handlers -- End +//***************************************************************************** + +__attribute__ ((section (".boot"))) +void wlan_pre_init (void) { + // create the wlan lock + #ifdef SL_PLATFORM_MULTI_THREADED + ASSERT(OSI_OK == sl_LockObjCreate(&wlan_LockObj, "WlanLock")); + #endif +} + +void wlan_first_start (void) { + if (wlan_obj.mode < 0) { + CLR_STATUS_BIT_ALL(wlan_obj.status); + wlan_obj.mode = sl_Start(0, 0, 0); + #ifdef SL_PLATFORM_MULTI_THREADED + sl_LockObjUnlock (&wlan_LockObj); + #endif + } + + // get the mac address + wlan_get_sl_mac(); +} + +void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth, const char *key, uint8_t key_len, + uint8_t channel, uint8_t antenna, bool add_mac) { + + // stop the servers + wlan_servers_stop(); + + // do a basic start + wlan_first_start(); + + // close any active connections + wlan_sl_disconnect(); + + // Remove all profiles + ASSERT_ON_ERROR(sl_WlanProfileDel(0xFF)); + + // Enable the DHCP client + uint8_t value = 1; + ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, 1, 1, &value)); + + // Set PM policy to normal + ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_PM, SL_NORMAL_POLICY, NULL, 0)); + + // Unregister mDNS services + ASSERT_ON_ERROR(sl_NetAppMDNSUnRegisterService(0, 0)); + + // Stop the internal HTTP server + sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); + + // Remove all 64 filters (8 * 8) + _WlanRxFilterOperationCommandBuff_t RxFilterIdMask; + memset ((void *)&RxFilterIdMask, 0 ,sizeof(RxFilterIdMask)); + memset(RxFilterIdMask.FilterIdMask, 0xFF, 8); + ASSERT_ON_ERROR(sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (_u8 *)&RxFilterIdMask, sizeof(_WlanRxFilterOperationCommandBuff_t))); + +#if MICROPY_HW_ANTENNA_DIVERSITY + // set the antenna type + wlan_set_antenna (antenna); +#endif + + // switch to the requested mode + wlan_set_mode(mode); + + // stop and start again (we need to in the propper mode from now on) + wlan_reenable(mode); + + // Set Tx power level for station or AP mode + // Number between 0-15, as dB offset from max power - 0 will set max power + uint8_t ucPower = 0; + if (mode == ROLE_AP) { + ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_AP_TX_POWER, sizeof(ucPower), + (unsigned char *)&ucPower)); + + // configure all parameters + wlan_set_ssid (ssid, ssid_len, add_mac); + wlan_set_security (auth, key, key_len); + wlan_set_channel (channel); + + // set the country + _u8* country = (_u8*)"EU"; + ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, country)); + + SlNetCfgIpV4Args_t ipV4; + ipV4.ipV4 = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 IP address + ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP + ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 Default gateway address + ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 DNS server address + ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, + sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); + + SlNetAppDhcpServerBasicOpt_t dhcpParams; + dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address + dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,2); // first IP Address for allocation. + dhcpParams.ipv4_addr_last = SL_IPV4_VAL(192,168,1,254); // last IP Address for allocation. + ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // Stop DHCP server before settings + ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, + sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters + ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // Start DHCP server with new settings + + // stop and start again + wlan_reenable(mode); + } else { // STA and P2P modes + ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, + sizeof(ucPower), (unsigned char *)&ucPower)); + // set connection policy to Auto + Fast (tries to connect to the last connected AP) + ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 1, 0, 0, 0), NULL, 0)); + } + + // set current time and date (needed to validate certificates) + //wlan_set_current_time (pyb_rtc_get_seconds()); + + // start the servers before returning + //wlan_servers_start(); +} + +void wlan_update(void) { +#ifndef SL_PLATFORM_MULTI_THREADED + _SlTaskEntry(); +#endif +} + +void wlan_stop (uint32_t timeout) { + wlan_servers_stop(); + #ifdef SL_PLATFORM_MULTI_THREADED + sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); + #endif + sl_Stop(timeout); + wlan_clear_data(); + wlan_obj.mode = -1; +} + +void wlan_get_mac (uint8_t *macAddress) { + if (macAddress) { + memcpy (macAddress, wlan_obj.mac, SL_MAC_ADDR_LEN); + } +} + +void wlan_get_ip (uint32_t *ip) { + if (ip) { + *ip = IS_IP_ACQUIRED(wlan_obj.status) ? wlan_obj.ip : 0; + } +} + +bool wlan_is_connected (void) { + return (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION) && + (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED) || wlan_obj.mode != ROLE_STA)); +} + +void wlan_set_current_time (uint32_t seconds_since_2000) { + timeutils_struct_time_t tm; + timeutils_seconds_since_2000_to_struct_time(seconds_since_2000, &tm); + + SlDateTime_t sl_datetime = {0}; + sl_datetime.sl_tm_day = tm.tm_mday; + sl_datetime.sl_tm_mon = tm.tm_mon; + sl_datetime.sl_tm_year = tm.tm_year; + sl_datetime.sl_tm_hour = tm.tm_hour; + sl_datetime.sl_tm_min = tm.tm_min; + sl_datetime.sl_tm_sec = tm.tm_sec; + sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, sizeof(SlDateTime_t), (_u8 *)(&sl_datetime)); +} + +void wlan_off_on (void) { + // no need to lock the WLAN object on every API call since the servers and the MicroPtyhon + // task have the same priority + wlan_reenable(wlan_obj.mode); +} + +//***************************************************************************** +// DEFINE STATIC FUNCTIONS +//***************************************************************************** + +STATIC void wlan_clear_data (void) { + CLR_STATUS_BIT_ALL(wlan_obj.status); + wlan_obj.ip = 0; + //memset(wlan_obj.ssid_o, 0, sizeof(wlan_obj.ssid)); + //memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid)); +} + +STATIC void wlan_reenable (SlWlanMode_t mode) { + // stop and start again + #ifdef SL_PLATFORM_MULTI_THREADED + sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); + #endif + sl_Stop(SL_STOP_TIMEOUT); + wlan_clear_data(); + wlan_obj.mode = sl_Start(0, 0, 0); + #ifdef SL_PLATFORM_MULTI_THREADED + sl_LockObjUnlock (&wlan_LockObj); + #endif + ASSERT (wlan_obj.mode == mode); +} + +STATIC void wlan_servers_start (void) { +#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + // start the servers if they were enabled before + if (wlan_obj.servers_enabled) { + servers_start(); + } +#endif +} + +STATIC void wlan_servers_stop (void) { +#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + // Stop all other processes using the wlan engine + if ((wlan_obj.servers_enabled = servers_are_enabled())) { + servers_stop(); + } +#endif +} + +STATIC void wlan_reset (void) { + wlan_servers_stop(); + wlan_reenable (wlan_obj.mode); + wlan_servers_start(); +} + +STATIC void wlan_validate_mode (uint mode) { + if (mode != ROLE_STA && mode != ROLE_AP) { + mp_raise_ValueError(mpexception_value_invalid_arguments); + } +} + +STATIC void wlan_set_mode (uint mode) { + wlan_obj.mode = mode; + ASSERT_ON_ERROR(sl_WlanSetMode(mode)); +} + +STATIC void wlan_validate_ssid_len (uint32_t len) { + if (len > MODWLAN_SSID_LEN_MAX) { + mp_raise_ValueError(mpexception_value_invalid_arguments); + } +} + +STATIC void wlan_set_ssid (const char *ssid, uint8_t len, bool add_mac) { + if (ssid != NULL) { + // save the ssid + memcpy(&wlan_obj.ssid, ssid, len); + // append the last 2 bytes of the MAC address, since the use of this functionality is under our control + // we can assume that the lenght of the ssid is less than (32 - 5) + if (add_mac) { + snprintf((char *)&wlan_obj.ssid[len], sizeof(wlan_obj.ssid) - len, "-%02x%02x", wlan_obj.mac[4], wlan_obj.mac[5]); + len += 5; + } + wlan_obj.ssid[len] = '\0'; + ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID, len, (unsigned char *)wlan_obj.ssid)); + } +} + +STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len) { + if (auth != SL_SEC_TYPE_WEP && auth != SL_SEC_TYPE_WPA_WPA2) { + goto invalid_args; + } + if (auth == SL_SEC_TYPE_WEP) { + for (mp_uint_t i = strlen(key); i > 0; i--) { + if (!unichar_isxdigit(*key++)) { + goto invalid_args; + } + } + } + return; + +invalid_args: + mp_raise_ValueError(mpexception_value_invalid_arguments); +} + +STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) { + wlan_obj.auth = auth; + ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, sizeof(uint8_t), &auth)); + if (key != NULL) { + memcpy(&wlan_obj.key, key, len); + wlan_obj.key[len] = '\0'; + if (auth == SL_SEC_TYPE_WEP) { + _u8 wep_key[32]; + wlan_wep_key_unhexlify(key, (char *)&wep_key); + key = (const char *)&wep_key; + len /= 2; + } + ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, len, (unsigned char *)key)); + } else { + wlan_obj.key[0] = '\0'; + } +} + +STATIC void wlan_validate_channel (uint8_t channel) { + if (channel < 1 || channel > 11) { + mp_raise_ValueError(mpexception_value_invalid_arguments); + } +} + +STATIC void wlan_set_channel (uint8_t channel) { + wlan_obj.channel = channel; + ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, &channel)); +} + +#if MICROPY_HW_ANTENNA_DIVERSITY +STATIC void wlan_validate_antenna (uint8_t antenna) { + if (antenna != ANTENNA_TYPE_INTERNAL && antenna != ANTENNA_TYPE_EXTERNAL) { + mp_raise_ValueError(mpexception_value_invalid_arguments); + } +} + +STATIC void wlan_set_antenna (uint8_t antenna) { + wlan_obj.antenna = antenna; + antenna_select(antenna); +} +#endif + +STATIC void wlan_sl_disconnect (void) { + // Device in station-mode. Disconnect previous connection if any + // The function returns 0 if 'Disconnected done', negative number if already + // disconnected Wait for 'disconnection' event if 0 is returned, Ignore + // other return-codes + if (0 == sl_WlanDisconnect()) { + while (IS_CONNECTED(wlan_obj.status)) { + mp_hal_delay_ms(MODWLAN_CONNECTION_WAIT_MS); + wlan_update(); + } + } +} + +STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, + const char* key, uint32_t key_len, int32_t timeout) { + SlSecParams_t secParams; + secParams.Key = (_i8*)key; + secParams.KeyLen = ((key != NULL) ? key_len : 0); + secParams.Type = sec; + + // first close any active connections + wlan_sl_disconnect(); + + if (!sl_WlanConnect((_i8*)ssid, ssid_len, (_u8*)bssid, &secParams, NULL)) { + // wait for the WLAN Event + uint32_t waitForConnectionMs = 0; + while (timeout && !IS_CONNECTED(wlan_obj.status)) { + mp_hal_delay_ms(MODWLAN_CONNECTION_WAIT_MS); + waitForConnectionMs += MODWLAN_CONNECTION_WAIT_MS; + if (timeout > 0 && waitForConnectionMs > timeout) { + return MODWLAN_ERROR_TIMEOUT; + } + wlan_update(); + } + return MODWLAN_OK; + } + return MODWLAN_ERROR_INVALID_PARAMS; +} + +STATIC void wlan_get_sl_mac (void) { + // Get the MAC address + uint8_t macAddrLen = SL_MAC_ADDR_LEN; + sl_NetCfgGet(SL_MAC_ADDRESS_GET, NULL, &macAddrLen, wlan_obj.mac); +} + +STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out) { + byte hex_byte = 0; + for (mp_uint_t i = strlen(key); i > 0 ; i--) { + hex_byte += unichar_xdigit_value(*key++); + if (i & 1) { + hex_byte <<= 4; + } else { + *key_out++ = hex_byte; + hex_byte = 0; + } + } +} +/* +STATIC void wlan_lpds_irq_enable (mp_obj_t self_in) { + wlan_obj_t *self = self_in; + self->irq_enabled = true; +} + +STATIC void wlan_lpds_irq_disable (mp_obj_t self_in) { + wlan_obj_t *self = self_in; + self->irq_enabled = false; +} + +STATIC int wlan_irq_flags (mp_obj_t self_in) { + wlan_obj_t *self = self_in; + return self->irq_flags; +} +*/ +STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid) { + for (int i = 0; i < nets->len; i++) { + // index 1 in the list is the bssid + mp_obj_str_t *_bssid = (mp_obj_str_t *)((mp_obj_tuple_t *)nets->items[i])->items[1]; + if (!memcmp (_bssid->data, bssid, SL_BSSID_LENGTH)) { + return false; + } + } + return true; +} + +/******************************************************************************/ +// MicroPython bindings; WLAN class + +/// \class WLAN - WiFi driver + +STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) { + // get the mode + int8_t mode = args[0].u_int; + wlan_validate_mode(mode); + + // get the ssid + size_t ssid_len = 0; + const char *ssid = NULL; + if (args[1].u_obj != NULL) { + ssid = mp_obj_str_get_data(args[1].u_obj, &ssid_len); + wlan_validate_ssid_len(ssid_len); + } + + // get the auth config + uint8_t auth = SL_SEC_TYPE_OPEN; + size_t key_len = 0; + const char *key = NULL; + if (args[2].u_obj != mp_const_none) { + mp_obj_t *sec; + mp_obj_get_array_fixed_n(args[2].u_obj, 2, &sec); + auth = mp_obj_get_int(sec[0]); + key = mp_obj_str_get_data(sec[1], &key_len); + wlan_validate_security(auth, key, key_len); + } + + // get the channel + uint8_t channel = args[3].u_int; + wlan_validate_channel(channel); + + // get the antenna type + uint8_t antenna = 0; +#if MICROPY_HW_ANTENNA_DIVERSITY + antenna = args[4].u_int; + wlan_validate_antenna(antenna); +#endif + + // initialize the wlan subsystem + wlan_sl_init(mode, (const char *)ssid, ssid_len, auth, (const char *)key, key_len, channel, antenna, false); + + return mp_const_none; +} + +STATIC const mp_arg_t wlan_init_args[] = { + { MP_QSTR_spi, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_cs, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_en, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_irq, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mode, MP_ARG_INT, {.u_int = ROLE_STA} }, + { MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + #if MICROPY_HW_ANTENNA_DIVERSITY + { MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} }, + #endif +}; + +STATIC mp_obj_t cc31k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // parse args + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); + mp_arg_val_t args[MP_ARRAY_SIZE(wlan_init_args)]; + mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), wlan_init_args, args); + + // setup the object + wlan_obj_t *self = &wlan_obj; + self->base.type = (mp_obj_t)&mod_network_nic_type_cc31k; + + // set the pins to use + cc3100_drv_init( + args[0].u_obj, + pin_find(args[1].u_obj), + pin_find(args[2].u_obj), + pin_find(args[3].u_obj) + ); + + // start the peripheral + wlan_init_helper(self, &args[4]); + + // register with network module + mod_network_register_nic((mp_obj_t)self); + + return (mp_obj_t)self; +} + +STATIC mp_obj_t wlan_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(wlan_init_args) - 1]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &wlan_init_args[1], args); + return wlan_init_helper(pos_args[0], args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_init_obj, 1, wlan_init); + +STATIC mp_obj_t wlan_scan(mp_obj_t self_in) { + STATIC const qstr wlan_scan_info_fields[] = { + MP_QSTR_ssid, MP_QSTR_bssid, MP_QSTR_sec, MP_QSTR_channel, MP_QSTR_rssi + }; + + // check for correct wlan mode + if (wlan_obj.mode == ROLE_AP) { + mp_raise_OSError(MP_EPERM); + } + + Sl_WlanNetworkEntry_t wlanEntry; + mp_obj_t nets = mp_obj_new_list(0, NULL); + uint8_t _index = 0; + + // trigger a new network scan + uint32_t scanSeconds = MODWLAN_SCAN_PERIOD_S; + ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_SCAN , MODWLAN_SL_SCAN_ENABLE, (_u8 *)&scanSeconds, sizeof(scanSeconds))); + + // wait for the scan to complete + mp_hal_delay_ms(MODWLAN_WAIT_FOR_SCAN_MS); + + do { + if (sl_WlanGetNetworkList(_index++, 1, &wlanEntry) <= 0) { + break; + } + + // we must skip any duplicated results + if (!wlan_scan_result_is_unique(nets, wlanEntry.bssid)) { + continue; + } + + mp_obj_t tuple[5]; + tuple[0] = mp_obj_new_str((const char *)wlanEntry.ssid, wlanEntry.ssid_len); + tuple[1] = mp_obj_new_bytes((const byte *)wlanEntry.bssid, SL_BSSID_LENGTH); + // 'normalize' the security type + if (wlanEntry.sec_type > 2) { + wlanEntry.sec_type = 2; + } + tuple[2] = mp_obj_new_int(wlanEntry.sec_type); + tuple[3] = mp_const_none; + tuple[4] = mp_obj_new_int(wlanEntry.rssi); + + // add the network to the list + mp_obj_list_append(nets, mp_obj_new_attrtuple(wlan_scan_info_fields, 5, tuple)); + + } while (_index < MODWLAN_SL_MAX_NETWORKS); + + return nets; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan); + +STATIC mp_obj_t wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + STATIC const mp_arg_t allowed_args[] = { + { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, }, + { MP_QSTR_auth, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + // check for the correct wlan mode + if (wlan_obj.mode == ROLE_AP) { + mp_raise_OSError(MP_EPERM); + } + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // get the ssid + size_t ssid_len; + const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len); + wlan_validate_ssid_len(ssid_len); + + // get the auth config + uint8_t auth = SL_SEC_TYPE_OPEN; + size_t key_len = 0; + const char *key = NULL; + if (args[1].u_obj != mp_const_none) { + mp_obj_t *sec; + mp_obj_get_array_fixed_n(args[1].u_obj, 2, &sec); + auth = mp_obj_get_int(sec[0]); + key = mp_obj_str_get_data(sec[1], &key_len); + wlan_validate_security(auth, key, key_len); + + // convert the wep key if needed + if (auth == SL_SEC_TYPE_WEP) { + _u8 wep_key[32]; + wlan_wep_key_unhexlify(key, (char *)&wep_key); + key = (const char *)&wep_key; + key_len /= 2; + } + } + + // get the bssid + const char *bssid = NULL; + if (args[2].u_obj != mp_const_none) { + bssid = mp_obj_str_get_str(args[2].u_obj); + } + + // get the timeout + int32_t timeout = -1; + if (args[3].u_obj != mp_const_none) { + timeout = mp_obj_get_int(args[3].u_obj); + } + + // connect to the requested access point + modwlan_Status_t status; + status = wlan_do_connect (ssid, ssid_len, bssid, auth, key, key_len, timeout); + if (status == MODWLAN_ERROR_TIMEOUT) { + mp_raise_OSError(MP_ETIMEDOUT); + } else if (status == MODWLAN_ERROR_INVALID_PARAMS) { + mp_raise_ValueError(mpexception_value_invalid_arguments); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_connect_obj, 1, wlan_connect); + +STATIC mp_obj_t wlan_disconnect(mp_obj_t self_in) { + wlan_sl_disconnect(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_disconnect_obj, wlan_disconnect); + +STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) { + return wlan_is_connected() ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_isconnected_obj, wlan_isconnected); + +STATIC mp_obj_t wlan_ifconfig(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + STATIC const mp_arg_t wlan_ifconfig_args[] = { + { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_config, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(wlan_ifconfig_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), wlan_ifconfig_args, args); + + // check the interface id + if (args[0].u_int != 0) { + mp_raise_OSError(MP_EPERM); + } + + // get the configuration + if (args[1].u_obj == MP_OBJ_NULL) { + // get + unsigned char len = sizeof(SlNetCfgIpV4Args_t); + unsigned char dhcpIsOn; + SlNetCfgIpV4Args_t ipV4; + sl_NetCfgGet(SL_IPV4_STA_P2P_CL_GET_INFO, &dhcpIsOn, &len, (uint8_t *)&ipV4); + + mp_obj_t ifconfig[4] = { + netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4, NETUTILS_LITTLE), + netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE), + netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4Gateway, NETUTILS_LITTLE), + netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4DnsServer, NETUTILS_LITTLE) + }; + return mp_obj_new_tuple(4, ifconfig); + } else { // set the configuration + if (MP_OBJ_IS_TYPE(args[1].u_obj, &mp_type_tuple)) { + // set a static ip + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[1].u_obj, 4, &items); + + SlNetCfgIpV4Args_t ipV4; + netutils_parse_ipv4_addr(items[0], (uint8_t *)&ipV4.ipV4, NETUTILS_LITTLE); + netutils_parse_ipv4_addr(items[1], (uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE); + netutils_parse_ipv4_addr(items[2], (uint8_t *)&ipV4.ipV4Gateway, NETUTILS_LITTLE); + netutils_parse_ipv4_addr(items[3], (uint8_t *)&ipV4.ipV4DnsServer, NETUTILS_LITTLE); + + if (wlan_obj.mode == ROLE_AP) { + ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); + SlNetAppDhcpServerBasicOpt_t dhcpParams; + dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address + dhcpParams.ipv4_addr_start = ipV4.ipV4 + 1; // first IP Address for allocation. + dhcpParams.ipv4_addr_last = (ipV4.ipV4 & 0xFFFFFF00) + 254; // last IP Address for allocation. + ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // stop DHCP server before settings + ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, + sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters + ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // start DHCP server with new settings + } else { + ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); + } + } else { + // check for the correct string + const char *mode = mp_obj_str_get_str(args[1].u_obj); + if (strcmp("dhcp", mode)) { + mp_raise_ValueError(mpexception_value_invalid_arguments); + } + + // only if we are not in AP mode + if (wlan_obj.mode != ROLE_AP) { + _u8 val = 1; + sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, 1, &val); + } + } + // config values have changed, so reset + wlan_reset(); + // set current time and date (needed to validate certificates) + //wlan_set_current_time (pyb_rtc_get_seconds()); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_ifconfig_obj, 1, wlan_ifconfig); + +STATIC mp_obj_t wlan_mode(size_t n_args, const mp_obj_t *args) { + wlan_obj_t *self = args[0]; + if (n_args == 1) { + return mp_obj_new_int(self->mode); + } else { + uint mode = mp_obj_get_int(args[1]); + wlan_validate_mode(mode); + wlan_set_mode(mode); + wlan_reset(); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mode_obj, 1, 2, wlan_mode); + +STATIC mp_obj_t wlan_ssid(size_t n_args, const mp_obj_t *args) { + wlan_obj_t *self = args[0]; + if (n_args == 1) { + return mp_obj_new_str((const char *)self->ssid, strlen((const char *)self->ssid)); + } else { + size_t len; + const char *ssid = mp_obj_str_get_data(args[1], &len); + wlan_validate_ssid_len(len); + wlan_set_ssid(ssid, len, false); + wlan_reset(); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_ssid_obj, 1, 2, wlan_ssid); + +STATIC mp_obj_t wlan_auth(size_t n_args, const mp_obj_t *args) { + wlan_obj_t *self = args[0]; + if (n_args == 1) { + if (self->auth == SL_SEC_TYPE_OPEN) { + return mp_const_none; + } else { + mp_obj_t security[2]; + security[0] = mp_obj_new_int(self->auth); + security[1] = mp_obj_new_str((const char *)self->key, strlen((const char *)self->key)); + return mp_obj_new_tuple(2, security); + } + } else { + // get the auth config + uint8_t auth = SL_SEC_TYPE_OPEN; + size_t key_len = 0; + const char *key = NULL; + if (args[1] != mp_const_none) { + mp_obj_t *sec; + mp_obj_get_array_fixed_n(args[1], 2, &sec); + auth = mp_obj_get_int(sec[0]); + key = mp_obj_str_get_data(sec[1], &key_len); + wlan_validate_security(auth, key, key_len); + } + wlan_set_security(auth, key, key_len); + wlan_reset(); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_auth_obj, 1, 2, wlan_auth); + +STATIC mp_obj_t wlan_channel(size_t n_args, const mp_obj_t *args) { + wlan_obj_t *self = args[0]; + if (n_args == 1) { + return mp_obj_new_int(self->channel); + } else { + uint8_t channel = mp_obj_get_int(args[1]); + wlan_validate_channel(channel); + wlan_set_channel(channel); + wlan_reset(); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_channel_obj, 1, 2, wlan_channel); + +STATIC mp_obj_t wlan_antenna(size_t n_args, const mp_obj_t *args) { + wlan_obj_t *self = args[0]; + if (n_args == 1) { + return mp_obj_new_int(self->antenna); + } else { + #if MICROPY_HW_ANTENNA_DIVERSITY + uint8_t antenna = mp_obj_get_int(args[1]); + wlan_validate_antenna(antenna); + wlan_set_antenna(antenna); + #endif + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_antenna_obj, 1, 2, wlan_antenna); + +STATIC mp_obj_t wlan_mac(size_t n_args, const mp_obj_t *args) { + wlan_obj_t *self = args[0]; + if (n_args == 1) { + return mp_obj_new_bytes((const byte *)self->mac, SL_BSSID_LENGTH); + } else { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + if (bufinfo.len != 6) { + mp_raise_ValueError(mpexception_value_invalid_arguments); + } + memcpy(self->mac, bufinfo.buf, SL_MAC_ADDR_LEN); + sl_NetCfgSet(SL_MAC_ADDRESS_SET, 1, SL_MAC_ADDR_LEN, (_u8 *)self->mac); + wlan_reset(); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mac_obj, 1, 2, wlan_mac); +/* +STATIC mp_obj_t wlan_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); + + wlan_obj_t *self = pos_args[0]; + + // check the trigger, only one type is supported + if (mp_obj_get_int(args[0].u_obj) != MODWLAN_WIFI_EVENT_ANY) { + goto invalid_args; + } + + // check the power mode + if (mp_obj_get_int(args[3].u_obj) != PYB_PWR_MODE_LPDS) { + goto invalid_args; + } + + // create the callback + mp_obj_t _irq = mp_irq_new (self, args[2].u_obj, &wlan_irq_methods); + self->irq_obj = _irq; + + // enable the irq just before leaving + wlan_lpds_irq_enable(self); + + return _irq; + +invalid_args: + mp_raise_ValueError(mpexception_value_invalid_arguments); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq); +*/ +//STATIC mp_obj_t wlan_connections (mp_obj_t self_in) { +// mp_obj_t device[2]; +// mp_obj_t connections = mp_obj_new_list(0, NULL); +// +// if (wlan_is_connected()) { +// device[0] = mp_obj_new_str((const char *)wlan_obj.ssid_o, strlen((const char *)wlan_obj.ssid_o)); +// device[1] = mp_obj_new_bytes((const byte *)wlan_obj.bssid, SL_BSSID_LENGTH); +// // add the device to the list +// mp_obj_list_append(connections, mp_obj_new_tuple(MP_ARRAY_SIZE(device), device)); +// } +// return connections; +//} +//STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_connections_obj, wlan_connections); + +//STATIC mp_obj_t wlan_urn (uint n_args, const mp_obj_t *args) { +// char urn[MAX_DEVICE_URN_LEN]; +// uint8_t len = MAX_DEVICE_URN_LEN; +// +// // an URN is given, so set it +// if (n_args == 2) { +// const char *p = mp_obj_str_get_str(args[1]); +// uint8_t len = strlen(p); +// +// // the call to sl_NetAppSet corrupts the input string URN=args[1], so we copy into a local buffer +// if (len > MAX_DEVICE_URN_LEN) { +// mp_raise_ValueError(mpexception_value_invalid_arguments); +// } +// strcpy(urn, p); +// +// if (sl_NetAppSet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, len, (unsigned char *)urn) < 0) { +// mp_raise_OSError(MP_EIO); +// } +// } +// else { +// // get the URN +// if (sl_NetAppGet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, &len, (uint8_t *)urn) < 0) { +// mp_raise_OSError(MP_EIO); +// } +// return mp_obj_new_str(urn, (len - 1)); +// } +// +// return mp_const_none; +//} +//STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_urn_obj, 1, 2, wlan_urn); + +STATIC mp_obj_t wlan_print_ver(void) { + SlVersionFull ver; + byte config_opt = SL_DEVICE_GENERAL_VERSION; + byte config_len = sizeof(ver); + sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver); + printf("NWP: %d.%d.%d.%d\n", (int)ver.NwpVersion[0], (int)ver.NwpVersion[1], (int)ver.NwpVersion[2], (int)ver.NwpVersion[3]); + printf("MAC: %d.%d.%d.%d\n", (int)ver.ChipFwAndPhyVersion.FwVersion[0], (int)ver.ChipFwAndPhyVersion.FwVersion[1], + (int)ver.ChipFwAndPhyVersion.FwVersion[2], (int)ver.ChipFwAndPhyVersion.FwVersion[3]); + printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1], + ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(wlan_print_ver_fun_obj, wlan_print_ver); +STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(wlan_print_ver_obj, MP_ROM_PTR(&wlan_print_ver_fun_obj)); + +STATIC const mp_rom_map_elem_t cc31k_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&wlan_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&wlan_scan_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&wlan_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&wlan_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wlan_isconnected_obj) }, + { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wlan_ifconfig_obj) }, + { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&wlan_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_ssid), MP_ROM_PTR(&wlan_ssid_obj) }, + { MP_ROM_QSTR(MP_QSTR_auth), MP_ROM_PTR(&wlan_auth_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wlan_channel_obj) }, + { MP_ROM_QSTR(MP_QSTR_antenna), MP_ROM_PTR(&wlan_antenna_obj) }, + { MP_ROM_QSTR(MP_QSTR_mac), MP_ROM_PTR(&wlan_mac_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&wlan_irq_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&wlan_connections_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_urn), MP_ROM_PTR(&wlan_urn_obj) }, + { MP_ROM_QSTR(MP_QSTR_print_ver), MP_ROM_PTR(&wlan_print_ver_obj) }, + + // class constants + { MP_ROM_QSTR(MP_QSTR_STA), MP_ROM_INT(ROLE_STA) }, + { MP_ROM_QSTR(MP_QSTR_AP), MP_ROM_INT(ROLE_AP) }, + { MP_ROM_QSTR(MP_QSTR_WEP), MP_ROM_INT(SL_SEC_TYPE_WEP) }, + { MP_ROM_QSTR(MP_QSTR_WPA), MP_ROM_INT(SL_SEC_TYPE_WPA_WPA2) }, + { MP_ROM_QSTR(MP_QSTR_WPA2), MP_ROM_INT(SL_SEC_TYPE_WPA_WPA2) }, + #if MICROPY_HW_ANTENNA_DIVERSITY + { MP_ROM_QSTR(MP_QSTR_INT_ANT), MP_ROM_INT(ANTENNA_TYPE_INTERNAL) }, + { MP_ROM_QSTR(MP_QSTR_EXT_ANT), MP_ROM_INT(ANTENNA_TYPE_EXTERNAL) }, + #endif + { MP_ROM_QSTR(MP_QSTR_ANY_EVENT), MP_ROM_INT(MODWLAN_WIFI_EVENT_ANY) }, +}; +STATIC MP_DEFINE_CONST_DICT(cc31k_locals_dict, cc31k_locals_dict_table); + +const mod_network_nic_type_t mod_network_nic_type_cc31k = { + .base = { + { &mp_type_type }, + .name = MP_QSTR_CC31K, + .make_new = cc31k_make_new, + .locals_dict = (mp_obj_dict_t*)&cc31k_locals_dict, + }, + .gethostbyname = cc31k_gethostbyname, + .socket = cc31k_socket_socket, + .close = cc31k_socket_close, + .bind = cc31k_socket_bind, + .listen = cc31k_socket_listen, + .accept = cc31k_socket_accept, + .connect = cc31k_socket_connect, + .send = cc31k_socket_send, + .recv = cc31k_socket_recv, + .sendto = cc31k_socket_sendto, + .recvfrom = cc31k_socket_recvfrom, + .setsockopt = cc31k_socket_setsockopt, + .settimeout = cc31k_socket_settimeout, + .ioctl = cc31k_socket_ioctl, +}; + +/* +STATIC const mp_irq_methods_t wlan_irq_methods = { + .init = wlan_irq, + .enable = wlan_lpds_irq_enable, + .disable = wlan_lpds_irq_disable, + .flags = wlan_irq_flags, +}; +*/ +#endif // (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) diff --git a/ports/nrf/modules/network/modnwcc31k.h b/ports/nrf/modules/network/modnwcc31k.h new file mode 100644 index 0000000000000..c47343f1e7c75 --- /dev/null +++ b/ports/nrf/modules/network/modnwcc31k.h @@ -0,0 +1,107 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Daniel Campora + * + * 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_CC3200_MODS_MODWLAN_H +#define MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H + +#include "py/stream.h" + +/****************************************************************************** + DEFINE CONSTANTS + ******************************************************************************/ +#define SIMPLELINK_SPAWN_TASK_PRIORITY 3 +#define SIMPLELINK_TASK_STACK_SIZE 2048 +#define SL_STOP_TIMEOUT 35 +#define SL_STOP_TIMEOUT_LONG 575 + +#define MODWLAN_WIFI_EVENT_ANY 0x01 + +#define MODWLAN_SSID_LEN_MAX 32 + +/****************************************************************************** + DEFINE TYPES + ******************************************************************************/ +typedef enum { + MODWLAN_OK = 0, + MODWLAN_ERROR_INVALID_PARAMS = -1, + MODWLAN_ERROR_TIMEOUT = -2, + MODWLAN_ERROR_UNKNOWN = -3, +} modwlan_Status_t; + +typedef struct _wlan_obj_t { + mp_obj_base_t base; + mp_obj_t irq_obj; + uint32_t status; + + uint32_t ip; + + int8_t mode; + uint8_t auth; + uint8_t channel; + uint8_t antenna; + + // my own ssid, key and mac + uint8_t ssid[(MODWLAN_SSID_LEN_MAX + 1)]; + uint8_t key[65]; + uint8_t mac[SL_MAC_ADDR_LEN]; + + // the sssid (or name) and mac of the other device + uint8_t ssid_o[33]; + uint8_t bssid[6]; + uint8_t irq_flags; + bool irq_enabled; + +#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) + bool servers_enabled; +#endif +} wlan_obj_t; + +/****************************************************************************** + DECLARE PUBLIC DATA + ******************************************************************************/ +extern _SlLockObj_t wlan_LockObj; + +/****************************************************************************** + DECLARE PUBLIC FUNCTIONS + ******************************************************************************/ +extern void wlan_pre_init (void); +extern void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth, const char *key, uint8_t key_len, + uint8_t channel, uint8_t antenna, bool add_mac); +extern void wlan_first_start (void); +extern void wlan_update(void); +extern void wlan_stop (uint32_t timeout); +extern void wlan_get_mac (uint8_t *macAddress); +extern void wlan_get_ip (uint32_t *ip); +extern bool wlan_is_connected (void); +extern void wlan_set_current_time (uint32_t seconds_since_2000); +extern void wlan_off_on (void); + +extern void modusocket_pre_init (void); +extern void modusocket_socket_add (int16_t sd, bool user); +extern void modusocket_socket_delete (int16_t sd); +extern void modusocket_enter_sleep (void); +extern void modusocket_close_all_user_sockets (void); + +#endif // MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index a5e16421cc844..d6e24cdf8cf2a 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -219,6 +219,8 @@ extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_ubluepy; extern const struct _mp_obj_module_t music_module; extern const struct _mp_obj_module_t random_module; +extern const struct _mp_obj_module_t mp_module_usocket; +extern const struct _mp_obj_module_t mp_module_network; #if MICROPY_PY_UBLUEPY #define UBLUEPY_MODULE { MP_ROM_QSTR(MP_QSTR_ubluepy), MP_ROM_PTR(&mp_module_ubluepy) }, @@ -245,6 +247,24 @@ extern const struct _mp_obj_module_t random_module; #define MICROPY_BOARD_BUILTINS #endif // BOARD_SPECIFIC_MODULES +#if MICROPY_PY_USOCKET +// usocket implementation provided by skeleton wrapper +#define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, +#define SOCKET_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) }, +#define SOCKET_POLL +#else +// no usocket module +#define SOCKET_BUILTIN_MODULE +#define SOCKET_BUILTIN_MODULE_WEAK_LINKS +#define SOCKET_POLL +#endif + +#if MICROPY_PY_NETWORK +#define NETWORK_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_network), MP_ROM_PTR(&mp_module_network) }, +#else +#define NETWORK_BUILTIN_MODULE +#endif + #if BLUETOOTH_SD #if MICROPY_PY_BLE @@ -264,6 +284,8 @@ extern const struct _mp_obj_module_t ble_module; MUSIC_MODULE \ UBLUEPY_MODULE \ RANDOM_MODULE \ + SOCKET_BUILTIN_MODULE \ + NETWORK_BUILTIN_MODULE \ MICROPY_BOARD_BUILTINS \ @@ -276,6 +298,8 @@ extern const struct _mp_obj_module_t ble_module; { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_uos) }, \ MUSIC_MODULE \ RANDOM_MODULE \ + SOCKET_BUILTIN_MODULE \ + NETWORK_BUILTIN_MODULE \ MICROPY_BOARD_BUILTINS \ @@ -284,6 +308,7 @@ extern const struct _mp_obj_module_t ble_module; #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&mp_module_uos) }, \ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ + SOCKET_BUILTIN_MODULE_WEAK_LINKS \ // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ @@ -333,6 +358,10 @@ extern const struct _mp_obj_module_t ble_module; \ /* micro:bit root pointers */ \ void *async_data[2]; \ + \ + /* list of registered NICs */ \ + mp_obj_list_t mod_network_nic_list; \ + #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) @@ -342,3 +371,12 @@ extern const struct _mp_obj_module_t ble_module; #define MICROPY_PIN_DEFS_PORT_H "pin_defs_nrf5.h" #endif + +//#define MICROPY_MPHALPORT_H "cc3200_hal.h" +#define MICROPY_PORT_HAS_TELNET (0) +#define MICROPY_PORT_HAS_FTP (0) + +#define MICROPY_PORT_WLAN_AP_SSID "SSID" +#define MICROPY_PORT_WLAN_AP_KEY "PASSKEY" +#define MICROPY_PORT_WLAN_AP_SECURITY SL_SEC_TYPE_WPA_WPA2 +#define MICROPY_PORT_WLAN_AP_CHANNEL 5 From 3d215350f315b0791252e9438fa20da777434bfc Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Mon, 3 Sep 2018 23:06:42 +0200 Subject: [PATCH 2/2] extmod: Consolidate use of modnetwork and modusocket. --- .../modules/network => extmod}/modnetwork.c | 0 .../modules/network => extmod}/modnetwork.h | 4 +- .../modules/network => extmod}/modnwcc31k.c | 90 +- .../modules/network => extmod}/modnwcc31k.h | 0 {ports/stm32 => extmod}/modusocket.c | 23 +- {ports/cc3200/mods => extmod}/modusocket.h | 12 +- ports/cc3200/application.mk | 17 +- .../cc3200/fatfs/src/drivers/sflash_diskio.c | 2 +- ports/cc3200/ftp/ftp.c | 2 +- ports/cc3200/ftp/updater.c | 2 +- ports/cc3200/mods/modmachine.c | 2 +- ports/cc3200/mods/modnetwork.c | 179 --- ports/cc3200/mods/modnetwork.h | 73 - ports/cc3200/mods/modusocket.c | 819 ----------- ports/cc3200/mods/modussl.c | 6 +- ports/cc3200/mods/modwlan.c | 1303 ----------------- ports/cc3200/mods/modwlan.h | 99 -- ports/cc3200/mods/pybrtc.c | 2 +- ports/cc3200/mods/pybsleep.c | 2 +- ports/cc3200/mpconfigport.h | 4 +- ports/cc3200/mptask.c | 4 +- ports/cc3200/serverstask.c | 2 +- ports/cc3200/telnet/telnet.c | 2 +- ports/cc3200/util/random.c | 2 +- ports/nrf/Makefile | 19 +- ports/stm32/Makefile | 5 +- ports/stm32/modnetwork.c | 177 --- ports/stm32/modnetwork.h | 101 -- ports/stm32/modnwcc3k.c | 2 +- ports/stm32/modnwwiznet5k.c | 2 +- 30 files changed, 121 insertions(+), 2836 deletions(-) rename {ports/nrf/modules/network => extmod}/modnetwork.c (100%) rename {ports/nrf/modules/network => extmod}/modnetwork.h (99%) rename {ports/nrf/modules/network => extmod}/modnwcc31k.c (98%) rename {ports/nrf/modules/network => extmod}/modnwcc31k.h (100%) rename {ports/stm32 => extmod}/modusocket.c (95%) rename {ports/cc3200/mods => extmod}/modusocket.h (77%) delete mode 100644 ports/cc3200/mods/modnetwork.c delete mode 100644 ports/cc3200/mods/modnetwork.h delete mode 100644 ports/cc3200/mods/modusocket.c delete mode 100644 ports/cc3200/mods/modwlan.c delete mode 100644 ports/cc3200/mods/modwlan.h delete mode 100644 ports/stm32/modnetwork.c delete mode 100644 ports/stm32/modnetwork.h diff --git a/ports/nrf/modules/network/modnetwork.c b/extmod/modnetwork.c similarity index 100% rename from ports/nrf/modules/network/modnetwork.c rename to extmod/modnetwork.c diff --git a/ports/nrf/modules/network/modnetwork.h b/extmod/modnetwork.h similarity index 99% rename from ports/nrf/modules/network/modnetwork.h rename to extmod/modnetwork.h index 79fda811f7c49..ccbeeefb3fc9e 100644 --- a/ports/nrf/modules/network/modnetwork.h +++ b/extmod/modnetwork.h @@ -89,12 +89,12 @@ typedef struct _mod_network_socket_obj_t { int8_t fileno; uint8_t proto; } u_param; -#if MICROPY_PY_CC31K +#if (MICROPY_PY_CC31K) int16_t sd; #endif mp_uint_t u_state; }; -#if MICROPY_PY_CC31K +#if (MICROPY_PY_CC31K) uint32_t timeout_ms; // 0 for no timeout bool cert_req; #endif diff --git a/ports/nrf/modules/network/modnwcc31k.c b/extmod/modnwcc31k.c similarity index 98% rename from ports/nrf/modules/network/modnwcc31k.c rename to extmod/modnwcc31k.c index 7b4b695efa12b..e469de72a8e88 100644 --- a/ports/nrf/modules/network/modnwcc31k.c +++ b/extmod/modnwcc31k.c @@ -42,27 +42,27 @@ #include "lib/netutils/netutils.h" #include "modnetwork.h" #include "modnwcc31k.h" -//#include "pybrtc.h" -//#include "debug.h" +#include "simplelink.h" + +#if (TARGET_IS_CC3200) +#include "pybrtc.h" +#include "debug.h" +#include "mpirq.h" +#include "pybsleep.h" +#include "mpexception.h" +#else +const char mpexception_value_invalid_arguments[] = "invalid argument(s) value"; +const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type"; +const char mpexception_uncaught[] = "uncaught exception"; +#endif // (TARGET_IS_CC3200) + +#if (MICROPY_HW_ANTENNA_DIVERSITY) +#include "antenna.h" +#endif + #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) #include "serverstask.h" #endif -//#include "mpexception.h" -//#include "antenna.h" - -#if MICROPY_PY_CC31K -#include "simplelink.h" -#endif // MICROPY_PY_CC31K - -#include "py/obj.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mphal.h" -#include "lib/netutils/netutils.h" -#include "modnetwork.h" -#include "modnwcc31k.h" -//#include "mpexception.h" #define WLAN_MAX_RX_SIZE 16000 #define WLAN_MAX_TX_SIZE 1476 @@ -525,10 +525,6 @@ typedef enum{ #define ASSERT_ON_ERROR(x) ASSERT((x) >= 0) -const char mpexception_value_invalid_arguments[] = "invalid argument(s) value"; -const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type"; -const char mpexception_uncaught[] = "uncaught exception"; - #if defined(DEBUG) #define ASSERT(expr) assert(expr) #else @@ -554,7 +550,9 @@ STATIC wlan_obj_t wlan_obj = { #endif }; -//STATIC const mp_irq_methods_t wlan_irq_methods; +#if (TARGET_IS_CC3200) +STATIC const mp_irq_methods_t wlan_irq_methods; +#endif // (TARGET_IS_CC3200) /****************************************************************************** DECLARE PUBLIC DATA @@ -901,11 +899,12 @@ void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 1, 0, 0, 0), NULL, 0)); } +#if (TARGET_IS_CC3200) // set current time and date (needed to validate certificates) - //wlan_set_current_time (pyb_rtc_get_seconds()); - + wlan_set_current_time (pyb_rtc_get_seconds()); // start the servers before returning - //wlan_servers_start(); + wlan_servers_start(); +#endif // (TARGET_IS_CC3200) } void wlan_update(void) { @@ -1158,7 +1157,8 @@ STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out) { } } } -/* + +#if (TARGET_IS_CC3200) STATIC void wlan_lpds_irq_enable (mp_obj_t self_in) { wlan_obj_t *self = self_in; self->irq_enabled = true; @@ -1173,7 +1173,8 @@ STATIC int wlan_irq_flags (mp_obj_t self_in) { wlan_obj_t *self = self_in; return self->irq_flags; } -*/ +#endif // (TARGET_IS_CC3200) + STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid) { for (int i = 0; i < nets->len; i++) { // index 1 in the list is the bssid @@ -1233,10 +1234,14 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) { } STATIC const mp_arg_t wlan_init_args[] = { +#if (TARGET_IS_CC3200) + { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, +#else { MP_QSTR_spi, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_cs, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_en, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_irq, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, +#endif { MP_QSTR_mode, MP_ARG_INT, {.u_int = ROLE_STA} }, { MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -1256,7 +1261,19 @@ STATIC mp_obj_t cc31k_make_new(const mp_obj_type_t *type, size_t n_args, size_t // setup the object wlan_obj_t *self = &wlan_obj; self->base.type = (mp_obj_t)&mod_network_nic_type_cc31k; - +#if (TARGET_IS_CC3200) + // give it to the sleep module + pyb_sleep_set_wlan_obj(self); + + if (n_args > 1 || n_kw > 0) { + // check the peripheral id + if (args[0].u_int != 0) { + mp_raise_OSError(MP_ENODEV); + } + // start the peripheral + wlan_init_helper(self, &args[1]); + } +#else // set the pins to use cc3100_drv_init( args[0].u_obj, @@ -1267,6 +1284,7 @@ STATIC mp_obj_t cc31k_make_new(const mp_obj_type_t *type, size_t n_args, size_t // start the peripheral wlan_init_helper(self, &args[4]); +#endif // register with network module mod_network_register_nic((mp_obj_t)self); @@ -1592,7 +1610,8 @@ STATIC mp_obj_t wlan_mac(size_t n_args, const mp_obj_t *args) { } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mac_obj, 1, 2, wlan_mac); -/* + +#if (TARGET_IS_CC3200) STATIC mp_obj_t wlan_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); @@ -1622,7 +1641,8 @@ STATIC mp_obj_t wlan_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq); -*/ +#endif // (TARGET_IS_CC3200) + //STATIC mp_obj_t wlan_connections (mp_obj_t self_in) { // mp_obj_t device[2]; // mp_obj_t connections = mp_obj_new_list(0, NULL); @@ -1696,7 +1716,9 @@ STATIC const mp_rom_map_elem_t cc31k_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wlan_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_antenna), MP_ROM_PTR(&wlan_antenna_obj) }, { MP_ROM_QSTR(MP_QSTR_mac), MP_ROM_PTR(&wlan_mac_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&wlan_irq_obj) }, +#if (TARGET_IS_CC3200) + { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&wlan_irq_obj) }, +#endif // (TARGET_IS_CC3200) //{ MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&wlan_connections_obj) }, //{ MP_ROM_QSTR(MP_QSTR_urn), MP_ROM_PTR(&wlan_urn_obj) }, { MP_ROM_QSTR(MP_QSTR_print_ver), MP_ROM_PTR(&wlan_print_ver_obj) }, @@ -1738,12 +1760,12 @@ const mod_network_nic_type_t mod_network_nic_type_cc31k = { .ioctl = cc31k_socket_ioctl, }; -/* +#if (TARGET_IS_CC3200) STATIC const mp_irq_methods_t wlan_irq_methods = { .init = wlan_irq, .enable = wlan_lpds_irq_enable, .disable = wlan_lpds_irq_disable, .flags = wlan_irq_flags, }; -*/ +#endif // (TARGET_IS_CC3200) #endif // (MICROPY_PY_NETWORK && MICROPY_PY_CC31K) diff --git a/ports/nrf/modules/network/modnwcc31k.h b/extmod/modnwcc31k.h similarity index 100% rename from ports/nrf/modules/network/modnwcc31k.h rename to extmod/modnwcc31k.h diff --git a/ports/stm32/modusocket.c b/extmod/modusocket.c similarity index 95% rename from ports/stm32/modusocket.c rename to extmod/modusocket.c index 7503ecbd68d20..0cda64ad7ab01 100644 --- a/ports/stm32/modusocket.c +++ b/extmod/modusocket.c @@ -53,13 +53,17 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t s->nic_type = NULL; s->u_param.domain = MOD_NETWORK_AF_INET; s->u_param.type = MOD_NETWORK_SOCK_STREAM; + s->u_param.proto = MOD_NETWORK_IPPROTO_TCP; s->u_param.fileno = -1; if (n_args >= 1) { s->u_param.domain = mp_obj_get_int(args[0]); if (n_args >= 2) { s->u_param.type = mp_obj_get_int(args[1]); - if (n_args >= 4) { - s->u_param.fileno = mp_obj_get_int(args[3]); + if (n_args >= 3) { + s->u_param.proto = mp_obj_get_int(args[2]); + if (n_args >= 4) { + s->u_param.fileno = mp_obj_get_int(args[3]); + } } } } @@ -160,7 +164,6 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { // get address uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); - // check if we need to select a NIC socket_select_nic(self, ip); @@ -351,9 +354,15 @@ STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, + + // stream methods + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read1_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); +MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -367,7 +376,7 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int * return self->nic_type->ioctl(self, request, arg, errcode); } -STATIC const mp_stream_p_t socket_stream_p = { +const mp_stream_p_t socket_stream_p = { .ioctl = socket_ioctl, .is_text = false, }; @@ -409,7 +418,7 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); if (nic_type->gethostbyname != NULL) { - int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); + int ret = nic_type->gethostbyname(nic, host, hlen, out_ip, MOD_NETWORK_AF_INET); if (ret != 0) { mp_raise_OSError(ret); } @@ -458,7 +467,7 @@ STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = { */ }; -STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); +MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); const mp_obj_module_t mp_module_usocket = { .base = { &mp_type_module }, diff --git a/ports/cc3200/mods/modusocket.h b/extmod/modusocket.h similarity index 77% rename from ports/cc3200/mods/modusocket.h rename to extmod/modusocket.h index aaee04ce1927e..bd4d5079657ae 100644 --- a/ports/cc3200/mods/modusocket.h +++ b/extmod/modusocket.h @@ -23,18 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H -#define MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H +#ifndef MICROPY_INCLUDED_EXTMOD_MODUSOCKET_H +#define MICROPY_INCLUDED_EXTMOD_MODUSOCKET_H #include "py/stream.h" extern const mp_obj_dict_t socket_locals_dict; extern const mp_stream_p_t socket_stream_p; -extern void modusocket_pre_init (void); -extern void modusocket_socket_add (int16_t sd, bool user); -extern void modusocket_socket_delete (int16_t sd); -extern void modusocket_enter_sleep (void); -extern void modusocket_close_all_user_sockets (void); - -#endif // MICROPY_INCLUDED_CC3200_MODS_MODUSOCKET_H +#endif // MICROPY_INCLUDED_EXTMOD_MODUSOCKET_H diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk index 19abe661631ae..71a7453a03fcf 100644 --- a/ports/cc3200/application.mk +++ b/ports/cc3200/application.mk @@ -19,8 +19,9 @@ APP_INC += -Ibootmgr APP_INC += -I$(BUILD) APP_INC += -I$(BUILD)/genhdr APP_INC += -I$(TOP)/ports/stm32 +APP_INC += -I$(TOP)/extmod -APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS +APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS -DMICROPY_PY_CC31K=1 APP_FATFS_SRC_C = $(addprefix fatfs/src/,\ drivers/sflash_diskio.c \ @@ -78,14 +79,11 @@ APP_MISC_SRC_C = $(addprefix misc/,\ APP_MODS_SRC_C = $(addprefix mods/,\ modmachine.c \ - modnetwork.c \ modubinascii.c \ moduos.c \ - modusocket.c \ modussl.c \ modutime.c \ modwipy.c \ - modwlan.c \ pybadc.c \ pybpin.c \ pybi2c.c \ @@ -156,13 +154,20 @@ APP_STM_SRC_C = $(addprefix ports/stm32/,\ irq.c \ ) +APP_EXTMOD_SRC_C = $(addprefix extmod/,\ + modnetwork.c \ + modnwcc31k.c \ + modusocket.c \ + ) + + OBJ = $(PY_O) $(addprefix $(BUILD)/, $(APP_FATFS_SRC_C:.c=.o) $(APP_RTOS_SRC_C:.c=.o) $(APP_FTP_SRC_C:.c=.o) $(APP_HAL_SRC_C:.c=.o) $(APP_MISC_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_CC3100_SRC_C:.c=.o) $(APP_SL_SRC_C:.c=.o) $(APP_TELNET_SRC_C:.c=.o) $(APP_UTIL_SRC_C:.c=.o) $(APP_UTIL_SRC_S:.s=.o)) -OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o) $(APP_EXTMOD_SRC_C:.c=.o)) OBJ += $(BUILD)/pins.o # List of sources for qstr extraction -SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) +SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) $(APP_EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR SRC_QSTR_AUTO_DEPS += diff --git a/ports/cc3200/fatfs/src/drivers/sflash_diskio.c b/ports/cc3200/fatfs/src/drivers/sflash_diskio.c index 6a1fc406855d3..4b63afd509b80 100644 --- a/ports/cc3200/fatfs/src/drivers/sflash_diskio.c +++ b/ports/cc3200/fatfs/src/drivers/sflash_diskio.c @@ -10,7 +10,7 @@ #include "sflash_diskio.h" #include "debug.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #define SFLASH_TIMEOUT_MAX_MS 5500 #define SFLASH_WAIT_TIME_MS 5 diff --git a/ports/cc3200/ftp/ftp.c b/ports/cc3200/ftp/ftp.c index ee80e51f5269e..2a550f5e843f8 100644 --- a/ports/cc3200/ftp/ftp.c +++ b/ports/cc3200/ftp/ftp.c @@ -41,7 +41,7 @@ #include "ftp.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "modusocket.h" #include "debug.h" #include "serverstask.h" diff --git a/ports/cc3200/ftp/updater.c b/ports/cc3200/ftp/updater.c index 5be2c6063c9ba..c8a21e3076f4c 100644 --- a/ports/cc3200/ftp/updater.c +++ b/ports/cc3200/ftp/updater.c @@ -34,7 +34,7 @@ #include "updater.h" #include "shamd5.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "debug.h" #include "osi.h" diff --git a/ports/cc3200/mods/modmachine.c b/ports/cc3200/mods/modmachine.c index 6051497e30d99..e68a1d968810e 100644 --- a/ports/cc3200/mods/modmachine.c +++ b/ports/cc3200/mods/modmachine.c @@ -42,7 +42,7 @@ #include "pybrtc.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "moduos.h" #include "FreeRTOS.h" #include "portable.h" diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c deleted file mode 100644 index 37dffe731f11d..0000000000000 --- a/ports/cc3200/mods/modnetwork.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2015 Daniel Campora - * - * 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 "py/runtime.h" -#include "py/mperrno.h" -#include "py/mphal.h" -#include "modnetwork.h" -#include "mpexception.h" -#include "serverstask.h" -#include "simplelink.h" - - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ -typedef struct { - mp_obj_base_t base; -} network_server_obj_t; - -/****************************************************************************** - DECLARE PRIVATE DATA - ******************************************************************************/ -STATIC network_server_obj_t network_server_obj; -STATIC const mp_obj_type_t network_server_type; - -/// \module network - network configuration -/// -/// This module provides network drivers and server configuration. - -void mod_network_init0(void) { -} - -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) -STATIC mp_obj_t network_server_init_helper(mp_obj_t self, const mp_arg_val_t *args) { - const char *user = SERVERS_DEF_USER; - const char *pass = SERVERS_DEF_PASS; - if (args[0].u_obj != MP_OBJ_NULL) { - mp_obj_t *login; - mp_obj_get_array_fixed_n(args[0].u_obj, 2, &login); - user = mp_obj_str_get_str(login[0]); - pass = mp_obj_str_get_str(login[1]); - } - - uint32_t timeout = SERVERS_DEF_TIMEOUT_MS / 1000; - if (args[1].u_obj != MP_OBJ_NULL) { - timeout = mp_obj_get_int(args[1].u_obj); - } - - // configure the new login - servers_set_login ((char *)user, (char *)pass); - - // configure the timeout - servers_set_timeout(timeout * 1000); - - // start the servers - servers_start(); - - return mp_const_none; -} - -STATIC const mp_arg_t network_server_args[] = { - { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_login, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, -}; -STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // parse args - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); - mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args)]; - mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), network_server_args, args); - - // check the server id - if (args[0].u_obj != MP_OBJ_NULL) { - if (mp_obj_get_int(args[0].u_obj) != 0) { - mp_raise_OSError(MP_ENODEV); - } - } - - // setup the object and initialize it - network_server_obj_t *self = &network_server_obj; - self->base.type = &network_server_type; - network_server_init_helper(self, &args[1]); - - return (mp_obj_t)self; -} - -STATIC mp_obj_t network_server_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args) - 1]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &network_server_args[1], args); - return network_server_init_helper(pos_args[0], args); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_server_init_obj, 1, network_server_init); - -// timeout value given in seconds -STATIC mp_obj_t network_server_timeout(size_t n_args, const mp_obj_t *args) { - if (n_args > 1) { - uint32_t timeout = mp_obj_get_int(args[1]); - servers_set_timeout(timeout * 1000); - return mp_const_none; - } else { - // get - return mp_obj_new_int(servers_get_timeout() / 1000); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_timeout_obj, 1, 2, network_server_timeout); - -STATIC mp_obj_t network_server_running(mp_obj_t self_in) { - // get - return mp_obj_new_bool(servers_are_enabled()); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_running_obj, network_server_running); - -STATIC mp_obj_t network_server_deinit(mp_obj_t self_in) { - // simply stop the servers - servers_stop(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_deinit_obj, network_server_deinit); -#endif - -STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, - { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_wlan) }, - -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - { MP_ROM_QSTR(MP_QSTR_Server), MP_ROM_PTR(&network_server_type) }, -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); - -const mp_obj_module_t mp_module_network = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_network_globals, -}; - -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) -STATIC const mp_rom_map_elem_t network_server_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_server_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_server_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&network_server_timeout_obj) }, - { MP_ROM_QSTR(MP_QSTR_isrunning), MP_ROM_PTR(&network_server_running_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_dict_table); - -STATIC const mp_obj_type_t network_server_type = { - { &mp_type_type }, - .name = MP_QSTR_Server, - .make_new = network_server_make_new, - .locals_dict = (mp_obj_t)&network_server_locals_dict, -}; -#endif diff --git a/ports/cc3200/mods/modnetwork.h b/ports/cc3200/mods/modnetwork.h deleted file mode 100644 index 6ec90a2bac189..0000000000000 --- a/ports/cc3200/mods/modnetwork.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2015 Daniel Campora - * - * 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_CC3200_MODS_MODNETWORK_H -#define MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H - -/****************************************************************************** - DEFINE CONSTANTS - ******************************************************************************/ -#define MOD_NETWORK_IPV4ADDR_BUF_SIZE (4) - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ -typedef struct _mod_network_nic_type_t { - mp_obj_type_t base; -} mod_network_nic_type_t; - -typedef struct _mod_network_socket_base_t { - union { - struct { - // this order is important so that fileno gets > 0 once - // the socket descriptor is assigned after being created. - uint8_t domain; - int8_t fileno; - uint8_t type; - uint8_t proto; - } u_param; - int16_t sd; - }; - uint32_t timeout_ms; // 0 for no timeout - bool cert_req; -} mod_network_socket_base_t; - -typedef struct _mod_network_socket_obj_t { - mp_obj_base_t base; - mod_network_socket_base_t sock_base; -} mod_network_socket_obj_t; - -/****************************************************************************** - EXPORTED DATA - ******************************************************************************/ -extern const mod_network_nic_type_t mod_network_nic_type_wlan; - -/****************************************************************************** - DECLARE FUNCTIONS - ******************************************************************************/ -void mod_network_init0(void); - -#endif // MICROPY_INCLUDED_CC3200_MODS_MODNETWORK_H diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c deleted file mode 100644 index 286b1fb02bfb2..0000000000000 --- a/ports/cc3200/mods/modusocket.c +++ /dev/null @@ -1,819 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2015 Daniel Campora - * - * 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 "simplelink.h" -#include "py/mpconfig.h" -#include "py/obj.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mphal.h" -#include "lib/netutils/netutils.h" -#include "modnetwork.h" -#include "modusocket.h" -#include "mpexception.h" - -/******************************************************************************/ -// The following set of macros and functions provide a glue between the CC3100 -// simplelink layer and the functions/methods provided by the usocket module. -// They were historically in a separate file because usocket was designed to -// work with multiple NICs, and the wlan_XXX functions just provided one -// particular NIC implementation (that of the CC3100). But the CC3200 port only -// supports a single NIC (being the CC3100) so it's unnecessary and inefficient -// to provide an intermediate wrapper layer. Hence the wlan_XXX functions -// are provided below as static functions so they can be inlined directly by -// the corresponding usocket calls. - -#define WLAN_MAX_RX_SIZE 16000 -#define WLAN_MAX_TX_SIZE 1476 - -#define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \ - addr.sa_family = SL_AF_INET; \ - addr.sa_data[0] = port >> 8; \ - addr.sa_data[1] = port; \ - addr.sa_data[2] = ip[3]; \ - addr.sa_data[3] = ip[2]; \ - addr.sa_data[4] = ip[1]; \ - addr.sa_data[5] = ip[0]; - -#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \ - ip[0] = addr.sa_data[5]; \ - ip[1] = addr.sa_data[4]; \ - ip[2] = addr.sa_data[3]; \ - ip[3] = addr.sa_data[2]; - -#define SOCKET_TIMEOUT_QUANTA_MS (20) - -STATIC int convert_sl_errno(int sl_errno) { - return -sl_errno; -} - -// This function is left as non-static so it's not inlined. -int check_timedout(mod_network_socket_obj_t *s, int ret, uint32_t *timeout_ms, int *_errno) { - if (*timeout_ms == 0 || ret != SL_EAGAIN) { - if (s->sock_base.timeout_ms > 0 && ret == SL_EAGAIN) { - *_errno = MP_ETIMEDOUT; - } else { - *_errno = convert_sl_errno(ret); - } - return -1; - } - mp_hal_delay_ms(SOCKET_TIMEOUT_QUANTA_MS); - if (*timeout_ms < SOCKET_TIMEOUT_QUANTA_MS) { - *timeout_ms = 0; - } else { - *timeout_ms -= SOCKET_TIMEOUT_QUANTA_MS; - } - return 0; -} - -STATIC int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { - uint32_t ip; - int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family); - out_ip[0] = ip; - out_ip[1] = ip >> 8; - out_ip[2] = ip >> 16; - out_ip[3] = ip >> 24; - return result; -} - -STATIC int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) { - int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto); - if (sd < 0) { - *_errno = sd; - return -1; - } - s->sock_base.sd = sd; - return 0; -} - -STATIC void wlan_socket_close(mod_network_socket_obj_t *s) { - // this is to prevent the finalizer to close a socket that failed when being created - if (s->sock_base.sd >= 0) { - modusocket_socket_delete(s->sock_base.sd); - sl_Close(s->sock_base.sd); - s->sock_base.sd = -1; - } -} - -STATIC int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr)); - if (ret != 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) { - int ret = sl_Listen(s->sock_base.sd, backlog); - if (ret != 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) { - // accept incoming connection - int16_t sd; - SlSockAddr_t addr; - SlSocklen_t addr_len = sizeof(addr); - - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - sd = sl_Accept(s->sock_base.sd, &addr, &addr_len); - if (sd >= 0) { - // save the socket descriptor - s2->sock_base.sd = sd; - // return ip and port - UNPACK_SOCKADDR(addr, ip, *port); - return 0; - } - if (check_timedout(s, sd, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - uint32_t timeout_ms = s->sock_base.timeout_ms; - - // For a non-blocking connect the CC3100 will return SL_EALREADY while the - // connection is in progress. - - for (;;) { - int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr)); - if (ret == 0) { - return 0; - } - - // Check if we are in non-blocking mode and the connection is in progress - if (s->sock_base.timeout_ms == 0 && ret == SL_EALREADY) { - // To match BSD we return EINPROGRESS here - *_errno = MP_EINPROGRESS; - return -1; - } - - // We are in blocking mode, so if the connection isn't in progress then error out - if (ret != SL_EALREADY) { - *_errno = convert_sl_errno(ret); - return -1; - } - - if (check_timedout(s, SL_EAGAIN, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) { - if (len == 0) { - return 0; - } - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_Send(s->sock_base.sd, (const void *)buf, len, 0); - if (ret > 0) { - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) { - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0); - if (ret >= 0) { - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { - MAKE_SOCKADDR(addr, ip, port) - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr)); - if (ret >= 0) { - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { - SlSockAddr_t addr; - SlSocklen_t addr_len = sizeof(addr); - uint32_t timeout_ms = s->sock_base.timeout_ms; - for (;;) { - int ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len); - if (ret >= 0) { - UNPACK_SOCKADDR(addr, ip, *port); - return ret; - } - if (check_timedout(s, ret, &timeout_ms, _errno)) { - return -1; - } - } -} - -STATIC int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { - int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen); - if (ret < 0) { - *_errno = ret; - return -1; - } - return 0; -} - -STATIC int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) { - SlSockNonblocking_t option; - if (timeout_s == 0 || timeout_s == -1) { - if (timeout_s == 0) { - // set non-blocking mode - option.NonblockingEnabled = 1; - } else { - // set blocking mode - option.NonblockingEnabled = 0; - } - timeout_s = 0; - } else { - // synthesize timeout via non-blocking behaviour with a loop - option.NonblockingEnabled = 1; - } - - int ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option)); - if (ret != 0) { - *_errno = convert_sl_errno(ret); - return -1; - } - - s->sock_base.timeout_ms = timeout_s * 1000; - return 0; -} - -STATIC int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) { - mp_int_t ret; - if (request == MP_STREAM_POLL) { - mp_uint_t flags = arg; - ret = 0; - int32_t sd = s->sock_base.sd; - - // init fds - SlFdSet_t rfds, wfds, xfds; - SL_FD_ZERO(&rfds); - SL_FD_ZERO(&wfds); - SL_FD_ZERO(&xfds); - - // set fds if needed - if (flags & MP_STREAM_POLL_RD) { - SL_FD_SET(sd, &rfds); - } - if (flags & MP_STREAM_POLL_WR) { - SL_FD_SET(sd, &wfds); - } - if (flags & MP_STREAM_POLL_HUP) { - SL_FD_SET(sd, &xfds); - } - - // call simplelink's select with minimum timeout - SlTimeval_t tv; - tv.tv_sec = 0; - tv.tv_usec = 1; - int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv); - - // check for errors - if (nfds == -1) { - *_errno = nfds; - return -1; - } - - // check return of select - if (SL_FD_ISSET(sd, &rfds)) { - ret |= MP_STREAM_POLL_RD; - } - if (SL_FD_ISSET(sd, &wfds)) { - ret |= MP_STREAM_POLL_WR; - } - if (SL_FD_ISSET(sd, &xfds)) { - ret |= MP_STREAM_POLL_HUP; - } - } else if (request == MP_STREAM_CLOSE) { - wlan_socket_close(s); - ret = 0; - } else { - *_errno = MP_EINVAL; - ret = MP_STREAM_ERROR; - } - return ret; -} - -/****************************************************************************** - DEFINE PRIVATE CONSTANTS - ******************************************************************************/ -#define MOD_NETWORK_MAX_SOCKETS 10 - -/****************************************************************************** - DEFINE PRIVATE TYPES - ******************************************************************************/ -typedef struct { - int16_t sd; - bool user; -} modusocket_sock_t; - -/****************************************************************************** - DEFINE PRIVATE DATA - ******************************************************************************/ -STATIC const mp_obj_type_t socket_type; -STATIC OsiLockObj_t modusocket_LockObj; -STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, - {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}}; - -/****************************************************************************** - DEFINE PUBLIC FUNCTIONS - ******************************************************************************/ -__attribute__ ((section (".boot"))) -void modusocket_pre_init (void) { - // create the wlan lock - ASSERT(OSI_OK == sl_LockObjCreate(&modusocket_LockObj, "SockLock")); - sl_LockObjUnlock (&modusocket_LockObj); -} - -void modusocket_socket_add (int16_t sd, bool user) { - sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - if (modusocket_sockets[i].sd < 0) { - modusocket_sockets[i].sd = sd; - modusocket_sockets[i].user = user; - break; - } - } - sl_LockObjUnlock (&modusocket_LockObj); -} - -void modusocket_socket_delete (int16_t sd) { - sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - if (modusocket_sockets[i].sd == sd) { - modusocket_sockets[i].sd = -1; - break; - } - } - sl_LockObjUnlock (&modusocket_LockObj); -} - -void modusocket_enter_sleep (void) { - SlFdSet_t socketset; - int16_t maxfd = 0; - - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - int16_t sd; - if ((sd = modusocket_sockets[i].sd) >= 0) { - SL_FD_SET(sd, &socketset); - maxfd = (maxfd > sd) ? maxfd : sd; - } - } - - if (maxfd > 0) { - // wait for any of the sockets to become ready... - sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL); - } -} - -void modusocket_close_all_user_sockets (void) { - sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); - for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { - if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) { - sl_Close(modusocket_sockets[i].sd); - modusocket_sockets[i].sd = -1; - } - } - sl_LockObjUnlock (&modusocket_LockObj); -} - -/******************************************************************************/ -// socket class - -// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None) -STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 4, false); - - // create socket object - mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t); - s->base.type = (mp_obj_t)&socket_type; - s->sock_base.u_param.domain = SL_AF_INET; - s->sock_base.u_param.type = SL_SOCK_STREAM; - s->sock_base.u_param.proto = SL_IPPROTO_TCP; - s->sock_base.u_param.fileno = -1; - s->sock_base.timeout_ms = 0; - s->sock_base.cert_req = false; - - if (n_args > 0) { - s->sock_base.u_param.domain = mp_obj_get_int(args[0]); - if (n_args > 1) { - s->sock_base.u_param.type = mp_obj_get_int(args[1]); - if (n_args > 2) { - s->sock_base.u_param.proto = mp_obj_get_int(args[2]); - if (n_args > 3) { - s->sock_base.u_param.fileno = mp_obj_get_int(args[3]); - } - } - } - } - - // create the socket - int _errno; - if (wlan_socket_socket(s, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - // add the socket to the list - modusocket_socket_add(s->sock_base.sd, true); - return s; -} - -// method socket.bind(address) -STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { - mod_network_socket_obj_t *self = self_in; - - // get address - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); - - // call the NIC to bind the socket - int _errno = 0; - if (wlan_socket_bind(self, ip, port, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); - -// method socket.listen([backlog]) -STATIC mp_obj_t socket_listen(size_t n_args, const mp_obj_t *args) { - mod_network_socket_obj_t *self = args[0]; - - int32_t backlog = 0; - if (n_args > 1) { - backlog = mp_obj_get_int(args[1]); - backlog = (backlog < 0) ? 0 : backlog; - } - - int _errno; - if (wlan_socket_listen(self, backlog, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen); - -// method socket.accept() -STATIC mp_obj_t socket_accept(mp_obj_t self_in) { - mod_network_socket_obj_t *self = self_in; - - // create new socket object - mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); - // the new socket inherits all properties from its parent - memcpy (socket2, self, sizeof(mod_network_socket_obj_t)); - - // accept the incoming connection - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = 0; - int _errno = 0; - if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) { - mp_raise_OSError(_errno); - } - - // add the socket to the list - modusocket_socket_add(socket2->sock_base.sd, true); - - // make the return value - mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); - client->items[0] = socket2; - client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); - return client; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); - -// method socket.connect(address) -STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { - mod_network_socket_obj_t *self = self_in; - - // get address - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); - - // connect the socket - int _errno; - if (wlan_socket_connect(self, ip, port, &_errno) != 0) { - if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) { - return mp_const_none; - } - mp_raise_OSError(_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); - -// method socket.send(bytes) -STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { - mod_network_socket_obj_t *self = self_in; - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - int _errno; - mp_int_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - return mp_obj_new_int_from_uint(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); - -// method socket.recv(bufsize) -STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { - mod_network_socket_obj_t *self = self_in; - mp_int_t len = mp_obj_get_int(len_in); - vstr_t vstr; - vstr_init_len(&vstr, len); - int _errno; - mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - if (ret == 0) { - return mp_const_empty_bytes; - } - vstr.len = ret; - vstr.buf[vstr.len] = '\0'; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); - -// method socket.sendto(bytes, address) -STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { - mod_network_socket_obj_t *self = self_in; - - // get the data - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); - - // get address - uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); - - // call the nic to sendto - int _errno = 0; - mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - return mp_obj_new_int(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); - -// method socket.recvfrom(bufsize) -STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { - mod_network_socket_obj_t *self = self_in; - vstr_t vstr; - vstr_init_len(&vstr, mp_obj_get_int(len_in)); - byte ip[4]; - mp_uint_t port = 0; - int _errno = 0; - mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); - if (ret < 0) { - mp_raise_OSError(_errno); - } - mp_obj_t tuple[2]; - if (ret == 0) { - tuple[0] = mp_const_empty_bytes; - } else { - vstr.len = ret; - vstr.buf[vstr.len] = '\0'; - tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); - } - tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); - return mp_obj_new_tuple(2, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); - -// method socket.setsockopt(level, optname, value) -STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { - mod_network_socket_obj_t *self = args[0]; - - mp_int_t level = mp_obj_get_int(args[1]); - mp_int_t opt = mp_obj_get_int(args[2]); - - const void *optval; - mp_uint_t optlen; - mp_int_t val; - if (mp_obj_is_integer(args[3])) { - val = mp_obj_get_int_truncated(args[3]); - optval = &val; - optlen = sizeof(val); - } else { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - optval = bufinfo.buf; - optlen = bufinfo.len; - } - - int _errno; - if (wlan_socket_setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { - mp_raise_OSError(-_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); - -// method socket.settimeout(value) -// timeout=0 means non-blocking -// timeout=None means blocking -// otherwise, timeout is in seconds -STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { - mod_network_socket_obj_t *self = self_in; - mp_uint_t timeout; - if (timeout_in == mp_const_none) { - timeout = -1; - } else { - timeout = mp_obj_get_int(timeout_in); - } - int _errno = 0; - if (wlan_socket_settimeout(self, timeout, &_errno) != 0) { - mp_raise_OSError(_errno); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); - -// method socket.setblocking(flag) -STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { - if (mp_obj_is_true(blocking)) { - return socket_settimeout(self_in, mp_const_none); - } else { - return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0)); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); - -STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { - (void)n_args; - return args[0]; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 6, socket_makefile); - -STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, - { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, - { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_send_obj) }, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, - { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, - { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, - { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, - { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, - { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, - { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, - - // stream methods - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read1_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, -}; - -MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); - -STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { - mod_network_socket_obj_t *self = self_in; - mp_int_t ret = wlan_socket_recv(self, buf, size, errcode); - if (ret < 0) { - // we need to ignore the socket closed error here because a read() without params - // only returns when the socket is closed by the other end - if (*errcode != -SL_ESECCLOSED) { - ret = MP_STREAM_ERROR; - } else { - ret = 0; - } - } - return ret; -} - -STATIC mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { - mod_network_socket_obj_t *self = self_in; - mp_int_t ret = wlan_socket_send(self, buf, size, errcode); - if (ret < 0) { - ret = MP_STREAM_ERROR; - } - return ret; -} - -STATIC mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { - mod_network_socket_obj_t *self = self_in; - return wlan_socket_ioctl(self, request, arg, errcode); -} - -const mp_stream_p_t socket_stream_p = { - .read = socket_read, - .write = socket_write, - .ioctl = socket_ioctl, - .is_text = false, -}; - -STATIC const mp_obj_type_t socket_type = { - { &mp_type_type }, - .name = MP_QSTR_socket, - .make_new = socket_make_new, - .protocol = &socket_stream_p, - .locals_dict = (mp_obj_t)&socket_locals_dict, -}; - -/******************************************************************************/ -// usocket module - -// function usocket.getaddrinfo(host, port) -/// \function getaddrinfo(host, port) -STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { - size_t hlen; - const char *host = mp_obj_str_get_data(host_in, &hlen); - mp_int_t port = mp_obj_get_int(port_in); - - // ipv4 only - uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - int32_t result = wlan_gethostbyname(host, hlen, out_ip, SL_AF_INET); - if (result < 0) { - mp_raise_OSError(-result); - } - mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); - tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SL_AF_INET); - tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM); - tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); - tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); - tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE); - return mp_obj_new_list(1, (mp_obj_t*)&tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo); - -STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, - - { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, - { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_usocket_getaddrinfo_obj) }, - - // class constants - { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(SL_AF_INET) }, - - { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SL_SOCK_STREAM) }, - { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SL_SOCK_DGRAM) }, - - { MP_ROM_QSTR(MP_QSTR_IPPROTO_SEC), MP_ROM_INT(SL_SEC_SOCKET) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(SL_IPPROTO_TCP) }, - { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(SL_IPPROTO_UDP) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); - -const mp_obj_module_t mp_module_usocket = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, -}; diff --git a/ports/cc3200/mods/modussl.c b/ports/cc3200/mods/modussl.c index 3211570499247..76d0617e421f0 100644 --- a/ports/cc3200/mods/modussl.c +++ b/ports/cc3200/mods/modussl.c @@ -47,7 +47,7 @@ ******************************************************************************/ typedef struct _mp_obj_ssl_socket_t { mp_obj_base_t base; - mod_network_socket_base_t sock_base; + mod_network_socket_obj_t sock_base; mp_obj_t o_sock; } mp_obj_ssl_socket_t; @@ -102,7 +102,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ } _i16 _errno; - _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd; + _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sd; // set the requested SSL method _u8 method = args[5].u_int; @@ -122,7 +122,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ // create the ssl socket mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t); // ssl sockets inherit all properties from the original socket - memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t)); + memcpy (&ssl_sock->sock_base, ((mod_network_socket_obj_t *)args[0].u_obj), sizeof(mod_network_socket_obj_t)); ssl_sock->base.type = &ssl_socket_type; ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false; ssl_sock->o_sock = args[0].u_obj; diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c deleted file mode 100644 index 8acc89da38b5a..0000000000000 --- a/ports/cc3200/mods/modwlan.c +++ /dev/null @@ -1,1303 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Daniel Campora - * - * 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 - -#include "simplelink.h" -#include "py/mpconfig.h" -#include "py/obj.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mphal.h" -#include "lib/timeutils/timeutils.h" -#include "lib/netutils/netutils.h" -#include "modnetwork.h" -#include "modusocket.h" -#include "modwlan.h" -#include "pybrtc.h" -#include "debug.h" -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) -#include "serverstask.h" -#endif -#include "mpexception.h" -#include "mpirq.h" -#include "pybsleep.h" -#include "antenna.h" - - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ -// Status bits - These are used to set/reset the corresponding bits in a given variable -typedef enum{ - STATUS_BIT_NWP_INIT = 0, // If this bit is set: Network Processor is - // powered up - - STATUS_BIT_CONNECTION, // If this bit is set: the device is connected to - // the AP or client is connected to device (AP) - - STATUS_BIT_IP_LEASED, // If this bit is set: the device has leased IP to - // any connected client - - STATUS_BIT_IP_ACQUIRED, // If this bit is set: the device has acquired an IP - - STATUS_BIT_SMARTCONFIG_START, // If this bit is set: the SmartConfiguration - // process is started from SmartConfig app - - STATUS_BIT_P2P_DEV_FOUND, // If this bit is set: the device (P2P mode) - // found any p2p-device in scan - - STATUS_BIT_P2P_REQ_RECEIVED, // If this bit is set: the device (P2P mode) - // found any p2p-negotiation request - - STATUS_BIT_CONNECTION_FAILED, // If this bit is set: the device(P2P mode) - // connection to client(or reverse way) is failed - - STATUS_BIT_PING_DONE // If this bit is set: the device has completed - // the ping operation -} e_StatusBits; - -/****************************************************************************** - DEFINE CONSTANTS - ******************************************************************************/ -#define CLR_STATUS_BIT_ALL(status) (status = 0) -#define SET_STATUS_BIT(status, bit) (status |= ( 1 << (bit))) -#define CLR_STATUS_BIT(status, bit) (status &= ~(1 << (bit))) -#define GET_STATUS_BIT(status, bit) (0 != (status & (1 << (bit)))) - -#define IS_NW_PROCSR_ON(status) GET_STATUS_BIT(status, STATUS_BIT_NWP_INIT) -#define IS_CONNECTED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION) -#define IS_IP_LEASED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_LEASED) -#define IS_IP_ACQUIRED(status) GET_STATUS_BIT(status, STATUS_BIT_IP_ACQUIRED) -#define IS_SMART_CFG_START(status) GET_STATUS_BIT(status, STATUS_BIT_SMARTCONFIG_START) -#define IS_P2P_DEV_FOUND(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_DEV_FOUND) -#define IS_P2P_REQ_RCVD(status) GET_STATUS_BIT(status, STATUS_BIT_P2P_REQ_RECEIVED) -#define IS_CONNECT_FAILED(status) GET_STATUS_BIT(status, STATUS_BIT_CONNECTION_FAILED) -#define IS_PING_DONE(status) GET_STATUS_BIT(status, STATUS_BIT_PING_DONE) - -#define MODWLAN_SL_SCAN_ENABLE 1 -#define MODWLAN_SL_SCAN_DISABLE 0 -#define MODWLAN_SL_MAX_NETWORKS 20 - -#define MODWLAN_MAX_NETWORKS 20 -#define MODWLAN_SCAN_PERIOD_S 3600 // 1 hour -#define MODWLAN_WAIT_FOR_SCAN_MS 1050 -#define MODWLAN_CONNECTION_WAIT_MS 2 - -#define ASSERT_ON_ERROR(x) ASSERT((x) >= 0) - -/****************************************************************************** - DECLARE PRIVATE DATA - ******************************************************************************/ -STATIC wlan_obj_t wlan_obj = { - .mode = -1, - .status = 0, - .ip = 0, - .auth = MICROPY_PORT_WLAN_AP_SECURITY, - .channel = MICROPY_PORT_WLAN_AP_CHANNEL, - .ssid = MICROPY_PORT_WLAN_AP_SSID, - .key = MICROPY_PORT_WLAN_AP_KEY, - .mac = {0}, - //.ssid_o = {0}, - //.bssid = {0}, - #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - .servers_enabled = false, - #endif -}; - -STATIC const mp_irq_methods_t wlan_irq_methods; - -/****************************************************************************** - DECLARE PUBLIC DATA - ******************************************************************************/ -#ifdef SL_PLATFORM_MULTI_THREADED -OsiLockObj_t wlan_LockObj; -#endif - -/****************************************************************************** - DECLARE PRIVATE FUNCTIONS - ******************************************************************************/ -STATIC void wlan_clear_data (void); -STATIC void wlan_reenable (SlWlanMode_t mode); -STATIC void wlan_servers_start (void); -STATIC void wlan_servers_stop (void); -STATIC void wlan_reset (void); -STATIC void wlan_validate_mode (uint mode); -STATIC void wlan_set_mode (uint mode); -STATIC void wlan_validate_ssid_len (uint32_t len); -STATIC void wlan_set_ssid (const char *ssid, uint8_t len, bool add_mac); -STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len); -STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len); -STATIC void wlan_validate_channel (uint8_t channel); -STATIC void wlan_set_channel (uint8_t channel); -#if MICROPY_HW_ANTENNA_DIVERSITY -STATIC void wlan_validate_antenna (uint8_t antenna); -STATIC void wlan_set_antenna (uint8_t antenna); -#endif -STATIC void wlan_sl_disconnect (void); -STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, - const char* key, uint32_t key_len, int32_t timeout); -STATIC void wlan_get_sl_mac (void); -STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out); -STATIC void wlan_lpds_irq_enable (mp_obj_t self_in); -STATIC void wlan_lpds_irq_disable (mp_obj_t self_in); -STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid); - -//***************************************************************************** -// -//! \brief The Function Handles WLAN Events -//! -//! \param[in] pWlanEvent - Pointer to WLAN Event Info -//! -//! \return None -//! -//***************************************************************************** -void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) { - if (!pWlanEvent) { - return; - } - - switch(pWlanEvent->Event) - { - case SL_WLAN_CONNECT_EVENT: - { - //slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected; - // copy the new connection data - //memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH); - //memcpy(wlan_obj.ssid_o, pEventData->ssid_name, pEventData->ssid_len); - //wlan_obj.ssid_o[pEventData->ssid_len] = '\0'; - SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); - #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - // we must reset the servers in case that the last connection - // was lost without any notification being received - servers_reset(); - #endif - } - break; - case SL_WLAN_DISCONNECT_EVENT: - CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); - CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED); - #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - servers_reset(); - servers_wlan_cycle_power(); - #endif - break; - case SL_WLAN_STA_CONNECTED_EVENT: - { - //slPeerInfoAsyncResponse_t *pEventData = &pWlanEvent->EventData.APModeStaConnected; - // get the mac address and name of the connected device - //memcpy(wlan_obj.bssid, pEventData->mac, SL_BSSID_LENGTH); - //memcpy(wlan_obj.ssid_o, pEventData->go_peer_device_name, pEventData->go_peer_device_name_len); - //wlan_obj.ssid_o[pEventData->go_peer_device_name_len] = '\0'; - SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); - #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - // we must reset the servers in case that the last connection - // was lost without any notification being received - servers_reset(); - #endif - } - break; - case SL_WLAN_STA_DISCONNECTED_EVENT: - CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); - #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - servers_reset(); - servers_wlan_cycle_power(); - #endif - break; - case SL_WLAN_P2P_DEV_FOUND_EVENT: - // TODO - break; - case SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT: - // TODO - break; - case SL_WLAN_CONNECTION_FAILED_EVENT: - // TODO - break; - default: - break; - } -} - -//***************************************************************************** -// -//! \brief This function handles network events such as IP acquisition, IP -//! leased, IP released etc. -//! -//! \param[in] pNetAppEvent - Pointer to NetApp Event Info -//! -//! \return None -//! -//***************************************************************************** -void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent) { - if(!pNetAppEvent) { - return; - } - - switch(pNetAppEvent->Event) - { - case SL_NETAPP_IPV4_IPACQUIRED_EVENT: - { - SlIpV4AcquiredAsync_t *pEventData = NULL; - - SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED); - - // Ip Acquired Event Data - pEventData = &pNetAppEvent->EventData.ipAcquiredV4; - - // Get the ip - wlan_obj.ip = pEventData->ip; - } - break; - case SL_NETAPP_IPV6_IPACQUIRED_EVENT: - break; - case SL_NETAPP_IP_LEASED_EVENT: - break; - case SL_NETAPP_IP_RELEASED_EVENT: - break; - default: - break; - } -} - -//***************************************************************************** -// -//! \brief This function handles HTTP server events -//! -//! \param[in] pServerEvent - Contains the relevant event information -//! \param[in] pServerResponse - Should be filled by the user with the -//! relevant response information -//! -//! \return None -//! -//**************************************************************************** -void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent, SlHttpServerResponse_t *pHttpResponse) { - if (!pHttpEvent) { - return; - } - - switch (pHttpEvent->Event) { - case SL_NETAPP_HTTPGETTOKENVALUE_EVENT: - break; - case SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT: - break; - default: - break; - } -} - -//***************************************************************************** -// -//! \brief This function handles General Events -//! -//! \param[in] pDevEvent - Pointer to General Event Info -//! -//! \return None -//! -//***************************************************************************** -void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent) { - if (!pDevEvent) { - return; - } -} - -//***************************************************************************** -// -//! This function handles socket events indication -//! -//! \param[in] pSock - Pointer to Socket Event Info -//! -//! \return None -//! -//***************************************************************************** -void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) { - if (!pSock) { - return; - } - - switch( pSock->Event ) { - case SL_SOCKET_TX_FAILED_EVENT: - switch( pSock->socketAsyncEvent.SockTxFailData.status) { - case SL_ECLOSE: - break; - default: - break; - } - break; - case SL_SOCKET_ASYNC_EVENT: - switch(pSock->socketAsyncEvent.SockAsyncData.type) { - case SSL_ACCEPT: - break; - case RX_FRAGMENTATION_TOO_BIG: - break; - case OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED: - break; - default: - break; - } - break; - default: - break; - } -} - -//***************************************************************************** -// SimpleLink Asynchronous Event Handlers -- End -//***************************************************************************** - -__attribute__ ((section (".boot"))) -void wlan_pre_init (void) { - // create the wlan lock - #ifdef SL_PLATFORM_MULTI_THREADED - ASSERT(OSI_OK == sl_LockObjCreate(&wlan_LockObj, "WlanLock")); - #endif -} - -void wlan_first_start (void) { - if (wlan_obj.mode < 0) { - CLR_STATUS_BIT_ALL(wlan_obj.status); - wlan_obj.mode = sl_Start(0, 0, 0); - #ifdef SL_PLATFORM_MULTI_THREADED - sl_LockObjUnlock (&wlan_LockObj); - #endif - } - - // get the mac address - wlan_get_sl_mac(); -} - -void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth, const char *key, uint8_t key_len, - uint8_t channel, uint8_t antenna, bool add_mac) { - - // stop the servers - wlan_servers_stop(); - - // do a basic start - wlan_first_start(); - - // close any active connections - wlan_sl_disconnect(); - - // Remove all profiles - ASSERT_ON_ERROR(sl_WlanProfileDel(0xFF)); - - // Enable the DHCP client - uint8_t value = 1; - ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, 1, 1, &value)); - - // Set PM policy to normal - ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_PM, SL_NORMAL_POLICY, NULL, 0)); - - // Unregister mDNS services - ASSERT_ON_ERROR(sl_NetAppMDNSUnRegisterService(0, 0)); - - // Stop the internal HTTP server - sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); - - // Remove all 64 filters (8 * 8) - _WlanRxFilterOperationCommandBuff_t RxFilterIdMask; - memset ((void *)&RxFilterIdMask, 0 ,sizeof(RxFilterIdMask)); - memset(RxFilterIdMask.FilterIdMask, 0xFF, 8); - ASSERT_ON_ERROR(sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (_u8 *)&RxFilterIdMask, sizeof(_WlanRxFilterOperationCommandBuff_t))); - -#if MICROPY_HW_ANTENNA_DIVERSITY - // set the antenna type - wlan_set_antenna (antenna); -#endif - - // switch to the requested mode - wlan_set_mode(mode); - - // stop and start again (we need to in the propper mode from now on) - wlan_reenable(mode); - - // Set Tx power level for station or AP mode - // Number between 0-15, as dB offset from max power - 0 will set max power - uint8_t ucPower = 0; - if (mode == ROLE_AP) { - ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_AP_TX_POWER, sizeof(ucPower), - (unsigned char *)&ucPower)); - - // configure all parameters - wlan_set_ssid (ssid, ssid_len, add_mac); - wlan_set_security (auth, key, key_len); - wlan_set_channel (channel); - - // set the country - _u8* country = (_u8*)"EU"; - ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, country)); - - SlNetCfgIpV4Args_t ipV4; - ipV4.ipV4 = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 IP address - ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP - ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 Default gateway address - ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 DNS server address - ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, - sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); - - SlNetAppDhcpServerBasicOpt_t dhcpParams; - dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address - dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,2); // first IP Address for allocation. - dhcpParams.ipv4_addr_last = SL_IPV4_VAL(192,168,1,254); // last IP Address for allocation. - ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // Stop DHCP server before settings - ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, - sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters - ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // Start DHCP server with new settings - - // stop and start again - wlan_reenable(mode); - } else { // STA and P2P modes - ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, - sizeof(ucPower), (unsigned char *)&ucPower)); - // set connection policy to Auto + Fast (tries to connect to the last connected AP) - ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 1, 0, 0, 0), NULL, 0)); - } - - // set current time and date (needed to validate certificates) - wlan_set_current_time (pyb_rtc_get_seconds()); - - // start the servers before returning - wlan_servers_start(); -} - -void wlan_update(void) { -#ifndef SL_PLATFORM_MULTI_THREADED - _SlTaskEntry(); -#endif -} - -void wlan_stop (uint32_t timeout) { - wlan_servers_stop(); - #ifdef SL_PLATFORM_MULTI_THREADED - sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); - #endif - sl_Stop(timeout); - wlan_clear_data(); - wlan_obj.mode = -1; -} - -void wlan_get_mac (uint8_t *macAddress) { - if (macAddress) { - memcpy (macAddress, wlan_obj.mac, SL_MAC_ADDR_LEN); - } -} - -void wlan_get_ip (uint32_t *ip) { - if (ip) { - *ip = IS_IP_ACQUIRED(wlan_obj.status) ? wlan_obj.ip : 0; - } -} - -bool wlan_is_connected (void) { - return (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION) && - (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED) || wlan_obj.mode != ROLE_STA)); -} - -void wlan_set_current_time (uint32_t seconds_since_2000) { - timeutils_struct_time_t tm; - timeutils_seconds_since_2000_to_struct_time(seconds_since_2000, &tm); - - SlDateTime_t sl_datetime = {0}; - sl_datetime.sl_tm_day = tm.tm_mday; - sl_datetime.sl_tm_mon = tm.tm_mon; - sl_datetime.sl_tm_year = tm.tm_year; - sl_datetime.sl_tm_hour = tm.tm_hour; - sl_datetime.sl_tm_min = tm.tm_min; - sl_datetime.sl_tm_sec = tm.tm_sec; - sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, sizeof(SlDateTime_t), (_u8 *)(&sl_datetime)); -} - -void wlan_off_on (void) { - // no need to lock the WLAN object on every API call since the servers and the MicroPtyhon - // task have the same priority - wlan_reenable(wlan_obj.mode); -} - -//***************************************************************************** -// DEFINE STATIC FUNCTIONS -//***************************************************************************** - -STATIC void wlan_clear_data (void) { - CLR_STATUS_BIT_ALL(wlan_obj.status); - wlan_obj.ip = 0; - //memset(wlan_obj.ssid_o, 0, sizeof(wlan_obj.ssid)); - //memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid)); -} - -STATIC void wlan_reenable (SlWlanMode_t mode) { - // stop and start again - #ifdef SL_PLATFORM_MULTI_THREADED - sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER); - #endif - sl_Stop(SL_STOP_TIMEOUT); - wlan_clear_data(); - wlan_obj.mode = sl_Start(0, 0, 0); - #ifdef SL_PLATFORM_MULTI_THREADED - sl_LockObjUnlock (&wlan_LockObj); - #endif - ASSERT (wlan_obj.mode == mode); -} - -STATIC void wlan_servers_start (void) { -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - // start the servers if they were enabled before - if (wlan_obj.servers_enabled) { - servers_start(); - } -#endif -} - -STATIC void wlan_servers_stop (void) { -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - // Stop all other processes using the wlan engine - if ((wlan_obj.servers_enabled = servers_are_enabled())) { - servers_stop(); - } -#endif -} - -STATIC void wlan_reset (void) { - wlan_servers_stop(); - wlan_reenable (wlan_obj.mode); - wlan_servers_start(); -} - -STATIC void wlan_validate_mode (uint mode) { - if (mode != ROLE_STA && mode != ROLE_AP) { - mp_raise_ValueError(mpexception_value_invalid_arguments); - } -} - -STATIC void wlan_set_mode (uint mode) { - wlan_obj.mode = mode; - ASSERT_ON_ERROR(sl_WlanSetMode(mode)); -} - -STATIC void wlan_validate_ssid_len (uint32_t len) { - if (len > MODWLAN_SSID_LEN_MAX) { - mp_raise_ValueError(mpexception_value_invalid_arguments); - } -} - -STATIC void wlan_set_ssid (const char *ssid, uint8_t len, bool add_mac) { - if (ssid != NULL) { - // save the ssid - memcpy(&wlan_obj.ssid, ssid, len); - // append the last 2 bytes of the MAC address, since the use of this functionality is under our control - // we can assume that the lenght of the ssid is less than (32 - 5) - if (add_mac) { - snprintf((char *)&wlan_obj.ssid[len], sizeof(wlan_obj.ssid) - len, "-%02x%02x", wlan_obj.mac[4], wlan_obj.mac[5]); - len += 5; - } - wlan_obj.ssid[len] = '\0'; - ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID, len, (unsigned char *)wlan_obj.ssid)); - } -} - -STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len) { - if (auth != SL_SEC_TYPE_WEP && auth != SL_SEC_TYPE_WPA_WPA2) { - goto invalid_args; - } - if (auth == SL_SEC_TYPE_WEP) { - for (mp_uint_t i = strlen(key); i > 0; i--) { - if (!unichar_isxdigit(*key++)) { - goto invalid_args; - } - } - } - return; - -invalid_args: - mp_raise_ValueError(mpexception_value_invalid_arguments); -} - -STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) { - wlan_obj.auth = auth; - ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, sizeof(uint8_t), &auth)); - if (key != NULL) { - memcpy(&wlan_obj.key, key, len); - wlan_obj.key[len] = '\0'; - if (auth == SL_SEC_TYPE_WEP) { - _u8 wep_key[32]; - wlan_wep_key_unhexlify(key, (char *)&wep_key); - key = (const char *)&wep_key; - len /= 2; - } - ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, len, (unsigned char *)key)); - } else { - wlan_obj.key[0] = '\0'; - } -} - -STATIC void wlan_validate_channel (uint8_t channel) { - if (channel < 1 || channel > 11) { - mp_raise_ValueError(mpexception_value_invalid_arguments); - } -} - -STATIC void wlan_set_channel (uint8_t channel) { - wlan_obj.channel = channel; - ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, &channel)); -} - -#if MICROPY_HW_ANTENNA_DIVERSITY -STATIC void wlan_validate_antenna (uint8_t antenna) { - if (antenna != ANTENNA_TYPE_INTERNAL && antenna != ANTENNA_TYPE_EXTERNAL) { - mp_raise_ValueError(mpexception_value_invalid_arguments); - } -} - -STATIC void wlan_set_antenna (uint8_t antenna) { - wlan_obj.antenna = antenna; - antenna_select(antenna); -} -#endif - -STATIC void wlan_sl_disconnect (void) { - // Device in station-mode. Disconnect previous connection if any - // The function returns 0 if 'Disconnected done', negative number if already - // disconnected Wait for 'disconnection' event if 0 is returned, Ignore - // other return-codes - if (0 == sl_WlanDisconnect()) { - while (IS_CONNECTED(wlan_obj.status)) { - mp_hal_delay_ms(MODWLAN_CONNECTION_WAIT_MS); - wlan_update(); - } - } -} - -STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec, - const char* key, uint32_t key_len, int32_t timeout) { - SlSecParams_t secParams; - secParams.Key = (_i8*)key; - secParams.KeyLen = ((key != NULL) ? key_len : 0); - secParams.Type = sec; - - // first close any active connections - wlan_sl_disconnect(); - - if (!sl_WlanConnect((_i8*)ssid, ssid_len, (_u8*)bssid, &secParams, NULL)) { - // wait for the WLAN Event - uint32_t waitForConnectionMs = 0; - while (timeout && !IS_CONNECTED(wlan_obj.status)) { - mp_hal_delay_ms(MODWLAN_CONNECTION_WAIT_MS); - waitForConnectionMs += MODWLAN_CONNECTION_WAIT_MS; - if (timeout > 0 && waitForConnectionMs > timeout) { - return MODWLAN_ERROR_TIMEOUT; - } - wlan_update(); - } - return MODWLAN_OK; - } - return MODWLAN_ERROR_INVALID_PARAMS; -} - -STATIC void wlan_get_sl_mac (void) { - // Get the MAC address - uint8_t macAddrLen = SL_MAC_ADDR_LEN; - sl_NetCfgGet(SL_MAC_ADDRESS_GET, NULL, &macAddrLen, wlan_obj.mac); -} - -STATIC void wlan_wep_key_unhexlify (const char *key, char *key_out) { - byte hex_byte = 0; - for (mp_uint_t i = strlen(key); i > 0 ; i--) { - hex_byte += unichar_xdigit_value(*key++); - if (i & 1) { - hex_byte <<= 4; - } else { - *key_out++ = hex_byte; - hex_byte = 0; - } - } -} - -STATIC void wlan_lpds_irq_enable (mp_obj_t self_in) { - wlan_obj_t *self = self_in; - self->irq_enabled = true; -} - -STATIC void wlan_lpds_irq_disable (mp_obj_t self_in) { - wlan_obj_t *self = self_in; - self->irq_enabled = false; -} - -STATIC int wlan_irq_flags (mp_obj_t self_in) { - wlan_obj_t *self = self_in; - return self->irq_flags; -} - -STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid) { - for (int i = 0; i < nets->len; i++) { - // index 1 in the list is the bssid - mp_obj_str_t *_bssid = (mp_obj_str_t *)((mp_obj_tuple_t *)nets->items[i])->items[1]; - if (!memcmp (_bssid->data, bssid, SL_BSSID_LENGTH)) { - return false; - } - } - return true; -} - -/******************************************************************************/ -// MicroPython bindings; WLAN class - -/// \class WLAN - WiFi driver - -STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) { - // get the mode - int8_t mode = args[0].u_int; - wlan_validate_mode(mode); - - // get the ssid - size_t ssid_len = 0; - const char *ssid = NULL; - if (args[1].u_obj != NULL) { - ssid = mp_obj_str_get_data(args[1].u_obj, &ssid_len); - wlan_validate_ssid_len(ssid_len); - } - - // get the auth config - uint8_t auth = SL_SEC_TYPE_OPEN; - size_t key_len = 0; - const char *key = NULL; - if (args[2].u_obj != mp_const_none) { - mp_obj_t *sec; - mp_obj_get_array_fixed_n(args[2].u_obj, 2, &sec); - auth = mp_obj_get_int(sec[0]); - key = mp_obj_str_get_data(sec[1], &key_len); - wlan_validate_security(auth, key, key_len); - } - - // get the channel - uint8_t channel = args[3].u_int; - wlan_validate_channel(channel); - - // get the antenna type - uint8_t antenna = 0; -#if MICROPY_HW_ANTENNA_DIVERSITY - antenna = args[4].u_int; - wlan_validate_antenna(antenna); -#endif - - // initialize the wlan subsystem - wlan_sl_init(mode, (const char *)ssid, ssid_len, auth, (const char *)key, key_len, channel, antenna, false); - - return mp_const_none; -} - -STATIC const mp_arg_t wlan_init_args[] = { - { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_mode, MP_ARG_INT, {.u_int = ROLE_STA} }, - { MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, - #if MICROPY_HW_ANTENNA_DIVERSITY - { MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} }, - #endif -}; -STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // parse args - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args); - mp_arg_val_t args[MP_ARRAY_SIZE(wlan_init_args)]; - mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), wlan_init_args, args); - - // setup the object - wlan_obj_t *self = &wlan_obj; - self->base.type = (mp_obj_t)&mod_network_nic_type_wlan; - - // give it to the sleep module - pyb_sleep_set_wlan_obj(self); - - if (n_args > 1 || n_kw > 0) { - // check the peripheral id - if (args[0].u_int != 0) { - mp_raise_OSError(MP_ENODEV); - } - // start the peripheral - wlan_init_helper(self, &args[1]); - } - - return (mp_obj_t)self; -} - -STATIC mp_obj_t wlan_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(wlan_init_args) - 1]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &wlan_init_args[1], args); - return wlan_init_helper(pos_args[0], args); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_init_obj, 1, wlan_init); - -STATIC mp_obj_t wlan_scan(mp_obj_t self_in) { - STATIC const qstr wlan_scan_info_fields[] = { - MP_QSTR_ssid, MP_QSTR_bssid, MP_QSTR_sec, MP_QSTR_channel, MP_QSTR_rssi - }; - - // check for correct wlan mode - if (wlan_obj.mode == ROLE_AP) { - mp_raise_OSError(MP_EPERM); - } - - Sl_WlanNetworkEntry_t wlanEntry; - mp_obj_t nets = mp_obj_new_list(0, NULL); - uint8_t _index = 0; - - // trigger a new network scan - uint32_t scanSeconds = MODWLAN_SCAN_PERIOD_S; - ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_SCAN , MODWLAN_SL_SCAN_ENABLE, (_u8 *)&scanSeconds, sizeof(scanSeconds))); - - // wait for the scan to complete - mp_hal_delay_ms(MODWLAN_WAIT_FOR_SCAN_MS); - - do { - if (sl_WlanGetNetworkList(_index++, 1, &wlanEntry) <= 0) { - break; - } - - // we must skip any duplicated results - if (!wlan_scan_result_is_unique(nets, wlanEntry.bssid)) { - continue; - } - - mp_obj_t tuple[5]; - tuple[0] = mp_obj_new_str((const char *)wlanEntry.ssid, wlanEntry.ssid_len); - tuple[1] = mp_obj_new_bytes((const byte *)wlanEntry.bssid, SL_BSSID_LENGTH); - // 'normalize' the security type - if (wlanEntry.sec_type > 2) { - wlanEntry.sec_type = 2; - } - tuple[2] = mp_obj_new_int(wlanEntry.sec_type); - tuple[3] = mp_const_none; - tuple[4] = mp_obj_new_int(wlanEntry.rssi); - - // add the network to the list - mp_obj_list_append(nets, mp_obj_new_attrtuple(wlan_scan_info_fields, 5, tuple)); - - } while (_index < MODWLAN_SL_MAX_NETWORKS); - - return nets; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan); - -STATIC mp_obj_t wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, }, - { MP_QSTR_auth, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - // check for the correct wlan mode - if (wlan_obj.mode == ROLE_AP) { - mp_raise_OSError(MP_EPERM); - } - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // get the ssid - size_t ssid_len; - const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len); - wlan_validate_ssid_len(ssid_len); - - // get the auth config - uint8_t auth = SL_SEC_TYPE_OPEN; - size_t key_len = 0; - const char *key = NULL; - if (args[1].u_obj != mp_const_none) { - mp_obj_t *sec; - mp_obj_get_array_fixed_n(args[1].u_obj, 2, &sec); - auth = mp_obj_get_int(sec[0]); - key = mp_obj_str_get_data(sec[1], &key_len); - wlan_validate_security(auth, key, key_len); - - // convert the wep key if needed - if (auth == SL_SEC_TYPE_WEP) { - _u8 wep_key[32]; - wlan_wep_key_unhexlify(key, (char *)&wep_key); - key = (const char *)&wep_key; - key_len /= 2; - } - } - - // get the bssid - const char *bssid = NULL; - if (args[2].u_obj != mp_const_none) { - bssid = mp_obj_str_get_str(args[2].u_obj); - } - - // get the timeout - int32_t timeout = -1; - if (args[3].u_obj != mp_const_none) { - timeout = mp_obj_get_int(args[3].u_obj); - } - - // connect to the requested access point - modwlan_Status_t status; - status = wlan_do_connect (ssid, ssid_len, bssid, auth, key, key_len, timeout); - if (status == MODWLAN_ERROR_TIMEOUT) { - mp_raise_OSError(MP_ETIMEDOUT); - } else if (status == MODWLAN_ERROR_INVALID_PARAMS) { - mp_raise_ValueError(mpexception_value_invalid_arguments); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_connect_obj, 1, wlan_connect); - -STATIC mp_obj_t wlan_disconnect(mp_obj_t self_in) { - wlan_sl_disconnect(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_disconnect_obj, wlan_disconnect); - -STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) { - return wlan_is_connected() ? mp_const_true : mp_const_false; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_isconnected_obj, wlan_isconnected); - -STATIC mp_obj_t wlan_ifconfig(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - STATIC const mp_arg_t wlan_ifconfig_args[] = { - { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_config, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(wlan_ifconfig_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), wlan_ifconfig_args, args); - - // check the interface id - if (args[0].u_int != 0) { - mp_raise_OSError(MP_EPERM); - } - - // get the configuration - if (args[1].u_obj == MP_OBJ_NULL) { - // get - unsigned char len = sizeof(SlNetCfgIpV4Args_t); - unsigned char dhcpIsOn; - SlNetCfgIpV4Args_t ipV4; - sl_NetCfgGet(SL_IPV4_STA_P2P_CL_GET_INFO, &dhcpIsOn, &len, (uint8_t *)&ipV4); - - mp_obj_t ifconfig[4] = { - netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4, NETUTILS_LITTLE), - netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE), - netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4Gateway, NETUTILS_LITTLE), - netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4DnsServer, NETUTILS_LITTLE) - }; - return mp_obj_new_tuple(4, ifconfig); - } else { // set the configuration - if (MP_OBJ_IS_TYPE(args[1].u_obj, &mp_type_tuple)) { - // set a static ip - mp_obj_t *items; - mp_obj_get_array_fixed_n(args[1].u_obj, 4, &items); - - SlNetCfgIpV4Args_t ipV4; - netutils_parse_ipv4_addr(items[0], (uint8_t *)&ipV4.ipV4, NETUTILS_LITTLE); - netutils_parse_ipv4_addr(items[1], (uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE); - netutils_parse_ipv4_addr(items[2], (uint8_t *)&ipV4.ipV4Gateway, NETUTILS_LITTLE); - netutils_parse_ipv4_addr(items[3], (uint8_t *)&ipV4.ipV4DnsServer, NETUTILS_LITTLE); - - if (wlan_obj.mode == ROLE_AP) { - ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); - SlNetAppDhcpServerBasicOpt_t dhcpParams; - dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address - dhcpParams.ipv4_addr_start = ipV4.ipV4 + 1; // first IP Address for allocation. - dhcpParams.ipv4_addr_last = (ipV4.ipV4 & 0xFFFFFF00) + 254; // last IP Address for allocation. - ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // stop DHCP server before settings - ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, - sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters - ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // start DHCP server with new settings - } else { - ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4)); - } - } else { - // check for the correct string - const char *mode = mp_obj_str_get_str(args[1].u_obj); - if (strcmp("dhcp", mode)) { - mp_raise_ValueError(mpexception_value_invalid_arguments); - } - - // only if we are not in AP mode - if (wlan_obj.mode != ROLE_AP) { - _u8 val = 1; - sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, 1, &val); - } - } - // config values have changed, so reset - wlan_reset(); - // set current time and date (needed to validate certificates) - wlan_set_current_time (pyb_rtc_get_seconds()); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_ifconfig_obj, 1, wlan_ifconfig); - -STATIC mp_obj_t wlan_mode(size_t n_args, const mp_obj_t *args) { - wlan_obj_t *self = args[0]; - if (n_args == 1) { - return mp_obj_new_int(self->mode); - } else { - uint mode = mp_obj_get_int(args[1]); - wlan_validate_mode(mode); - wlan_set_mode(mode); - wlan_reset(); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mode_obj, 1, 2, wlan_mode); - -STATIC mp_obj_t wlan_ssid(size_t n_args, const mp_obj_t *args) { - wlan_obj_t *self = args[0]; - if (n_args == 1) { - return mp_obj_new_str((const char *)self->ssid, strlen((const char *)self->ssid)); - } else { - size_t len; - const char *ssid = mp_obj_str_get_data(args[1], &len); - wlan_validate_ssid_len(len); - wlan_set_ssid(ssid, len, false); - wlan_reset(); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_ssid_obj, 1, 2, wlan_ssid); - -STATIC mp_obj_t wlan_auth(size_t n_args, const mp_obj_t *args) { - wlan_obj_t *self = args[0]; - if (n_args == 1) { - if (self->auth == SL_SEC_TYPE_OPEN) { - return mp_const_none; - } else { - mp_obj_t security[2]; - security[0] = mp_obj_new_int(self->auth); - security[1] = mp_obj_new_str((const char *)self->key, strlen((const char *)self->key)); - return mp_obj_new_tuple(2, security); - } - } else { - // get the auth config - uint8_t auth = SL_SEC_TYPE_OPEN; - size_t key_len = 0; - const char *key = NULL; - if (args[1] != mp_const_none) { - mp_obj_t *sec; - mp_obj_get_array_fixed_n(args[1], 2, &sec); - auth = mp_obj_get_int(sec[0]); - key = mp_obj_str_get_data(sec[1], &key_len); - wlan_validate_security(auth, key, key_len); - } - wlan_set_security(auth, key, key_len); - wlan_reset(); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_auth_obj, 1, 2, wlan_auth); - -STATIC mp_obj_t wlan_channel(size_t n_args, const mp_obj_t *args) { - wlan_obj_t *self = args[0]; - if (n_args == 1) { - return mp_obj_new_int(self->channel); - } else { - uint8_t channel = mp_obj_get_int(args[1]); - wlan_validate_channel(channel); - wlan_set_channel(channel); - wlan_reset(); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_channel_obj, 1, 2, wlan_channel); - -STATIC mp_obj_t wlan_antenna(size_t n_args, const mp_obj_t *args) { - wlan_obj_t *self = args[0]; - if (n_args == 1) { - return mp_obj_new_int(self->antenna); - } else { - #if MICROPY_HW_ANTENNA_DIVERSITY - uint8_t antenna = mp_obj_get_int(args[1]); - wlan_validate_antenna(antenna); - wlan_set_antenna(antenna); - #endif - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_antenna_obj, 1, 2, wlan_antenna); - -STATIC mp_obj_t wlan_mac(size_t n_args, const mp_obj_t *args) { - wlan_obj_t *self = args[0]; - if (n_args == 1) { - return mp_obj_new_bytes((const byte *)self->mac, SL_BSSID_LENGTH); - } else { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - if (bufinfo.len != 6) { - mp_raise_ValueError(mpexception_value_invalid_arguments); - } - memcpy(self->mac, bufinfo.buf, SL_MAC_ADDR_LEN); - sl_NetCfgSet(SL_MAC_ADDRESS_SET, 1, SL_MAC_ADDR_LEN, (_u8 *)self->mac); - wlan_reset(); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_mac_obj, 1, 2, wlan_mac); - -STATIC mp_obj_t wlan_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_val_t args[mp_irq_INIT_NUM_ARGS]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args); - - wlan_obj_t *self = pos_args[0]; - - // check the trigger, only one type is supported - if (mp_obj_get_int(args[0].u_obj) != MODWLAN_WIFI_EVENT_ANY) { - goto invalid_args; - } - - // check the power mode - if (mp_obj_get_int(args[3].u_obj) != PYB_PWR_MODE_LPDS) { - goto invalid_args; - } - - // create the callback - mp_obj_t _irq = mp_irq_new (self, args[2].u_obj, &wlan_irq_methods); - self->irq_obj = _irq; - - // enable the irq just before leaving - wlan_lpds_irq_enable(self); - - return _irq; - -invalid_args: - mp_raise_ValueError(mpexception_value_invalid_arguments); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq); - -//STATIC mp_obj_t wlan_connections (mp_obj_t self_in) { -// mp_obj_t device[2]; -// mp_obj_t connections = mp_obj_new_list(0, NULL); -// -// if (wlan_is_connected()) { -// device[0] = mp_obj_new_str((const char *)wlan_obj.ssid_o, strlen((const char *)wlan_obj.ssid_o)); -// device[1] = mp_obj_new_bytes((const byte *)wlan_obj.bssid, SL_BSSID_LENGTH); -// // add the device to the list -// mp_obj_list_append(connections, mp_obj_new_tuple(MP_ARRAY_SIZE(device), device)); -// } -// return connections; -//} -//STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_connections_obj, wlan_connections); - -//STATIC mp_obj_t wlan_urn (uint n_args, const mp_obj_t *args) { -// char urn[MAX_DEVICE_URN_LEN]; -// uint8_t len = MAX_DEVICE_URN_LEN; -// -// // an URN is given, so set it -// if (n_args == 2) { -// const char *p = mp_obj_str_get_str(args[1]); -// uint8_t len = strlen(p); -// -// // the call to sl_NetAppSet corrupts the input string URN=args[1], so we copy into a local buffer -// if (len > MAX_DEVICE_URN_LEN) { -// mp_raise_ValueError(mpexception_value_invalid_arguments); -// } -// strcpy(urn, p); -// -// if (sl_NetAppSet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, len, (unsigned char *)urn) < 0) { -// mp_raise_OSError(MP_EIO); -// } -// } -// else { -// // get the URN -// if (sl_NetAppGet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, &len, (uint8_t *)urn) < 0) { -// mp_raise_OSError(MP_EIO); -// } -// return mp_obj_new_str(urn, (len - 1)); -// } -// -// return mp_const_none; -//} -//STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_urn_obj, 1, 2, wlan_urn); - -STATIC mp_obj_t wlan_print_ver(void) { - SlVersionFull ver; - byte config_opt = SL_DEVICE_GENERAL_VERSION; - byte config_len = sizeof(ver); - sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver); - printf("NWP: %d.%d.%d.%d\n", (int)ver.NwpVersion[0], (int)ver.NwpVersion[1], (int)ver.NwpVersion[2], (int)ver.NwpVersion[3]); - printf("MAC: %d.%d.%d.%d\n", (int)ver.ChipFwAndPhyVersion.FwVersion[0], (int)ver.ChipFwAndPhyVersion.FwVersion[1], - (int)ver.ChipFwAndPhyVersion.FwVersion[2], (int)ver.ChipFwAndPhyVersion.FwVersion[3]); - printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1], - ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(wlan_print_ver_fun_obj, wlan_print_ver); -STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(wlan_print_ver_obj, MP_ROM_PTR(&wlan_print_ver_fun_obj)); - -STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&wlan_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&wlan_scan_obj) }, - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&wlan_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&wlan_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wlan_isconnected_obj) }, - { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wlan_ifconfig_obj) }, - { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&wlan_mode_obj) }, - { MP_ROM_QSTR(MP_QSTR_ssid), MP_ROM_PTR(&wlan_ssid_obj) }, - { MP_ROM_QSTR(MP_QSTR_auth), MP_ROM_PTR(&wlan_auth_obj) }, - { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wlan_channel_obj) }, - { MP_ROM_QSTR(MP_QSTR_antenna), MP_ROM_PTR(&wlan_antenna_obj) }, - { MP_ROM_QSTR(MP_QSTR_mac), MP_ROM_PTR(&wlan_mac_obj) }, - { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&wlan_irq_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_connections), MP_ROM_PTR(&wlan_connections_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_urn), MP_ROM_PTR(&wlan_urn_obj) }, - { MP_ROM_QSTR(MP_QSTR_print_ver), MP_ROM_PTR(&wlan_print_ver_obj) }, - - // class constants - { MP_ROM_QSTR(MP_QSTR_STA), MP_ROM_INT(ROLE_STA) }, - { MP_ROM_QSTR(MP_QSTR_AP), MP_ROM_INT(ROLE_AP) }, - { MP_ROM_QSTR(MP_QSTR_WEP), MP_ROM_INT(SL_SEC_TYPE_WEP) }, - { MP_ROM_QSTR(MP_QSTR_WPA), MP_ROM_INT(SL_SEC_TYPE_WPA_WPA2) }, - { MP_ROM_QSTR(MP_QSTR_WPA2), MP_ROM_INT(SL_SEC_TYPE_WPA_WPA2) }, - #if MICROPY_HW_ANTENNA_DIVERSITY - { MP_ROM_QSTR(MP_QSTR_INT_ANT), MP_ROM_INT(ANTENNA_TYPE_INTERNAL) }, - { MP_ROM_QSTR(MP_QSTR_EXT_ANT), MP_ROM_INT(ANTENNA_TYPE_EXTERNAL) }, - #endif - { MP_ROM_QSTR(MP_QSTR_ANY_EVENT), MP_ROM_INT(MODWLAN_WIFI_EVENT_ANY) }, -}; -STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table); - -const mod_network_nic_type_t mod_network_nic_type_wlan = { - .base = { - { &mp_type_type }, - .name = MP_QSTR_WLAN, - .make_new = wlan_make_new, - .locals_dict = (mp_obj_t)&wlan_locals_dict, - }, -}; - -STATIC const mp_irq_methods_t wlan_irq_methods = { - .init = wlan_irq, - .enable = wlan_lpds_irq_enable, - .disable = wlan_lpds_irq_disable, - .flags = wlan_irq_flags, -}; diff --git a/ports/cc3200/mods/modwlan.h b/ports/cc3200/mods/modwlan.h deleted file mode 100644 index b806644f55e93..0000000000000 --- a/ports/cc3200/mods/modwlan.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Daniel Campora - * - * 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_CC3200_MODS_MODWLAN_H -#define MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H - -/****************************************************************************** - DEFINE CONSTANTS - ******************************************************************************/ -#define SIMPLELINK_SPAWN_TASK_PRIORITY 3 -#define SIMPLELINK_TASK_STACK_SIZE 2048 -#define SL_STOP_TIMEOUT 35 -#define SL_STOP_TIMEOUT_LONG 575 - -#define MODWLAN_WIFI_EVENT_ANY 0x01 - -#define MODWLAN_SSID_LEN_MAX 32 - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ -typedef enum { - MODWLAN_OK = 0, - MODWLAN_ERROR_INVALID_PARAMS = -1, - MODWLAN_ERROR_TIMEOUT = -2, - MODWLAN_ERROR_UNKNOWN = -3, -} modwlan_Status_t; - -typedef struct _wlan_obj_t { - mp_obj_base_t base; - mp_obj_t irq_obj; - uint32_t status; - - uint32_t ip; - - int8_t mode; - uint8_t auth; - uint8_t channel; - uint8_t antenna; - - // my own ssid, key and mac - uint8_t ssid[(MODWLAN_SSID_LEN_MAX + 1)]; - uint8_t key[65]; - uint8_t mac[SL_MAC_ADDR_LEN]; - - // the sssid (or name) and mac of the other device - uint8_t ssid_o[33]; - uint8_t bssid[6]; - uint8_t irq_flags; - bool irq_enabled; - -#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) - bool servers_enabled; -#endif -} wlan_obj_t; - -/****************************************************************************** - DECLARE PUBLIC DATA - ******************************************************************************/ -extern _SlLockObj_t wlan_LockObj; - -/****************************************************************************** - DECLARE PUBLIC FUNCTIONS - ******************************************************************************/ -extern void wlan_pre_init (void); -extern void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth, const char *key, uint8_t key_len, - uint8_t channel, uint8_t antenna, bool add_mac); -extern void wlan_first_start (void); -extern void wlan_update(void); -extern void wlan_stop (uint32_t timeout); -extern void wlan_get_mac (uint8_t *macAddress); -extern void wlan_get_ip (uint32_t *ip); -extern bool wlan_is_connected (void); -extern void wlan_set_current_time (uint32_t seconds_since_2000); -extern void wlan_off_on (void); - -#endif // MICROPY_INCLUDED_CC3200_MODS_MODWLAN_H diff --git a/ports/cc3200/mods/pybrtc.c b/ports/cc3200/mods/pybrtc.c index e7b9cf258f483..18150a1060da2 100644 --- a/ports/cc3200/mods/pybrtc.c +++ b/ports/cc3200/mods/pybrtc.c @@ -40,7 +40,7 @@ #include "pybsleep.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "mpexception.h" /// \moduleref pyb diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c index b5990e9267c0c..cff8c515ff54d 100644 --- a/ports/cc3200/mods/pybsleep.c +++ b/ports/cc3200/mods/pybsleep.c @@ -46,7 +46,7 @@ #include "pybpin.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "osi.h" #include "debug.h" #include "mpexception.h" diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index ee9a226e5c996..576a27021c8e5 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -33,7 +33,6 @@ #endif // options to control how MicroPython is built - #define MICROPY_ALLOC_PATH_MAX (128) #define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_THUMB (0) @@ -117,6 +116,8 @@ #define MICROPY_PY_UHASHLIB (0) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_NETWORK (1) +#define MICROPY_PY_USOCKET (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) @@ -195,6 +196,7 @@ extern const struct _mp_obj_module_t mp_module_ussl; mp_obj_list_t pyb_timer_channel_obj_list; \ struct _pyb_uart_obj_t *pyb_uart_objs[2]; \ struct _os_term_dup_obj_t *os_term_dup_obj; \ + mp_obj_list_t mod_network_nic_list; \ // type definitions for the specific machine diff --git a/ports/cc3200/mptask.c b/ports/cc3200/mptask.c index 6143f72a7a68f..d0b42cebb9ea9 100644 --- a/ports/cc3200/mptask.c +++ b/ports/cc3200/mptask.c @@ -56,7 +56,7 @@ #include "simplelink.h" #include "modnetwork.h" #include "modusocket.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "serverstask.h" #include "telnet.h" #include "debug.h" @@ -149,7 +149,7 @@ void TASK_MicroPython (void *pvParameters) { uart_init0(); timer_init0(); readline_init0(); - mod_network_init0(); + mod_network_init(); rng_init0(); pybsleep_reset_cause_t rstcause = pyb_sleep_get_reset_cause(); diff --git a/ports/cc3200/serverstask.c b/ports/cc3200/serverstask.c index 100b8d33b0e1e..eb0b94cd7095b 100644 --- a/ports/cc3200/serverstask.c +++ b/ports/cc3200/serverstask.c @@ -40,7 +40,7 @@ #include "modusocket.h" #include "mpexception.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" /****************************************************************************** DEFINE PRIVATE TYPES diff --git a/ports/cc3200/telnet/telnet.c b/ports/cc3200/telnet/telnet.c index dbb77cd6d762f..e1cc2f51eb921 100644 --- a/ports/cc3200/telnet/telnet.c +++ b/ports/cc3200/telnet/telnet.c @@ -33,7 +33,7 @@ #include "telnet.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "modusocket.h" #include "debug.h" #include "mpexception.h" diff --git a/ports/cc3200/util/random.c b/ports/cc3200/util/random.c index f8e9cdf0cb21f..eb006fe7be169 100644 --- a/ports/cc3200/util/random.c +++ b/ports/cc3200/util/random.c @@ -35,7 +35,7 @@ #include "pybrtc.h" #include "simplelink.h" #include "modnetwork.h" -#include "modwlan.h" +#include "modnwcc31k.h" #include "random.h" #include "debug.h" diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 85fff5e8df032..6576df4467126 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -58,12 +58,11 @@ INC += -I./modules/music INC += -I./modules/random INC += -I./modules/ble INC += -I./modules/board -INC += -I./modules/socket -INC += -I./modules/network INC += -I../../lib/mp-readline INC += -I./drivers/bluetooth INC += -I./drivers/wifi INC += -I./drivers +INC += -I../../extmod INC += -I../../lib/nrfx/ INC += -I../../lib/nrfx/drivers INC += -I../../lib/nrfx/drivers/include @@ -191,6 +190,13 @@ SRC_NRFX_HAL += $(addprefix lib/nrfx/hal/,\ nrf_nvmc.c \ ) +EXTMOD_SRC_C += $(addprefix extmod/,\ + modnetwork.c \ + modusocket.c \ + modnwcc31k.c \ + ) + + SRC_C += \ main.c \ mphalport.c \ @@ -235,16 +241,13 @@ DRIVERS_SRC_C += $(addprefix modules/,\ music/musictunes.c \ ble/modble.c \ random/modrandom.c \ - socket/modusocket.c \ - network/modnetwork.c \ - network/modnwcc31k.c \ ) ifeq ($(MICROPY_PY_CC31K),1) CC3100_DIR=drivers/cc3100 INC += -I$(TOP)/$(CC3100_DIR)/inc CFLAGS_MOD += -DMICROPY_PY_CC31K=1 -SRC_MOD += $(addprefix $(CC3100_DIR)/src/,\ +DRIVERS_SRC_C += $(addprefix $(CC3100_DIR)/src/,\ device.c \ driver.c \ flowcont.c \ @@ -270,7 +273,7 @@ endif OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) @@ -330,7 +333,7 @@ $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(Q)$(SIZE) $@ # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) +SRC_QSTR += $(SRC_C) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) $(EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 24e12d669dd48..d6d1fdeb233cc 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -193,9 +193,12 @@ SRC_LIBM += lib/libm/thumb_vfp_sqrtf.c endif endif +INC += -I$(TOP)/extmod EXTMOD_SRC_C = $(addprefix extmod/,\ modlwip.c \ modonewire.c \ + modnetwork.c \ + modusocket.c \ ) DRIVERS_SRC_C = $(addprefix drivers/,\ @@ -242,8 +245,6 @@ SRC_C = \ modstm.c \ moduos.c \ modutime.c \ - modusocket.c \ - modnetwork.c \ extint.c \ usrsw.c \ rng.c \ diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c deleted file mode 100644 index dea23b40512e1..0000000000000 --- a/ports/stm32/modnetwork.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 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 - -#include "py/objlist.h" -#include "py/runtime.h" -#include "py/mphal.h" -#include "lib/netutils/netutils.h" -#include "modnetwork.h" - -#if MICROPY_PY_NETWORK - -#if MICROPY_PY_LWIP - -#include "lwip/netif.h" -#include "lwip/timeouts.h" -#include "lwip/dns.h" -#include "lwip/dhcp.h" - -u32_t sys_now(void) { - return mp_hal_ticks_ms(); -} - -void pyb_lwip_poll(void) { - // Poll all the NICs for incoming data - for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { - if (netif->flags & NETIF_FLAG_LINK_UP) { - mod_network_nic_type_t *nic = netif->state; - nic->poll_callback(nic, netif); - } - } - // Run the lwIP internal updates - sys_check_timeouts(); -} - -#endif - -/// \module network - network configuration -/// -/// This module provides network drivers and routing configuration. - -void mod_network_init(void) { - mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0); -} - -void mod_network_deinit(void) { -} - -void mod_network_register_nic(mp_obj_t nic) { - for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { - if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) { - // nic already registered - return; - } - } - // nic not registered so add to list - mp_obj_list_append(MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)), nic); -} - -mp_obj_t mod_network_find_nic(const uint8_t *ip) { - // find a NIC that is suited to given IP address - for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { - mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; - // TODO check IP suitability here - //mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); - return nic; - } - - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); -} - -STATIC mp_obj_t network_route(void) { - return MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route); - -STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, - - #if MICROPY_PY_WIZNET5K - { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) }, - #endif - #if MICROPY_PY_CC3K - { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) }, - #endif - - { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); - -const mp_obj_module_t mp_module_network = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_network_globals, -}; - -/*******************************************************************************/ -// Implementations of network methods that can be used by any interface - -#if MICROPY_PY_LWIP - -mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args) { - if (n_args == 0) { - // Get IP addresses - const ip_addr_t *dns = dns_getserver(0); - mp_obj_t tuple[4] = { - netutils_format_ipv4_addr((uint8_t*)&netif->ip_addr, NETUTILS_BIG), - netutils_format_ipv4_addr((uint8_t*)&netif->netmask, NETUTILS_BIG), - netutils_format_ipv4_addr((uint8_t*)&netif->gw, NETUTILS_BIG), - netutils_format_ipv4_addr((uint8_t*)dns, NETUTILS_BIG), - }; - return mp_obj_new_tuple(4, tuple); - } else if (args[0] == MP_OBJ_NEW_QSTR(MP_QSTR_dhcp)) { - // Start the DHCP client - if (dhcp_supplied_address(netif)) { - dhcp_renew(netif); - } else { - dhcp_stop(netif); - dhcp_start(netif); - } - - // Wait for DHCP to get IP address - uint32_t start = mp_hal_ticks_ms(); - while (!dhcp_supplied_address(netif)) { - if (mp_hal_ticks_ms() - start > 10000) { - mp_raise_msg(&mp_type_OSError, "timeout waiting for DHCP to get IP address"); - } - mp_hal_delay_ms(100); - } - - return mp_const_none; - } else { - // Release and stop any existing DHCP - dhcp_release(netif); - dhcp_stop(netif); - // Set static IP addresses - mp_obj_t *items; - mp_obj_get_array_fixed_n(args[0], 4, &items); - netutils_parse_ipv4_addr(items[0], (uint8_t*)&netif->ip_addr, NETUTILS_BIG); - netutils_parse_ipv4_addr(items[1], (uint8_t*)&netif->netmask, NETUTILS_BIG); - netutils_parse_ipv4_addr(items[2], (uint8_t*)&netif->gw, NETUTILS_BIG); - ip_addr_t dns; - netutils_parse_ipv4_addr(items[3], (uint8_t*)&dns, NETUTILS_BIG); - dns_setserver(0, &dns); - return mp_const_none; - } -} - -#endif - -#endif // MICROPY_PY_NETWORK diff --git a/ports/stm32/modnetwork.h b/ports/stm32/modnetwork.h deleted file mode 100644 index f45e00fbc28dc..0000000000000 --- a/ports/stm32/modnetwork.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 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_MODNETWORK_H -#define MICROPY_INCLUDED_STM32_MODNETWORK_H - -#define MOD_NETWORK_IPADDR_BUF_SIZE (4) - -#define MOD_NETWORK_AF_INET (2) -#define MOD_NETWORK_AF_INET6 (10) - -#define MOD_NETWORK_SOCK_STREAM (1) -#define MOD_NETWORK_SOCK_DGRAM (2) -#define MOD_NETWORK_SOCK_RAW (3) - -#if MICROPY_PY_LWIP - -struct netif; - -typedef struct _mod_network_nic_type_t { - mp_obj_base_t base; - void (*poll_callback)(void *data, struct netif *netif); -} mod_network_nic_type_t; - -extern const mp_obj_type_t mod_network_nic_type_wiznet5k; - -mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args); - -#else - -struct _mod_network_socket_obj_t; - -typedef struct _mod_network_nic_type_t { - mp_obj_type_t base; - - // API for non-socket operations - int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out); - - // API for socket operations; return -1 on error - int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno); - void (*close)(struct _mod_network_socket_obj_t *socket); - int (*bind)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); - int (*listen)(struct _mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno); - int (*accept)(struct _mod_network_socket_obj_t *socket, struct _mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno); - int (*connect)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); - mp_uint_t (*send)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno); - mp_uint_t (*recv)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno); - mp_uint_t (*sendto)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); - mp_uint_t (*recvfrom)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); - int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); - int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); - int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); -} mod_network_nic_type_t; - -typedef struct _mod_network_socket_obj_t { - mp_obj_base_t base; - mp_obj_t nic; - mod_network_nic_type_t *nic_type; - union { - struct { - uint8_t domain; - uint8_t type; - int8_t fileno; - } u_param; - mp_uint_t u_state; - }; -} mod_network_socket_obj_t; - -extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; -extern const mod_network_nic_type_t mod_network_nic_type_cc3k; - -#endif - -void mod_network_init(void); -void mod_network_deinit(void); -void mod_network_register_nic(mp_obj_t nic); -mp_obj_t mod_network_find_nic(const uint8_t *ip); - -#endif // MICROPY_INCLUDED_STM32_MODNETWORK_H diff --git a/ports/stm32/modnwcc3k.c b/ports/stm32/modnwcc3k.c index 8723994f45251..0576bca7c644d 100644 --- a/ports/stm32/modnwcc3k.c +++ b/ports/stm32/modnwcc3k.c @@ -112,7 +112,7 @@ STATIC void cc3k_callback(long event_type, char *data, unsigned char length) { } } -STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { +STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { uint32_t ip; // CC3000 gethostbyname is unreliable and usually returns -95 on first call for (int retry = 5; CC3000_EXPORT(gethostbyname)((char*)name, len, &ip) < 0; retry--) { diff --git a/ports/stm32/modnwwiznet5k.c b/ports/stm32/modnwwiznet5k.c index bf4b72ff215c3..3f19bbf8f8c2a 100644 --- a/ports/stm32/modnwwiznet5k.c +++ b/ports/stm32/modnwwiznet5k.c @@ -83,7 +83,7 @@ STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { (void)status; } -STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { +STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8}; uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); DNS_init(0, buf);