diff --git a/docs/zephyr/quickref.rst b/docs/zephyr/quickref.rst
index 783621316c703..57262ffb5c632 100644
--- a/docs/zephyr/quickref.rst
+++ b/docs/zephyr/quickref.rst
@@ -19,7 +19,7 @@ See the corresponding section of the tutorial: :ref:`intro`.
Delay and timing
----------------
-Use the :mod:`time ` module::
+Use the :mod:`time ` module::
import time
@@ -151,7 +151,7 @@ Use the :ref:`zsensor.Sensor ` class to access sensor data::
accel.measure() # obtain a measurement reading from the accelerometer
# each of these prints the value taken by measure()
- accel.float(zsensor.ACCEL_X) # print measurement value for accelerometer X-axis sensor channel as float
- accel.millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths
- accel.micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths
- accel.int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel
+ accel.get_float(zsensor.ACCEL_X) # print measurement value for accelerometer X-axis sensor channel as float
+ accel.get_millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths
+ accel.get_micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths
+ accel.get_int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel
diff --git a/docs/zephyr/tutorial/repl.rst b/docs/zephyr/tutorial/repl.rst
index 8cd57c9435bf4..2c091f7ee94fe 100644
--- a/docs/zephyr/tutorial/repl.rst
+++ b/docs/zephyr/tutorial/repl.rst
@@ -10,7 +10,7 @@ REPL over the serial port
The REPL is available on a UART serial peripheral specified for the board by
the ``zephyr,console`` devicetree node. The baudrate of the REPL is 115200.
-If your board has a USB-serial convertor on it then you should be able to access
+If your board has a USB-serial converter on it then you should be able to access
the REPL directly from your PC.
To access the prompt over USB-serial you will need to use a terminal emulator
diff --git a/drivers/README.md b/drivers/README.md
index 854acc50b62c0..e4fac9fe8d43b 100644
--- a/drivers/README.md
+++ b/drivers/README.md
@@ -1,2 +1,2 @@
-This directory contains drivers for specific hardware. The drivers are
+This directory contains C drivers for specific hardware. The drivers are
intended to work across multiple ports.
diff --git a/drivers/bus/qspi.h b/drivers/bus/qspi.h
index 7dfaaf3d40c63..009f55b159d41 100644
--- a/drivers/bus/qspi.h
+++ b/drivers/bus/qspi.h
@@ -41,10 +41,10 @@ enum {
typedef struct _mp_qspi_proto_t {
int (*ioctl)(void *self, uint32_t cmd);
- void (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
- void (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
- uint32_t (*read_cmd)(void *self, uint8_t cmd, size_t len);
- void (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest);
+ int (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
+ int (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
+ int (*read_cmd)(void *self, uint8_t cmd, size_t len, uint32_t *dest);
+ int (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest);
} mp_qspi_proto_t;
typedef struct _mp_soft_qspi_obj_t {
diff --git a/drivers/bus/softqspi.c b/drivers/bus/softqspi.c
index 71ab559768b1b..dc205da3a7c40 100644
--- a/drivers/bus/softqspi.c
+++ b/drivers/bus/softqspi.c
@@ -158,15 +158,16 @@ STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint
//mp_hal_pin_input(self->io1);
}
-STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
+STATIC int mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint32_t cmd_buf = cmd | data << 8;
CS_LOW(self);
mp_soft_qspi_transfer(self, 1 + len, (uint8_t*)&cmd_buf, NULL);
CS_HIGH(self);
+ return 0;
}
-STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
+STATIC int mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint8_t cmd_buf[5] = {cmd};
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
@@ -174,18 +175,20 @@ STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_
mp_soft_qspi_transfer(self, addr_len + 1, cmd_buf, NULL);
mp_soft_qspi_transfer(self, len, src, NULL);
CS_HIGH(self);
+ return 0;
}
-STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
+STATIC int mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *dest) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint32_t cmd_buf = cmd;
CS_LOW(self);
mp_soft_qspi_transfer(self, 1 + len, (uint8_t*)&cmd_buf, (uint8_t*)&cmd_buf);
CS_HIGH(self);
- return cmd_buf >> 8;
+ *dest = cmd_buf >> 8;
+ return 0;
}
-STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
+STATIC int mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint8_t cmd_buf[7] = {cmd};
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
@@ -194,6 +197,7 @@ STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32
mp_soft_qspi_qwrite(self, addr_len + 3, &cmd_buf[1]); // 3/4 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles)
mp_soft_qspi_qread(self, len, dest);
CS_HIGH(self);
+ return 0;
}
const mp_qspi_proto_t mp_soft_qspi_proto = {
diff --git a/drivers/cc3000/inc/cc3000_common.h b/drivers/cc3000/inc/cc3000_common.h
deleted file mode 100644
index d0c4b1d4b92ea..0000000000000
--- a/drivers/cc3000/inc/cc3000_common.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/*****************************************************************************
-*
-* cc3000_common.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_COMMON_H__
-#define __CC3000_COMMON_H__
-
-#include "data_types.h"
-
-//******************************************************************************
-// Include files
-//******************************************************************************
-#include
-#include
-
-//*****************************************************************************
-// Prefix exported names to avoid name clash
-//*****************************************************************************
-#define CC3000_EXPORT(name) cc3000_ ## name
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int CC3000_EXPORT(errno);
-
-//*****************************************************************************
-// ERROR CODES
-//*****************************************************************************
-#define ESUCCESS 0
-#define EFAIL -1
-#define EERROR EFAIL
-
-//*****************************************************************************
-// COMMON DEFINES
-//*****************************************************************************
-#define ERROR_SOCKET_INACTIVE -57
-
-#define WLAN_ENABLE (1)
-#define WLAN_DISABLE (0)
-
-#define MAC_ADDR_LEN (6)
-
-#define SP_PORTION_SIZE (32)
-
-/*Defines for minimal and maximal RX buffer size. This size includes the spi
- header and hci header.
- The maximal buffer size derives from:
- MTU + HCI header + SPI header + sendto() agrs size
- The minimum buffer size derives from:
- HCI header + SPI header + max args size
-
- This buffer is used for receiving events and data.
- The packet can not be longer than MTU size and CC3000 does not support
- fragmentation. Note that the same buffer is used for reception of the data
- and events from CC3000. That is why the minimum is defined.
- The calculation for the actual size of buffer for reception is:
- Given the maximal data size MAX_DATA that is expected to be received by
- application, the required buffer is:
- Using recv() or recvfrom():
-
- max(CC3000_MINIMAL_RX_SIZE, MAX_DATA + HEADERS_SIZE_DATA + fromlen
- + ucArgsize + 1)
-
- Using gethostbyname() with minimal buffer size will limit the host name
- returned to 99 bytes only.
- The 1 is used for the overrun detection
-
- Buffer size increased to 130 following the add_profile() with WEP security
- which requires TX buffer size of 130 bytes:
- HEADERS_SIZE_EVNT + WLAN_ADD_PROFILE_WEP_PARAM_LEN + MAX SSID LEN + 4 * MAX KEY LEN = 130
- MAX SSID LEN = 32
- MAX SSID LEN = 13 (with add_profile only ascii key setting is supported,
- therfore maximum key size is 13)
-*/
-
-#define CC3000_MINIMAL_RX_SIZE (130 + 1)
-#define CC3000_MAXIMAL_RX_SIZE (1519 + 1)
-
-/*Defines for minimal and maximal TX buffer size.
- This buffer is used for sending events and data.
- The packet can not be longer than MTU size and CC3000 does not support
- fragmentation. Note that the same buffer is used for transmission of the data
- and commands. That is why the minimum is defined.
- The calculation for the actual size of buffer for transmission is:
- Given the maximal data size MAX_DATA, the required buffer is:
- Using Sendto():
-
- max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE
- + SOCKET_SENDTO_PARAMS_LEN + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1)
-
- Using Send():
-
- max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE
- + HCI_CMND_SEND_ARG_LENGTH + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1)
-
- The 1 is used for the overrun detection */
-
-#define CC3000_MINIMAL_TX_SIZE (130 + 1)
-#define CC3000_MAXIMAL_TX_SIZE (1519 + 1)
-
-//TX and RX buffer sizes, allow to receive and transmit maximum data at length 8.
-#ifdef CC3000_TINY_DRIVER
-#define TINY_CC3000_MAXIMAL_RX_SIZE 44
-#define TINY_CC3000_MAXIMAL_TX_SIZE 59
-#endif
-
-/*In order to determine your preferred buffer size,
- change CC3000_MAXIMAL_RX_SIZE and CC3000_MAXIMAL_TX_SIZE to a value between
- the minimal and maximal specified above.
- Note that the buffers are allocated by SPI.
- In case you change the size of those buffers, you might need also to change
- the linker file, since for example on MSP430 FRAM devices the buffers are
- allocated in the FRAM section that is allocated manually and not by IDE.
-*/
-
-#ifndef CC3000_TINY_DRIVER
-
- #define CC3000_RX_BUFFER_SIZE (CC3000_MAXIMAL_RX_SIZE)
- #define CC3000_TX_BUFFER_SIZE (CC3000_MAXIMAL_TX_SIZE)
-
-//if defined TINY DRIVER we use smaller RX and TX buffer in order to minimize RAM consumption
-#else
- #define CC3000_RX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_RX_SIZE)
- #define CC3000_TX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_TX_SIZE)
-
-#endif
-
-//*****************************************************************************
-// Compound Types
-//*****************************************************************************
-typedef INT32 cc3000_time_t;
-typedef UINT32 clock_t;
-typedef INT32 suseconds_t;
-
-typedef struct cc3000_timeval cc3000_timeval;
-
-struct cc3000_timeval
-{
- cc3000_time_t tv_sec; /* seconds */
- suseconds_t tv_usec; /* microseconds */
-};
-
-typedef CHAR *(*tFWPatches)(UINT32 *usLength);
-
-typedef CHAR *(*tDriverPatches)(UINT32 *usLength);
-
-typedef CHAR *(*tBootLoaderPatches)(UINT32 *usLength);
-
-typedef void (*tWlanCB)(INT32 event_type, CHAR * data, UINT8 length );
-
-typedef INT32 (*tWlanReadInteruptPin)(void);
-
-typedef void (*tWlanInterruptEnable)(void);
-
-typedef void (*tWlanInterruptDisable)(void);
-
-typedef void (*tWriteWlanPin)(UINT8 val);
-
-typedef struct
-{
- UINT16 usRxEventOpcode;
- UINT16 usEventOrDataReceived;
- UINT8 *pucReceivedData;
- UINT8 *pucTxCommandBuffer;
-
- tFWPatches sFWPatches;
- tDriverPatches sDriverPatches;
- tBootLoaderPatches sBootLoaderPatches;
- tWlanCB sWlanCB;
- tWlanReadInteruptPin ReadWlanInterruptPin;
- tWlanInterruptEnable WlanInterruptEnable;
- tWlanInterruptDisable WlanInterruptDisable;
- tWriteWlanPin WriteWlanPin;
-
- INT32 slTransmitDataError;
- UINT16 usNumberOfFreeBuffers;
- UINT16 usSlBufferLength;
- UINT16 usBufferSize;
- UINT16 usRxDataPending;
-
- UINT32 NumberOfSentPackets;
- UINT32 NumberOfReleasedPackets;
-
- UINT8 InformHostOnTxComplete;
-}sSimplLinkInformation;
-
-extern volatile sSimplLinkInformation tSLInformation;
-
-
-//*****************************************************************************
-// Prototypes for the APIs.
-//*****************************************************************************
-
-
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitEvent
-//!
-//! @param usOpcode command operation code
-//! @param pRetParams command return parameters
-//!
-//! @return none
-//!
-//! @brief Wait for event, pass it to the hci_event_handler and
-//! update the event opcode in a global variable.
-//
-//*****************************************************************************
-
-extern void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams);
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitData
-//!
-//! @param pBuf data buffer
-//! @param from from information
-//! @param fromlen from information length
-//!
-//! @return none
-//!
-//! @brief Wait for data, pass it to the hci_event_handler
-//! and update in a global variable that there is
-//! data to read.
-//
-//*****************************************************************************
-
-extern void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen);
-
-//*****************************************************************************
-//
-//! UINT32_TO_STREAM_f
-//!
-//! \param p pointer to the new stream
-//! \param u32 pointer to the 32 bit
-//!
-//! \return pointer to the new stream
-//!
-//! \brief This function is used for copying 32 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-extern UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32);
-
-//*****************************************************************************
-//
-//! UINT16_TO_STREAM_f
-//!
-//! \param p pointer to the new stream
-//! \param u32 pointer to the 16 bit
-//!
-//! \return pointer to the new stream
-//!
-//! \brief This function is used for copying 16 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-extern UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16);
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT16_f
-//!
-//! \param p pointer to the stream
-//! \param offset offset in the stream
-//!
-//! \return pointer to the new 16 bit
-//!
-//! \brief This function is used for copying received stream to
-//! 16 bit in little endian format.
-//
-//*****************************************************************************
-
-extern UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset);
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT32_f
-//!
-//! \param p pointer to the stream
-//! \param offset offset in the stream
-//!
-//! \return pointer to the new 32 bit
-//!
-//! \brief This function is used for copying received stream to
-//! 32 bit in little endian format.
-//
-//*****************************************************************************
-
-extern UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset);
-
-
-//*****************************************************************************
-// COMMON MACROs
-//*****************************************************************************
-
-
-//This macro is used for copying 8 bit to stream while converting to little endian format.
-#define UINT8_TO_STREAM(_p, _val) {*(_p)++ = (_val);}
-//This macro is used for copying 16 bit to stream while converting to little endian format.
-#define UINT16_TO_STREAM(_p, _u16) (UINT16_TO_STREAM_f(_p, _u16))
-//This macro is used for copying 32 bit to stream while converting to little endian format.
-#define UINT32_TO_STREAM(_p, _u32) (UINT32_TO_STREAM_f(_p, _u32))
-//This macro is used for copying a specified value length bits (l) to stream while converting to little endian format.
-#define ARRAY_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(p)++ = ((UINT8 *) a)[_i];}
-//This macro is used for copying received stream to 8 bit in little endian format.
-#define STREAM_TO_UINT8(_p, _offset, _u8) {_u8 = (UINT8)(*(_p + _offset));}
-//This macro is used for copying received stream to 16 bit in little endian format.
-#define STREAM_TO_UINT16(_p, _offset, _u16) {_u16 = STREAM_TO_UINT16_f(_p, _offset);}
-//This macro is used for copying received stream to 32 bit in little endian format.
-#define STREAM_TO_UINT32(_p, _offset, _u32) {_u32 = STREAM_TO_UINT32_f(_p, _offset);}
-#define STREAM_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(a)++= ((UINT8 *) p)[_i];}
-
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_COMMON_H__
diff --git a/drivers/cc3000/inc/ccspi.h b/drivers/cc3000/inc/ccspi.h
deleted file mode 100644
index 8fa3ecd10c2fc..0000000000000
--- a/drivers/cc3000/inc/ccspi.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*****************************************************************************
-*
-* spi.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_SPI_H__
-#define __CC3000_SPI_H__
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*gcSpiHandleRx)(void *p);
-typedef void (*gcSpiHandleTx)(void);
-extern unsigned char wlan_tx_buffer[];
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef*
-extern void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq);
-
-extern void SpiOpen(gcSpiHandleRx pfRxHandler);
-extern void SpiClose(void);
-extern void SpiPauseSpi(void);
-extern void SpiResumeSpi(void);
-extern long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength);
-extern void SpiConfigureHwMapping(void);
-extern void SpiCleanGPIOISR(void);
-extern void SSIConfigure(unsigned long ulSSIFreq, unsigned long bForceGpioConfiguration, unsigned long uiReconfigureSysClock);
-extern int init_spi(void);
-extern long ReadWlanInterruptPin(void);
-extern void WriteWlanPin(unsigned char val);
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif
-
diff --git a/drivers/cc3000/inc/data_types.h b/drivers/cc3000/inc/data_types.h
deleted file mode 100644
index 0520a9202fb88..0000000000000
--- a/drivers/cc3000/inc/data_types.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*****************************************************************************
-*
-* data_types.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_DATA_TYPES__
-#define __CC3000_DATA_TYPES__
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifndef NULL
-#define NULL (0)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#ifndef TRUE
-#define TRUE (!FALSE)
-#endif
-
-#ifndef OK
-#define OK (0)
-#endif
-
-#ifndef _INT8
-#define _INT8
-typedef signed char INT8;
-#endif
-
-#ifndef _UINT8
-#define _UINT8
-typedef unsigned char UINT8;
-#endif
-
-#ifndef _INT16
-#define _INT16
-typedef signed short INT16;
-#endif
-
-#ifndef _UINT16
-#define _UINT16
-typedef unsigned short UINT16;
-#endif
-
-#ifndef _BOOLEAN
-#define _BOOLEAN
-typedef unsigned char BOOLEAN;
-#endif
-
-#ifndef _INT32
-#define _INT32
-typedef signed long INT32;
-#endif
-
-#ifndef _UINT32
-#define _UINT32
-typedef unsigned long UINT32;
-#endif
-
-typedef int INT;
-typedef char CHAR;
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __CC3000_DATA_TYPES__ */
diff --git a/drivers/cc3000/inc/evnt_handler.h b/drivers/cc3000/inc/evnt_handler.h
deleted file mode 100644
index d05a442f05fbb..0000000000000
--- a/drivers/cc3000/inc/evnt_handler.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*****************************************************************************
-*
-* evnt_handler.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_EVENT_HANDLER_H__
-#define __CC3000_EVENT_HANDLER_H__
-#include "hci.h"
-#include "socket.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-//*****************************************************************************
-//
-//! hci_event_handler
-//!
-//! @param pRetParams incoming data buffer
-//! @param from from information (in case of data received)
-//! @param fromlen from information length (in case of data received)
-//!
-//! @return none
-//!
-//! @brief Parse the incoming events packets and issues corresponding
-//! event handler from global array of handlers pointers
-//
-//*****************************************************************************
-extern UINT8 *hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen);
-
-//*****************************************************************************
-//
-//! hci_unsol_event_handler
-//!
-//! @param event_hdr event header
-//!
-//! @return 1 if event supported and handled
-//! 0 if event is not supported
-//!
-//! @brief Handle unsolicited events
-//
-//*****************************************************************************
-extern INT32 hci_unsol_event_handler(CHAR *event_hdr);
-
-//*****************************************************************************
-//
-//! hci_unsolicited_event_handler
-//!
-//! @param None
-//!
-//! @return ESUCCESS if successful, EFAIL if an error occurred
-//!
-//! @brief Parse the incoming unsolicited event packets and issues
-//! corresponding event handler.
-//
-//*****************************************************************************
-extern INT32 hci_unsolicited_event_handler(void);
-
-#define M_BSD_RESP_PARAMS_OFFSET(hci_event_hdr)((CHAR *)(hci_event_hdr) + HCI_EVENT_HEADER_SIZE)
-
-#define SOCKET_STATUS_ACTIVE 0
-#define SOCKET_STATUS_INACTIVE 1
-/* Init socket_active_status = 'all ones': init all sockets with SOCKET_STATUS_INACTIVE.
- Will be changed by 'set_socket_active_status' upon 'connect' and 'accept' calls */
-#define SOCKET_STATUS_INIT_VAL 0xFFFF
-#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7))
-#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE))
-
-extern UINT32 socket_active_status;
-
-extern void set_socket_active_status(INT32 Sd, INT32 Status);
-extern INT32 get_socket_active_status(INT32 Sd);
-
-typedef struct _bsd_accept_return_t
-{
- INT32 iSocketDescriptor;
- INT32 iStatus;
- sockaddr tSocketAddress;
-
-} tBsdReturnParams;
-
-
-typedef struct _bsd_read_return_t
-{
- INT32 iSocketDescriptor;
- INT32 iNumberOfBytes;
- UINT32 uiFlags;
-} tBsdReadReturnParams;
-
-#define BSD_RECV_FROM_FROMLEN_OFFSET (4)
-#define BSD_RECV_FROM_FROM_OFFSET (16)
-
-
-typedef struct _bsd_select_return_t
-{
- INT32 iStatus;
- UINT32 uiRdfd;
- UINT32 uiWrfd;
- UINT32 uiExfd;
-} tBsdSelectRecvParams;
-
-
-typedef struct _bsd_getsockopt_return_t
-{
- UINT8 ucOptValue[4];
- CHAR iStatus;
-} tBsdGetSockOptReturnParams;
-
-typedef struct _bsd_gethostbyname_return_t
-{
- INT32 retVal;
- INT32 outputAddress;
-} tBsdGethostbynameParams;
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_EVENT_HANDLER_H__
-
diff --git a/drivers/cc3000/inc/hci.h b/drivers/cc3000/inc/hci.h
deleted file mode 100644
index f12b00e918e1b..0000000000000
--- a/drivers/cc3000/inc/hci.h
+++ /dev/null
@@ -1,330 +0,0 @@
-/*****************************************************************************
-*
-* hci.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_HCI_H__
-#define __CC3000_HCI_H__
-
-#include "cc3000_common.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define SPI_HEADER_SIZE (5)
-#define SIMPLE_LINK_HCI_CMND_HEADER_SIZE (4)
-#define HEADERS_SIZE_CMD (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
-#define SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE (5)
-#define SIMPLE_LINK_HCI_DATA_HEADER_SIZE (5)
-#define SIMPLE_LINK_HCI_PATCH_HEADER_SIZE (2)
-
-
-//*****************************************************************************
-//
-// Values that can be used as HCI Commands and HCI Packet header defines
-//
-//*****************************************************************************
-#define HCI_TYPE_CMND 0x1
-#define HCI_TYPE_DATA 0x2
-#define HCI_TYPE_PATCH 0x3
-#define HCI_TYPE_EVNT 0x4
-
-
-#define HCI_EVENT_PATCHES_DRV_REQ (1)
-#define HCI_EVENT_PATCHES_FW_REQ (2)
-#define HCI_EVENT_PATCHES_BOOTLOAD_REQ (3)
-
-
-#define HCI_CMND_WLAN_BASE (0x0000)
-#define HCI_CMND_WLAN_CONNECT 0x0001
-#define HCI_CMND_WLAN_DISCONNECT 0x0002
-#define HCI_CMND_WLAN_IOCTL_SET_SCANPARAM 0x0003
-#define HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY 0x0004
-#define HCI_CMND_WLAN_IOCTL_ADD_PROFILE 0x0005
-#define HCI_CMND_WLAN_IOCTL_DEL_PROFILE 0x0006
-#define HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS 0x0007
-#define HCI_CMND_EVENT_MASK 0x0008
-#define HCI_CMND_WLAN_IOCTL_STATUSGET 0x0009
-#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START 0x000A
-#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP 0x000B
-#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX 0x000C
-#define HCI_CMND_WLAN_CONFIGURE_PATCH 0x000D
-
-
-#define HCI_CMND_SOCKET_BASE 0x1000
-#define HCI_CMND_SOCKET 0x1001
-#define HCI_CMND_BIND 0x1002
-#define HCI_CMND_RECV 0x1004
-#define HCI_CMND_ACCEPT 0x1005
-#define HCI_CMND_LISTEN 0x1006
-#define HCI_CMND_CONNECT 0x1007
-#define HCI_CMND_BSD_SELECT 0x1008
-#define HCI_CMND_SETSOCKOPT 0x1009
-#define HCI_CMND_GETSOCKOPT 0x100A
-#define HCI_CMND_CLOSE_SOCKET 0x100B
-#define HCI_CMND_RECVFROM 0x100D
-#define HCI_CMND_GETHOSTNAME 0x1010
-#define HCI_CMND_MDNS_ADVERTISE 0x1011
-#define HCI_CMND_GETMSSVALUE 0x1012
-
-
-#define HCI_DATA_BASE 0x80
-
-#define HCI_CMND_SEND (0x01 + HCI_DATA_BASE)
-#define HCI_CMND_SENDTO (0x03 + HCI_DATA_BASE)
-#define HCI_DATA_BSD_RECVFROM (0x04 + HCI_DATA_BASE)
-#define HCI_DATA_BSD_RECV (0x05 + HCI_DATA_BASE)
-
-
-#define HCI_CMND_NVMEM_CBASE (0x0200)
-
-
-#define HCI_CMND_NVMEM_CREATE_ENTRY (0x0203)
-#define HCI_CMND_NVMEM_SWAP_ENTRY (0x0205)
-#define HCI_CMND_NVMEM_READ (0x0201)
-#define HCI_CMND_NVMEM_WRITE (0x0090)
-#define HCI_CMND_NVMEM_WRITE_PATCH (0x0204)
-#define HCI_CMND_READ_SP_VERSION (0x0207)
-
-#define HCI_CMND_READ_BUFFER_SIZE 0x400B
-#define HCI_CMND_SIMPLE_LINK_START 0x4000
-
-#define HCI_CMND_NETAPP_BASE 0x2000
-
-#define HCI_NETAPP_DHCP (0x0001 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_PING_SEND (0x0002 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_PING_REPORT (0x0003 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_PING_STOP (0x0004 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_IPCONFIG (0x0005 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_ARP_FLUSH (0x0006 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_SET_DEBUG_LEVEL (0x0008 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_SET_TIMERS (0x0009 + HCI_CMND_NETAPP_BASE)
-
-
-
-
-
-
-//*****************************************************************************
-//
-// Values that can be used as HCI Events defines
-//
-//*****************************************************************************
-#define HCI_EVNT_WLAN_BASE 0x0000
-#define HCI_EVNT_WLAN_CONNECT 0x0001
-#define HCI_EVNT_WLAN_DISCONNECT \
- 0x0002
-#define HCI_EVNT_WLAN_IOCTL_ADD_PROFILE \
- 0x0005
-
-
-#define HCI_EVNT_SOCKET HCI_CMND_SOCKET
-#define HCI_EVNT_BIND HCI_CMND_BIND
-#define HCI_EVNT_RECV HCI_CMND_RECV
-#define HCI_EVNT_ACCEPT HCI_CMND_ACCEPT
-#define HCI_EVNT_LISTEN HCI_CMND_LISTEN
-#define HCI_EVNT_CONNECT HCI_CMND_CONNECT
-#define HCI_EVNT_SELECT HCI_CMND_BSD_SELECT
-#define HCI_EVNT_CLOSE_SOCKET HCI_CMND_CLOSE_SOCKET
-#define HCI_EVNT_RECVFROM HCI_CMND_RECVFROM
-#define HCI_EVNT_SETSOCKOPT HCI_CMND_SETSOCKOPT
-#define HCI_EVNT_GETSOCKOPT HCI_CMND_GETSOCKOPT
-#define HCI_EVNT_BSD_GETHOSTBYNAME HCI_CMND_GETHOSTNAME
-#define HCI_EVNT_MDNS_ADVERTISE HCI_CMND_MDNS_ADVERTISE
-#define HCI_EVNT_GETMSSVALUE HCI_CMND_GETMSSVALUE
-
-#define HCI_EVNT_SEND 0x1003
-#define HCI_EVNT_WRITE 0x100E
-#define HCI_EVNT_SENDTO 0x100F
-
-#define HCI_EVNT_PATCHES_REQ 0x1000
-
-#define HCI_EVNT_UNSOL_BASE 0x4000
-
-#define HCI_EVNT_WLAN_UNSOL_BASE (0x8000)
-
-#define HCI_EVNT_WLAN_UNSOL_CONNECT (0x0001 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_UNSOL_DISCONNECT (0x0002 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_UNSOL_INIT (0x0004 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_TX_COMPLETE (0x0008 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_UNSOL_DHCP (0x0010 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_ASYNC_PING_REPORT (0x0040 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE (0x0080 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_KEEPALIVE (0x0200 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_BSD_TCP_CLOSE_WAIT (0x0800 + HCI_EVNT_WLAN_UNSOL_BASE)
-
-#define HCI_EVNT_DATA_UNSOL_FREE_BUFF \
- 0x4100
-
-#define HCI_EVNT_NVMEM_CREATE_ENTRY \
- HCI_CMND_NVMEM_CREATE_ENTRY
-#define HCI_EVNT_NVMEM_SWAP_ENTRY HCI_CMND_NVMEM_SWAP_ENTRY
-
-#define HCI_EVNT_NVMEM_READ HCI_CMND_NVMEM_READ
-#define HCI_EVNT_NVMEM_WRITE (0x0202)
-
-#define HCI_EVNT_READ_SP_VERSION \
- HCI_CMND_READ_SP_VERSION
-
-#define HCI_EVNT_INPROGRESS 0xFFFF
-
-
-#define HCI_DATA_RECVFROM 0x84
-#define HCI_DATA_RECV 0x85
-#define HCI_DATA_NVMEM 0x91
-
-#define HCI_EVENT_CC3000_CAN_SHUT_DOWN 0x99
-
-//*****************************************************************************
-//
-// Prototypes for the structures for APIs.
-//
-//*****************************************************************************
-
-#define HCI_DATA_HEADER_SIZE (5)
-#define HCI_EVENT_HEADER_SIZE (5)
-#define HCI_DATA_CMD_HEADER_SIZE (5)
-#define HCI_PATCH_HEADER_SIZE (6)
-
-#define HCI_PACKET_TYPE_OFFSET (0)
-#define HCI_PACKET_ARGSIZE_OFFSET (2)
-#define HCI_PACKET_LENGTH_OFFSET (3)
-
-
-#define HCI_EVENT_OPCODE_OFFSET (1)
-#define HCI_EVENT_LENGTH_OFFSET (3)
-#define HCI_EVENT_STATUS_OFFSET (4)
-#define HCI_DATA_LENGTH_OFFSET (3)
-
-
-
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-//*****************************************************************************
-//
-//! hci_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param ucArgsLength length of the arguments
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI command.
-//
-//*****************************************************************************
-extern UINT16 hci_command_send(UINT16 usOpcode,
- UINT8 *ucArgs,
- UINT8 ucArgsLength);
-
-
-//*****************************************************************************
-//
-//! hci_data_send
-//!
-//! @param usOpcode command operation code
-//! @param ucArgs pointer to the command's arguments buffer
-//! @param usArgsLength length of the arguments
-//! @param ucTail pointer to the data buffer
-//! @param usTailLength buffer length
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI data write operation
-//
-//*****************************************************************************
-extern INT32 hci_data_send(UINT8 ucOpcode,
- UINT8 *ucArgs,
- UINT16 usArgsLength,
- UINT16 usDataLength,
- const UINT8 *ucTail,
- UINT16 usTailLength);
-
-
-//*****************************************************************************
-//
-//! hci_data_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the data buffer
-//! @param ucArgsLength arguments length
-//! @param ucDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepare HCI header and initiate an HCI data write operation
-//
-//*****************************************************************************
-extern void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff,
- UINT8 ucArgsLength, UINT16 ucDataLength);
-
-//*****************************************************************************
-//
-//! hci_patch_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param patch pointer to patch content buffer
-//! @param usDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepare HCI header and initiate an HCI patch write operation
-//
-//*****************************************************************************
-extern void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength);
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_HCI_H__
diff --git a/drivers/cc3000/inc/host_driver_version.h b/drivers/cc3000/inc/host_driver_version.h
deleted file mode 100644
index a28d21f1beaca..0000000000000
--- a/drivers/cc3000/inc/host_driver_version.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*****************************************************************************
-*
-* host_driver_version.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_HOST_DRIVER_VERSION_H__
-#define __CC3000_HOST_DRIVER_VERSION_H__
-
-#define DRIVER_VERSION_NUMBER 15
-
-#endif // __CC3000_HOST_DRIVER_VERSION_H__
diff --git a/drivers/cc3000/inc/inet_ntop.h b/drivers/cc3000/inc/inet_ntop.h
deleted file mode 100644
index fa70806206ac8..0000000000000
--- a/drivers/cc3000/inc/inet_ntop.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __INET_NTOP_H
-#define __INET_NTOP_H
-char *inet_ntop(int af, const void *addr, char *buf, size_t size);
-#endif /* __INET_NTOP_H */
diff --git a/drivers/cc3000/inc/inet_pton.h b/drivers/cc3000/inc/inet_pton.h
deleted file mode 100644
index 0896d5d29fd7b..0000000000000
--- a/drivers/cc3000/inc/inet_pton.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __INET_PTON_H
-#define __INET_PTON_H
-int inet_pton(int, const char *, void *);
-#endif /* __INET_PTON_H */
diff --git a/drivers/cc3000/inc/netapp.h b/drivers/cc3000/inc/netapp.h
deleted file mode 100644
index 1e4f265896561..0000000000000
--- a/drivers/cc3000/inc/netapp.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/*****************************************************************************
-*
-* netapp.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_NETAPP_H__
-#define __CC3000_NETAPP_H__
-
-#include "data_types.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//*****************************************************************************
-//
-//! \addtogroup netapp_api
-//! @{
-//
-//*****************************************************************************
-
-typedef struct _netapp_dhcp_ret_args_t
-{
- UINT8 aucIP[4];
- UINT8 aucSubnetMask[4];
- UINT8 aucDefaultGateway[4];
- UINT8 aucDHCPServer[4];
- UINT8 aucDNSServer[4];
-}tNetappDhcpParams;
-
-typedef struct _netapp_ipconfig_ret_args_t
-{
- UINT8 aucIP[4];
- UINT8 aucSubnetMask[4];
- UINT8 aucDefaultGateway[4];
- UINT8 aucDHCPServer[4];
- UINT8 aucDNSServer[4];
- UINT8 uaMacAddr[6];
- UINT8 uaSSID[32];
-}tNetappIpconfigRetArgs;
-
-
-/*Ping send report parameters*/
-typedef struct _netapp_pingreport_args
-{
- UINT32 packets_sent;
- UINT32 packets_received;
- UINT32 min_round_time;
- UINT32 max_round_time;
- UINT32 avg_round_time;
-} netapp_pingreport_args_t;
-
-
-//*****************************************************************************
-//
-//! netapp_config_mac_adrress
-//!
-//! @param mac device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Configure device MAC address and store it in NVMEM.
-//! The value of the MAC address configured through the API will
-//! be stored in CC3000 non volatile memory, thus preserved
-//! over resets.
-//
-//*****************************************************************************
-extern INT32 netapp_config_mac_adrress( UINT8 *mac );
-
-//*****************************************************************************
-//
-//! netapp_dhcp
-//!
-//! @param aucIP device mac address, 6 bytes. Saved: yes
-//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes
-//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes
-//! @param aucDNSServer device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief netapp_dhcp is used to configure the network interface,
-//! static or dynamic (DHCP).\n In order to activate DHCP mode,
-//! aucIP, aucSubnetMask, aucDefaultGateway must be 0.
-//! The default mode of CC3000 is DHCP mode.
-//! Note that the configuration is saved in non volatile memory
-//! and thus preserved over resets.
-//!
-//! @note If the mode is altered a reset of CC3000 device is required
-//! in order to apply changes.\nAlso note that asynchronous event
-//! of DHCP_EVENT, which is generated when an IP address is
-//! allocated either by the DHCP server or due to static
-//! allocation is generated only upon a connection to the
-//! AP was established.
-//!
-//*****************************************************************************
-extern INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer);
-
-
-
-//*****************************************************************************
-//
-//! netapp_timeout_values
-//!
-//! @param aucDHCP DHCP lease time request, also impact
-//! the DHCP renew timeout. Range: [0-0xffffffff] seconds,
-//! 0 or 0xffffffff == infinity lease timeout.
-//! Resolution:10 seconds. Influence: only after
-//! reconnecting to the AP.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds.
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 14400 seconds.
-//!
-//! @param aucARP ARP refresh timeout, if ARP entry is not updated by
-//! incoming packet, the ARP entry will be deleted by
-//! the end of the timeout.
-//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 3600 seconds.
-//!
-//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout
-//! Range: [0-0xffffffff] seconds, 0 == infinity timeout
-//! Resolution: 10 seconds.
-//! Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 10 seconds.
-//!
-//! @param aucInactivity Socket inactivity timeout, socket timeout is
-//! refreshed by incoming or outgoing packet, by the
-//! end of the socket timeout the socket will be closed
-//! Range: [0-0xffffffff] sec, 0 == infinity timeout.
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 60 seconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Set new timeout values. Function set new timeout values for:
-//! DHCP lease timeout, ARP refresh timeout, keepalive event
-//! timeout and socket inactivity timeout
-//!
-//! @note If a parameter set to non zero value which is less than 10s,
-//! it will be set automatically to 10s.
-//!
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP, UINT32 *aucKeepalive, UINT32 *aucInactivity);
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_send
-//!
-//! @param ip destination IP address
-//! @param pingAttempts number of echo requests to send
-//! @param pingSize send buffer size which may be up to 1400 bytes
-//! @param pingTimeout Time to wait for a response,in milliseconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief send ICMP ECHO_REQUEST to network hosts
-//!
-//! @note If an operation finished successfully asynchronous ping report
-//! event will be generated. The report structure is as defined
-//! by structure netapp_pingreport_args_t.
-//!
-//! @warning Calling this function while a previous Ping Requests are in
-//! progress will stop the previous ping request.
-//*****************************************************************************
-
- #ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout);
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_stop
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief Stop any ping request.
-//!
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_ping_stop();
-#endif
-//*****************************************************************************
-//
-//! netapp_ping_report
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Request for ping status. This API triggers the CC3000 to send
-//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT.
-//! This event will carry the report structure:
-//! netapp_pingreport_args_t. This structure is filled in with ping
-//! results up till point of triggering API.
-//! netapp_pingreport_args_t:\n packets_sent - echo sent,
-//! packets_received - echo reply, min_round_time - minimum
-//! round time, max_round_time - max round time,
-//! avg_round_time - average round time
-//!
-//! @note When a ping operation is not active, the returned structure
-//! fields are 0.
-//!
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern void netapp_ping_report();
-#endif
-
-
-//*****************************************************************************
-//
-//! netapp_ipconfig
-//!
-//! @param[out] ipconfig This argument is a pointer to a
-//! tNetappIpconfigRetArgs structure. This structure is
-//! filled in with the network interface configuration.
-//! tNetappIpconfigRetArgs:\n aucIP - ip address,
-//! aucSubnetMask - mask, aucDefaultGateway - default
-//! gateway address, aucDHCPServer - dhcp server address
-//! aucDNSServer - dns server address, uaMacAddr - mac
-//! address, uaSSID - connected AP ssid
-//!
-//! @return none
-//!
-//! @brief Obtain the CC3000 Network interface information.
-//! Note that the information is available only after the WLAN
-//! connection was established. Calling this function before
-//! associated, will cause non-defined values to be returned.
-//!
-//! @note The function is useful for figuring out the IP Configuration of
-//! the device when DHCP is used and for figuring out the SSID of
-//! the Wireless network the device is associated with.
-//!
-//*****************************************************************************
-
-extern void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig );
-
-
-//*****************************************************************************
-//
-//! netapp_arp_flush
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Flushes ARP table
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_arp_flush();
-#endif
-
-
-//*****************************************************************************
-//
-//! netapp_set_debug_level
-//!
-//! @param[in] level debug level. Bitwise [0-8],
-//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical
-//! message, 1 information message, 2 - core messages, 3 -
-//! HCI messages, 4 - Network stack messages, 5 - wlan
-//! messages, 6 - wlan driver messages, 7 - epprom messages,
-//! 8 - general messages. Default: 0x13f. Saved: no
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Debug messages sent via the UART debug channel, this function
-//! enable/disable the debug level
-//!
-//*****************************************************************************
-
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_set_debug_level(UINT32 ulLevel);
-#endif
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_NETAPP_H__
-
diff --git a/drivers/cc3000/inc/nvmem.h b/drivers/cc3000/inc/nvmem.h
deleted file mode 100644
index b99a2e7b9ec5b..0000000000000
--- a/drivers/cc3000/inc/nvmem.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*****************************************************************************
-*
-* nvmem.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_NVRAM_H__
-#define __CC3000_NVRAM_H__
-
-#include "cc3000_common.h"
-
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-//*****************************************************************************
-//
-//! \addtogroup nvmem_api
-//! @{
-//
-//*****************************************************************************
-
-/****************************************************************************
-**
-** Definitions for File IDs
-**
-****************************************************************************/
-/* NVMEM file ID - system files*/
-#define NVMEM_NVS_FILEID (0)
-#define NVMEM_NVS_SHADOW_FILEID (1)
-#define NVMEM_WLAN_CONFIG_FILEID (2)
-#define NVMEM_WLAN_CONFIG_SHADOW_FILEID (3)
-#define NVMEM_WLAN_DRIVER_SP_FILEID (4)
-#define NVMEM_WLAN_FW_SP_FILEID (5)
-#define NVMEM_MAC_FILEID (6)
-#define NVMEM_FRONTEND_VARS_FILEID (7)
-#define NVMEM_IP_CONFIG_FILEID (8)
-#define NVMEM_IP_CONFIG_SHADOW_FILEID (9)
-#define NVMEM_BOOTLOADER_SP_FILEID (10)
-#define NVMEM_RM_FILEID (11)
-
-/* NVMEM file ID - user files*/
-#define NVMEM_AES128_KEY_FILEID (12)
-#define NVMEM_SHARED_MEM_FILEID (13)
-
-/* max entry in order to invalid nvmem */
-#define NVMEM_MAX_ENTRY (16)
-
-
-//*****************************************************************************
-//
-//! nvmem_read
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID,
-//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID,
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID,
-//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID,
-//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to read
-//! @param ulOffset ulOffset in file from where to read
-//! @param buff output buffer pointer
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads data from the file referred by the ulFileId parameter.
-//! Reads data from file ulOffset till length. Err if the file can't
-//! be used, is invalid, or if the read is out of bounds.
-//!
-//*****************************************************************************
-
-extern INT32 nvmem_read(UINT32 file_id, UINT32 length, UINT32 offset, UINT8 *buff);
-
-//*****************************************************************************
-//
-//! nvmem_write
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to write
-//! @param ulEntryOffset offset in file to start write operation from
-//! @param buff data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write data to nvmem.
-//! writes data to file referred by the ulFileId parameter.
-//! Writes data to file ulOffset till ulLength.The file id will be
-//! marked invalid till the write is done. The file entry doesn't
-//! need to be valid - only allocated.
-//!
-//*****************************************************************************
-
-extern INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff);
-
-
-//*****************************************************************************
-//
-//! nvmem_set_mac_address
-//!
-//! @param mac mac address to be set
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write MAC address to EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-extern UINT8 nvmem_set_mac_address(UINT8 *mac);
-
-
-//*****************************************************************************
-//
-//! nvmem_get_mac_address
-//!
-//! @param[out] mac mac address
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read MAC address from EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-extern UINT8 nvmem_get_mac_address(UINT8 *mac);
-
-
-//*****************************************************************************
-//
-//! nvmem_write_patch
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! @param spLength number of bytes to write
-//! @param spData SP data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief program a patch to a specific file ID.
-//! The SP data is assumed to be organized in 2-dimensional.
-//! Each line is SP_PORTION_SIZE bytes long. Actual programming is
-//! applied in SP_PORTION_SIZE bytes portions.
-//!
-//*****************************************************************************
-extern UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData);
-
-
-//*****************************************************************************
-//
-//! nvmem_read_sp_version
-//!
-//! @param[out] patchVer first number indicates package ID and the second
-//! number indicates package build number
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read patch version. read package version (WiFi FW patch,
-//! driver-supplicant-NS patch, bootloader patch)
-//!
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern UINT8 nvmem_read_sp_version(UINT8* patchVer);
-#endif
-
-//*****************************************************************************
-//
-//! nvmem_create_entry
-//!
-//! @param ulFileId nvmem file Id:\n
-//! * NVMEM_AES128_KEY_FILEID: 12
-//! * NVMEM_SHARED_MEM_FILEID: 13
-//! * and fileIDs 14 and 15
-//! @param ulNewLen entry ulLength
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Create new file entry and allocate space on the NVMEM.
-//! Applies only to user files.
-//! Modify the size of file.
-//! If the entry is unallocated - allocate it to size
-//! ulNewLen (marked invalid).
-//! If it is allocated then deallocate it first.
-//! To just mark the file as invalid without resizing -
-//! set ulNewLen=0.
-//!
-//*****************************************************************************
-extern INT32 nvmem_create_entry(UINT32 file_id, UINT32 newlen);
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_NVRAM_H__
diff --git a/drivers/cc3000/inc/patch_prog.h b/drivers/cc3000/inc/patch_prog.h
deleted file mode 100644
index 0a141a0cb535c..0000000000000
--- a/drivers/cc3000/inc/patch_prog.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __CC3000_PATCH_PROG_H__
-#define __CC3000_PATCH_PROG_H__
-extern unsigned short fw_length;
-extern const unsigned char fw_patch[];
-
-extern unsigned short drv_length;
-extern const unsigned char wlan_drv_patch[];
-extern const unsigned char cRMdefaultParams[128];
-
-void patch_prog_start();
-#endif //__CC3000_PATCH_PROG_H__
diff --git a/drivers/cc3000/inc/security.h b/drivers/cc3000/inc/security.h
deleted file mode 100644
index cd1baf55416f5..0000000000000
--- a/drivers/cc3000/inc/security.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*****************************************************************************
-*
-* security.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_SECURITY__
-#define __CC3000_SECURITY__
-
-#include "nvmem.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define AES128_KEY_SIZE 16
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-
-
-//*****************************************************************************
-//
-//! aes_encrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of plain text and cipher text
-//!
-//! @return none
-//!
-//! @brief AES128 encryption:
-//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes
-//! is computed. The AES implementation is in mode ECB (Electronic
-//! Code Book).
-//!
-//!
-//*****************************************************************************
-extern void aes_encrypt(UINT8 *state, UINT8 *key);
-
-//*****************************************************************************
-//
-//! aes_decrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of cipher text and plain text
-//!
-//! @return none
-//!
-//! @brief AES128 decryption:
-//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes
-//! is computed The AES implementation is in mode ECB
-//! (Electronic Code Book).
-//!
-//!
-//*****************************************************************************
-extern void aes_decrypt(UINT8 *state, UINT8 *key);
-
-
-//*****************************************************************************
-//
-//! aes_read_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads AES128 key from EEPROM
-//! Reads the AES128 key from fileID #12 in EEPROM
-//! returns an error if the key does not exist.
-//!
-//!
-//*****************************************************************************
-extern INT32 aes_read_key(UINT8 *key);
-
-//*****************************************************************************
-//
-//! aes_write_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief writes AES128 key from EEPROM
-//! Writes the AES128 key to fileID #12 in EEPROM
-//!
-//!
-//*****************************************************************************
-extern INT32 aes_write_key(UINT8 *key);
-
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif
diff --git a/drivers/cc3000/inc/socket.h b/drivers/cc3000/inc/socket.h
deleted file mode 100644
index 96c814bf77a08..0000000000000
--- a/drivers/cc3000/inc/socket.h
+++ /dev/null
@@ -1,676 +0,0 @@
-/*****************************************************************************
-*
-* socket.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_SOCKET_H__
-#define __CC3000_SOCKET_H__
-
-#include "cc3000_common.h"
-
-//*****************************************************************************
-//
-//! \addtogroup socket_api
-//! @{
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define HOSTNAME_MAX_LENGTH (230) // 230 bytes + header shouldn't exceed 8 bit value
-
-//--------- Address Families --------
-
-#define AF_INET 2
-#define AF_INET6 23
-
-//------------ Socket Types ------------
-
-#define SOCK_STREAM 1
-#define SOCK_DGRAM 2
-#define SOCK_RAW 3 // Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers
-#define SOCK_RDM 4
-#define SOCK_SEQPACKET 5
-
-//----------- Socket Protocol ----------
-
-#define IPPROTO_IP 0 // dummy for IP
-#define IPPROTO_ICMP 1 // control message protocol
-#define IPPROTO_IPV4 IPPROTO_IP // IP inside IP
-#define IPPROTO_TCP 6 // tcp
-#define IPPROTO_UDP 17 // user datagram protocol
-#define IPPROTO_IPV6 41 // IPv6 in IPv6
-#define IPPROTO_NONE 59 // No next header
-#define IPPROTO_RAW 255 // raw IP packet
-#define IPPROTO_MAX 256
-
-//----------- Socket retunr codes -----------
-
-#define SOC_ERROR (-1) // error
-#define SOC_IN_PROGRESS (-2) // socket in progress
-
-//----------- Socket Options -----------
-#define SOL_SOCKET 0xffff // socket level
-#define SOCKOPT_RECV_NONBLOCK 0 // recv non block mode, set SOCK_ON or SOCK_OFF (default block mode)
-#define SOCKOPT_RECV_TIMEOUT 1 // optname to configure recv and recvfromtimeout
-#define SOCKOPT_ACCEPT_NONBLOCK 2 // accept non block mode, set SOCK_ON or SOCK_OFF (default block mode)
-#define SOCK_ON 0 // socket non-blocking mode is enabled
-#define SOCK_OFF 1 // socket blocking mode is enabled
-
-#define MAX_PACKET_SIZE 1500
-#define MAX_LISTEN_QUEUE 4
-
-#define IOCTL_SOCKET_EVENTMASK
-
-#define ENOBUFS 55 // No buffer space available
-
-#define __FD_SETSIZE 32
-
-#define ASIC_ADDR_LEN 8
-
-#define NO_QUERY_RECIVED -3
-
-
-typedef struct _in_addr_t
-{
- UINT32 s_addr; // load with inet_aton()
-} in_addr;
-
-typedef struct _sockaddr_t
-{
- UINT16 sa_family;
- UINT8 sa_data[14];
-} sockaddr;
-
-typedef struct _sockaddr_in_t
-{
- INT16 sin_family; // e.g. AF_INET
- UINT16 sin_port; // e.g. htons(3490)
- in_addr sin_addr; // see struct in_addr, below
- CHAR sin_zero[8]; // zero this if you want to
-} sockaddr_in;
-
-typedef UINT32 socklen_t;
-
-// The fd_set member is required to be an array of INT32s.
-typedef INT32 __fd_mask;
-
-// It's easier to assume 8-bit bytes than to get CHAR_BIT.
-#define __NFDBITS (8 * sizeof (__fd_mask))
-#define __FDELT(d) ((d) / __NFDBITS)
-#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))
-
-// fd_set for select and pselect.
-typedef struct
-{
- __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
-#define __FDS_BITS(set) ((set)->fds_bits)
-} fd_set;
-
-// We don't use `memset' because this would require a prototype and
-// the array isn't too big.
-#define __FD_ZERO(set) \
- do { \
- UINT16 __i; \
- fd_set *__arr = (set); \
- for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \
- __FDS_BITS (__arr)[__i] = 0; \
- } while (0)
-#define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d))
-#define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d))
-#define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d))
-
-// Access macros for 'fd_set'.
-#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp)
-#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp)
-#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp)
-#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp)
-
-//Use in case of Big Endian only
-
-#define htonl(A) ((((UINT32)(A) & 0xff000000) >> 24) | \
- (((UINT32)(A) & 0x00ff0000) >> 8) | \
- (((UINT32)(A) & 0x0000ff00) << 8) | \
- (((UINT32)(A) & 0x000000ff) << 24))
-
-#define ntohl htonl
-
-//Use in case of Big Endian only
-#define htons(A) ((((UINT32)(A) & 0xff00) >> 8) | \
- (((UINT32)(A) & 0x00ff) << 8))
-
-
-#define ntohs htons
-
-// mDNS port - 5353 mDNS multicast address - 224.0.0.251
-#define SET_mDNS_ADD(sockaddr) sockaddr.sa_data[0] = 0x14; \
- sockaddr.sa_data[1] = 0xe9; \
- sockaddr.sa_data[2] = 0xe0; \
- sockaddr.sa_data[3] = 0x0; \
- sockaddr.sa_data[4] = 0x0; \
- sockaddr.sa_data[5] = 0xfb;
-
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-//*****************************************************************************
-//
-//! socket
-//!
-//! @param domain selects the protocol family which will be used for
-//! communication. On this version only AF_INET is supported
-//! @param type specifies the communication semantics. On this version
-//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
-//! @param protocol specifies a particular protocol to be used with the
-//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are
-//! supported.
-//!
-//! @return On success, socket handle that is used for consequent socket
-//! operations. On error, -1 is returned.
-//!
-//! @brief create an endpoint for communication
-//! The socket function creates a socket that is bound to a specific
-//! transport service provider. This function is called by the
-//! application layer to obtain a socket handle.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol);
-
-//*****************************************************************************
-//
-//! closesocket
-//!
-//! @param sd socket handle.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief The socket function closes a created socket.
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(closesocket)(INT32 sd);
-
-//*****************************************************************************
-//
-//! accept
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr the argument addr is a pointer to a sockaddr structure
-//! This structure is filled in with the address of the
-//! peer socket, as known to the communications layer.
-//! determined. The exact format of the address returned
-//! addr is by the socket's address sockaddr.
-//! On this version only AF_INET is supported.
-//! This argument returns in network order.
-//! @param[out] addrlen the addrlen argument is a value-result argument:
-//! it should initially contain the size of the structure
-//! pointed to by addr.
-//!
-//! @return For socket in blocking mode:
-//! On success, socket handle. on failure negative
-//! For socket in non-blocking mode:
-//! - On connection establishment, socket handle
-//! - On connection pending, SOC_IN_PROGRESS (-2)
-//! - On failure, SOC_ERROR (-1)
-//!
-//! @brief accept a connection on a socket:
-//! This function is used with connection-based socket types
-//! (SOCK_STREAM). It extracts the first connection request on the
-//! queue of pending connections, creates a new connected socket, and
-//! returns a new file descriptor referring to that socket.
-//! The newly created socket is not in the listening state.
-//! The original socket sd is unaffected by this call.
-//! The argument sd is a socket that has been created with socket(),
-//! bound to a local address with bind(), and is listening for
-//! connections after a listen(). The argument addr is a pointer
-//! to a sockaddr structure. This structure is filled in with the
-//! address of the peer socket, as known to the communications layer.
-//! The exact format of the address returned addr is determined by the
-//! socket's address family. The addrlen argument is a value-result
-//! argument: it should initially contain the size of the structure
-//! pointed to by addr, on return it will contain the actual
-//! length (in bytes) of the address returned.
-//!
-//! @sa socket ; bind ; listen
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen);
-
-//*****************************************************************************
-//
-//! bind
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr specifies the destination address. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief assign a name to a socket
-//! This function gives the socket the local address addr.
-//! addr is addrlen bytes long. Traditionally, this is called when a
-//! socket is created with socket, it exists in a name space (address
-//! family) but has no name assigned.
-//! It is necessary to assign a local address before a SOCK_STREAM
-//! socket may receive connections.
-//!
-//! @sa socket ; accept ; listen
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen);
-
-//*****************************************************************************
-//
-//! listen
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] backlog specifies the listen queue depth. On this version
-//! backlog is not supported.
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief listen for connections on a socket
-//! The willingness to accept incoming connections and a queue
-//! limit for incoming connections are specified with listen(),
-//! and then the connections are accepted with accept.
-//! The listen() call applies only to sockets of type SOCK_STREAM
-//! The backlog parameter defines the maximum length the queue of
-//! pending connections may grow to.
-//!
-//! @sa socket ; accept ; bind
-//!
-//! @note On this version, backlog is not supported
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog);
-
-//*****************************************************************************
-//
-//! gethostbyname
-//!
-//! @param[in] hostname host name
-//! @param[in] usNameLen name length
-//! @param[out] out_ip_addr This parameter is filled in with host IP address.
-//! In case that host name is not resolved,
-//! out_ip_addr is zero.
-//! @return On success, positive is returned. On error, negative is returned
-//!
-//! @brief Get host IP by name. Obtain the IP Address of machine on network,
-//! by its name.
-//!
-//! @note On this version, only blocking mode is supported. Also note that
-//! the function requires DNS server to be configured prior to its usage.
-//
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, UINT32* out_ip_addr);
-#endif
-
-
-//*****************************************************************************
-//
-//! connect
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] addr specifies the destination addr. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief initiate a connection on a socket
-//! Function connects the socket referred to by the socket descriptor
-//! sd, to the address specified by addr. The addrlen argument
-//! specifies the size of addr. The format of the address in addr is
-//! determined by the address space of the socket. If it is of type
-//! SOCK_DGRAM, this call specifies the peer with which the socket is
-//! to be associated; this address is that to which datagrams are to be
-//! sent, and the only address from which datagrams are to be received.
-//! If the socket is of type SOCK_STREAM, this call attempts to make a
-//! connection to another socket. The other socket is specified by
-//! address, which is an address in the communications space of the
-//! socket. Note that the function implements only blocking behavior
-//! thus the caller will be waiting either for the connection
-//! establishment or for the connection establishment failure.
-//!
-//! @sa socket
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen);
-
-//*****************************************************************************
-//
-//! select
-//!
-//! @param[in] nfds the highest-numbered file descriptor in any of the
-//! three sets, plus 1.
-//! @param[out] writesds socket descriptors list for write monitoring
-//! @param[out] readsds socket descriptors list for read monitoring
-//! @param[out] exceptsds socket descriptors list for exception monitoring
-//! @param[in] timeout is an upper bound on the amount of time elapsed
-//! before select() returns. Null means infinity
-//! timeout. The minimum timeout is 5 milliseconds,
-//! less than 5 milliseconds will be set
-//! automatically to 5 milliseconds.
-//! @return On success, select() returns the number of file descriptors
-//! contained in the three returned descriptor sets (that is, the
-//! total number of bits that are set in readfds, writefds,
-//! exceptfds) which may be zero if the timeout expires before
-//! anything interesting happens.
-//! On error, -1 is returned.
-//! *readsds - return the sockets on which Read request will
-//! return without delay with valid data.
-//! *writesds - return the sockets on which Write request
-//! will return without delay.
-//! *exceptsds - return the sockets which closed recently.
-//!
-//! @brief Monitor socket activity
-//! Select allow a program to monitor multiple file descriptors,
-//! waiting until one or more of the file descriptors become
-//! "ready" for some class of I/O operation
-//!
-//! @Note If the timeout value set to less than 5ms it will automatically set
-//! to 5ms to prevent overload of the system
-//!
-//! @sa socket
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds,
- fd_set *exceptsds, struct cc3000_timeval *timeout);
-
-//*****************************************************************************
-//
-//! setsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[in] optval specifies a value for the option
-//! @param[in] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa getsockopt
-//
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval,
- socklen_t optlen);
-#endif
-//*****************************************************************************
-//
-//! getsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[out] optval specifies a value for the option
-//! @param[out] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa setsockopt
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(getsockopt)(INT32 sd, INT32 level, INT32 optname, void *optval,
- socklen_t *optlen);
-
-//*****************************************************************************
-//
-//! recv
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief function receives a message from a connection-mode socket
-//!
-//! @sa recvfrom
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags);
-
-//*****************************************************************************
-//
-//! recvfrom
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//! @param[in] from pointer to an address structure indicating the source
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param[in] fromlen source address structure size
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief read data from socket
-//! function receives a message from a connection-mode or
-//! connectionless-mode socket. Note that raw sockets are not
-//! supported.
-//!
-//! @sa recv
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
- socklen_t *fromlen);
-
-//*****************************************************************************
-//
-//! send
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa sendto
-//
-//*****************************************************************************
-
-extern INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags);
-
-//*****************************************************************************
-//
-//! sendto
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//! @param to pointer to an address structure indicating the destination
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param tolen destination address structure size
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa send
-//
-//*****************************************************************************
-
-extern INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags,
- const sockaddr *to, socklen_t tolen);
-
-//*****************************************************************************
-//
-//! mdnsAdvertiser
-//!
-//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature
-//! @param[in] deviceServiceName Service name as part of the published
-//! canonical domain name
-//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars
-//!
-//!
-//! @return On success, zero is returned, return SOC_ERROR if socket was not
-//! opened successfully, or if an error occurred.
-//!
-//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength);
-
-
-//*****************************************************************************
-//
-//! getmssvalue
-//!
-//! @param[in] sd socket descriptor
-//!
-//! @return On success, returns the MSS value of a TCP connection
-//!
-//! @brief Returns the MSS value of a TCP connection according to the socket descriptor
-//
-//*****************************************************************************
-extern UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd);
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __SOCKET_H__
diff --git a/drivers/cc3000/inc/wlan.h b/drivers/cc3000/inc/wlan.h
deleted file mode 100644
index 48d195b32ae80..0000000000000
--- a/drivers/cc3000/inc/wlan.h
+++ /dev/null
@@ -1,518 +0,0 @@
-/*****************************************************************************
-*
-* wlan.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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 __CC3000_WLAN_H__
-#define __CC3000_WLAN_H__
-
-#include "cc3000_common.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WLAN_SEC_UNSEC (0)
-#define WLAN_SEC_WEP (1)
-#define WLAN_SEC_WPA (2)
-#define WLAN_SEC_WPA2 (3)
-//*****************************************************************************
-//
-//! \addtogroup wlan_api
-//! @{
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-//! wlan_init
-//!
-//! @param sWlanCB Asynchronous events callback.
-//! 0 no event call back.
-//! -call back parameters:
-//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event,
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event,
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done,
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report,
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive.
-//! 2) data: pointer to extra data that received by the event
-//! (NULL no data).
-//! 3) length: data length.
-//! -Events with extra data:
-//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask,
-//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes
-//! for DNS server.
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent,
-//! 4 bytes Packets received, 4 bytes Min round time,
-//! 4 bytes Max round time and 4 bytes for Avg round time.
-//!
-//! @param sFWPatches 0 no patch or pointer to FW patches
-//! @param sDriverPatches 0 no patch or pointer to driver patches
-//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches
-//! @param sReadWlanInterruptPin init callback. the callback read wlan
-//! interrupt status.
-//! @param sWlanInterruptEnable init callback. the callback enable wlan
-//! interrupt.
-//! @param sWlanInterruptDisable init callback. the callback disable wlan
-//! interrupt.
-//! @param sWriteWlanPin init callback. the callback write value
-//! to device pin.
-//!
-//! @return none
-//!
-//! @sa wlan_set_event_mask , wlan_start , wlan_stop
-//!
-//! @brief Initialize wlan driver
-//!
-//! @warning This function must be called before ANY other wlan driver function
-//
-//*****************************************************************************
-extern void wlan_init( tWlanCB sWlanCB,
- tFWPatches sFWPatches,
- tDriverPatches sDriverPatches,
- tBootLoaderPatches sBootLoaderPatches,
- tWlanReadInteruptPin sReadWlanInterruptPin,
- tWlanInterruptEnable sWlanInterruptEnable,
- tWlanInterruptDisable sWlanInterruptDisable,
- tWriteWlanPin sWriteWlanPin);
-
-
-
-//*****************************************************************************
-//
-//! wlan_start
-//!
-//! @param usPatchesAvailableAtHost - flag to indicate if patches available
-//! from host or from EEPROM. Due to the
-//! fact the patches are burn to the EEPROM
-//! using the patch programmer utility, the
-//! patches will be available from the EEPROM
-//! and not from the host.
-//!
-//! @return none
-//!
-//! @brief Start WLAN device. This function asserts the enable pin of
-//! the device (WLAN_EN), starting the HW initialization process.
-//! The function blocked until device Initialization is completed.
-//! Function also configure patches (FW, driver or bootloader)
-//! and calls appropriate device callbacks.
-//!
-//! @Note Prior calling the function wlan_init shall be called.
-//! @Warning This function must be called after wlan_init and before any
-//! other wlan API
-//! @sa wlan_init , wlan_stop
-//!
-//
-//*****************************************************************************
-extern int wlan_start(UINT16 usPatchesAvailableAtHost);
-
-//*****************************************************************************
-//
-//! wlan_stop
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Stop WLAN device by putting it into reset state.
-//!
-//! @sa wlan_start
-//
-//*****************************************************************************
-extern void wlan_stop(void);
-
-//*****************************************************************************
-//
-//! wlan_connect
-//!
-//! @param sec_type security options:
-//! WLAN_SEC_UNSEC,
-//! WLAN_SEC_WEP (ASCII support only),
-//! WLAN_SEC_WPA or WLAN_SEC_WPA2
-//! @param ssid up to 32 bytes and is ASCII SSID of the AP
-//! @param ssid_len length of the SSID
-//! @param bssid 6 bytes specified the AP bssid
-//! @param key up to 32 bytes specified the AP security key
-//! @param key_len key length
-//!
-//! @return On success, zero is returned. On error, negative is returned.
-//! Note that even though a zero is returned on success to trigger
-//! connection operation, it does not mean that CCC3000 is already
-//! connected. An asynchronous "Connected" event is generated when
-//! actual association process finishes and CC3000 is connected to
-//! the AP. If DHCP is set, An asynchronous "DHCP" event is
-//! generated when DHCP process is finish.
-//!
-//!
-//! @brief Connect to AP
-//! @warning Please Note that when connection to AP configured with security
-//! type WEP, please confirm that the key is set as ASCII and not
-//! as HEX.
-//! @sa wlan_disconnect
-//
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len,
- UINT8 *bssid, UINT8 *key, INT32 key_len);
-#else
-extern INT32 wlan_connect(CHAR *ssid, INT32 ssid_len);
-
-#endif
-
-//*****************************************************************************
-//
-//! wlan_disconnect
-//!
-//! @return 0 disconnected done, other CC3000 already disconnected
-//!
-//! @brief Disconnect connection from AP.
-//!
-//! @sa wlan_connect
-//
-//*****************************************************************************
-
-extern INT32 wlan_disconnect(void);
-
-//*****************************************************************************
-//
-//! wlan_add_profile
-//!
-//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2
-//! @param ucSsid ssid SSID up to 32 bytes
-//! @param ulSsidLen ssid length
-//! @param ucBssid bssid 6 bytes
-//! @param ulPriority ulPriority profile priority. Lowest priority:0.
-//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security
-//! @param ulGroupCipher_TxKeyIndex key index
-//! @param ulKeyMgmt KEY management
-//! @param ucPf_OrKey security key
-//! @param ulPassPhraseLen security key length for WPA\WPA2
-//!
-//! @return On success, index (1-7) of the stored profile is returned.
-//! On error, -1 is returned.
-//!
-//! @brief When auto start is enabled, the device connects to
-//! station from the profiles table. Up to 7 profiles are supported.
-//! If several profiles configured the device choose the highest
-//! priority profile, within each priority group, device will choose
-//! profile based on security policy, signal strength, etc
-//! parameters. All the profiles are stored in CC3000 NVMEM.
-//!
-//! @sa wlan_ioctl_del_profile
-//
-//*****************************************************************************
-
-extern INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid,
- UINT32 ulSsidLen,
- UINT8 *ucBssid,
- UINT32 ulPriority,
- UINT32 ulPairwiseCipher_Or_Key,
- UINT32 ulGroupCipher_TxKeyLen,
- UINT32 ulKeyMgmt,
- UINT8* ucPf_OrKey,
- UINT32 ulPassPhraseLen);
-
-
-
-//*****************************************************************************
-//
-//! wlan_ioctl_del_profile
-//!
-//! @param index number of profile to delete
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Delete WLAN profile
-//!
-//! @Note In order to delete all stored profile, set index to 255.
-//!
-//! @sa wlan_add_profile
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_del_profile(UINT32 ulIndex);
-
-//*****************************************************************************
-//
-//! wlan_set_event_mask
-//!
-//! @param mask mask option:
-//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done
-//! HCI_EVNT_WLAN_UNSOL_INIT init done
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive
-//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission
-//! Saved: no.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Mask event according to bit mask. In case that event is
-//! masked (1), the device will not send the masked event to host.
-//
-//*****************************************************************************
-extern INT32 wlan_set_event_mask(UINT32 ulMask);
-
-//*****************************************************************************
-//
-//! wlan_ioctl_statusget
-//!
-//! @param none
-//!
-//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING,
-//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED
-//!
-//! @brief get wlan status: disconnected, scanning, connecting or connected
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_statusget(void);
-
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_connection_policy
-//!
-//! @param should_connect_to_open_ap enable(1), disable(0) connect to any
-//! available AP. This parameter corresponds to the configuration of
-//! item # 3 in the brief description.
-//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries
-//! to connect to the last connected AP. This parameter corresponds
-//! to the configuration of item # 1 in the brief description.
-//! @param auto_start enable(1), disable(0) auto connect
-//! after reset and periodically reconnect if needed. This
-//! configuration configures option 2 in the above description.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief When auto is enabled, the device tries to connect according
-//! the following policy:
-//! 1) If fast connect is enabled and last connection is valid,
-//! the device will try to connect to it without the scanning
-//! procedure (fast). The last connection will be marked as
-//! invalid, due to adding/removing profile.
-//! 2) If profile exists, the device will try to connect it
-//! (Up to seven profiles).
-//! 3) If fast and profiles are not found, and open mode is
-//! enabled, the device will try to connect to any AP.
-//! * Note that the policy settings are stored in the CC3000 NVMEM.
-//!
-//! @sa wlan_add_profile , wlan_ioctl_del_profile
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_set_connection_policy(
- UINT32 should_connect_to_open_ap,
- UINT32 should_use_fast_connect,
- UINT32 ulUseProfiles);
-
-//*****************************************************************************
-//
-//! wlan_ioctl_get_scan_results
-//!
-//! @param[in] scan_timeout parameter not supported
-//! @param[out] ucResults scan result (_wlan_full_scan_results_args_t)
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Gets entry from scan result table.
-//! The scan results are returned one by one, and each entry
-//! represents a single AP found in the area. The following is a
-//! format of the scan result:
-//! - 4 Bytes: number of networks found
-//! - 4 Bytes: The status of the scan: 0 - aged results,
-//! 1 - results valid, 2 - no results
-//! - 42 bytes: Result entry, where the bytes are arranged as follows:
-//!
-//! - 1 bit isValid - is result valid or not
-//! - 7 bits rssi - RSSI value;
-//! - 2 bits: securityMode - security mode of the AP:
-//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2
-//! - 6 bits: SSID name length
-//! - 2 bytes: the time at which the entry has entered into
-//! scans result table
-//! - 32 bytes: SSID name
-//! - 6 bytes: BSSID
-//!
-//! @Note scan_timeout, is not supported on this version.
-//!
-//! @sa wlan_ioctl_set_scan_params
-//
-//*****************************************************************************
-
-
-extern INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout,
- UINT8 *ucResults);
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_scan_params
-//!
-//! @param uiEnable - start/stop application scan:
-//! 1 = start scan with default interval value of 10 min.
-//! in order to set a different scan interval value apply the value
-//! in milliseconds. minimum 1 second. 0=stop). Wlan reset
-//! (wlan_stop() wlan_start()) is needed when changing scan interval
-//! value. Saved: No
-//! @param uiMinDwellTime minimum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 20)
-//! @param uiMaxDwellTime maximum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 30)
-//! @param uiNumOfProbeRequests max probe request between dwell time.
-//! Saved: yes. Recommended Value: 5 (Default:2)
-//! @param uiChannelMask bitwise, up to 13 channels (0x1fff).
-//! Saved: yes. Default: 0x7ff
-//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80)
-//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0)
-//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205)
-//! @param aiIntervalList pointer to array with 16 entries (16 channels)
-//! each entry (UINT32) holds timeout between periodic scan
-//! (connection scan) - in milliseconds. Saved: yes. Default 2000ms.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief start and stop scan procedure. Set scan parameters.
-//!
-//! @Note uiDefaultTxPower, is not supported on this version.
-//!
-//! @sa wlan_ioctl_get_scan_results
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32
- uiMinDwellTime,UINT32 uiMaxDwellTime,
- UINT32 uiNumOfProbeRequests,
- UINT32 uiChannelMask,
- INT32 iRSSIThreshold,UINT32 uiSNRThreshold,
- UINT32 uiDefaultTxPower,
- UINT32 *aiIntervalList);
-
-
-//*****************************************************************************
-//
-//! wlan_smart_config_start
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Start to acquire device profile. The device acquire its own
-//! profile, if profile message is found. The acquired AP information
-//! is stored in CC3000 EEPROM only in case AES128 encryption is used.
-//! In case AES128 encryption is not used, a profile is created by
-//! CC3000 internally.
-//!
-//! @Note An asynchronous event - Smart Config Done will be generated as soon
-//! as the process finishes successfully.
-//!
-//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag);
-
-
-//*****************************************************************************
-//
-//! wlan_smart_config_stop
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Stop the acquire profile procedure
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_stop(void);
-
-//*****************************************************************************
-//
-//! wlan_smart_config_set_prefix
-//!
-//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Configure station ssid prefix. The prefix is used internally
-//! in CC3000. It should always be TTT.
-//!
-//! @Note The prefix is stored in CC3000 NVMEM
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_stop
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix);
-
-//*****************************************************************************
-//
-//! wlan_smart_config_process
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief process the acquired data and store it as a profile. The acquired
-//! AP information is stored in CC3000 EEPROM encrypted.
-//! The encrypted data is decrypted and stored as a profile.
-//! behavior is as defined by connection policy.
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_process(void);
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_WLAN_H__
diff --git a/drivers/cc3000/src/cc3000_common.c b/drivers/cc3000/src/cc3000_common.c
deleted file mode 100644
index b4c87848cf476..0000000000000
--- a/drivers/cc3000/src/cc3000_common.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*****************************************************************************
-*
-* cc3000_common.c.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-//*****************************************************************************
-//
-//! \addtogroup common_api
-//! @{
-//
-//*****************************************************************************
-/******************************************************************************
-*
-* Include files
-*
-*****************************************************************************/
-
-#include "cc3000_common.h"
-#include "socket.h"
-#include "wlan.h"
-#include "evnt_handler.h"
-
-//*****************************************************************************
-//
-//! __error__
-//!
-//! @param pcFilename - file name, where error occurred
-//! @param ulLine - line number, where error occurred
-//!
-//! @return none
-//!
-//! @brief stub function for ASSERT macro
-//
-//*****************************************************************************
-void __error__(CHAR *pcFilename, UINT32 ulLine)
-{
- //TODO full up function
-}
-
-
-
-//*****************************************************************************
-//
-//! UINT32_TO_STREAM_f
-//!
-//! @param p pointer to the new stream
-//! @param u32 pointer to the 32 bit
-//!
-//! @return pointer to the new stream
-//!
-//! @brief This function is used for copying 32 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32)
-{
- *(p)++ = (UINT8)(u32);
- *(p)++ = (UINT8)((u32) >> 8);
- *(p)++ = (UINT8)((u32) >> 16);
- *(p)++ = (UINT8)((u32) >> 24);
- return p;
-}
-
-//*****************************************************************************
-//
-//! UINT16_TO_STREAM_f
-//!
-//! @param p pointer to the new stream
-//! @param u32 pointer to the 16 bit
-//!
-//! @return pointer to the new stream
-//!
-//! @brief This function is used for copying 16 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16)
-{
- *(p)++ = (UINT8)(u16);
- *(p)++ = (UINT8)((u16) >> 8);
- return p;
-}
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT16_f
-//!
-//! @param p pointer to the stream
-//! @param offset offset in the stream
-//!
-//! @return pointer to the new 16 bit
-//!
-//! @brief This function is used for copying received stream to
-//! 16 bit in little endian format.
-//
-//*****************************************************************************
-
-UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset)
-{
- return (UINT16)((UINT16)((UINT16)
- (*(p + offset + 1)) << 8) + (UINT16)(*(p + offset)));
-}
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT32_f
-//!
-//! @param p pointer to the stream
-//! @param offset offset in the stream
-//!
-//! @return pointer to the new 32 bit
-//!
-//! @brief This function is used for copying received stream to
-//! 32 bit in little endian format.
-//
-//*****************************************************************************
-
-UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset)
-{
- return (UINT32)((UINT32)((UINT32)
- (*(p + offset + 3)) << 24) + (UINT32)((UINT32)
- (*(p + offset + 2)) << 16) + (UINT32)((UINT32)
- (*(p + offset + 1)) << 8) + (UINT32)(*(p + offset)));
-}
-
-
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/ccspi.c b/drivers/cc3000/src/ccspi.c
deleted file mode 100644
index 1dcd61884086d..0000000000000
--- a/drivers/cc3000/src/ccspi.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*****************************************************************************
- *
- * spi.c - CC3000 Host Driver Implementation.
- * Copyright (C) 2011 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.
- *
- *****************************************************************************/
-
-#include
-
-#include "py/runtime.h"
-#include "pin.h"
-#include "led.h"
-#include "extint.h"
-#include "spi.h"
-#include "ccspi.h"
-#include "evnt_handler.h"
-
-#if 0 // print debugging info
-#include
-#define DEBUG_printf(args...) printf(args)
-#else // don't print debugging info
-#define DEBUG_printf(args...) (void)0
-#endif
-
-// these need to be set to valid values before anything in this file will work
-STATIC const spi_t *SPI_HANDLE = NULL;
-STATIC const pin_obj_t *PIN_CS = NULL;
-STATIC const pin_obj_t *PIN_EN = NULL;
-STATIC const pin_obj_t *PIN_IRQ = NULL;
-
-#define CS_LOW() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_RESET)
-#define CS_HIGH() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET)
-
-#define READ 3
-#define WRITE 1
-
-#define HI(value) (((value) & 0xFF00) >> 8)
-#define LO(value) ((value) & 0x00FF)
-
-#define SPI_TIMEOUT (1000)
-#define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5)
-
-/* SPI bus states */
-#define eSPI_STATE_POWERUP (0)
-#define eSPI_STATE_INITIALIZED (1)
-#define eSPI_STATE_IDLE (2)
-#define eSPI_STATE_WRITE_IRQ (3)
-#define eSPI_STATE_WRITE_FIRST_PORTION (4)
-#define eSPI_STATE_WRITE_EOT (5)
-#define eSPI_STATE_READ_IRQ (6)
-#define eSPI_STATE_READ_FIRST_PORTION (7)
-#define eSPI_STATE_READ_EOT (8)
-
-// The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
-// for the purpose of detection of the overrun. The location of the memory where the magic number
-// resides shall never be written. In case it is written - the overrun occured and either recevie function
-// or send function will stuck forever.
-#define CC3000_BUFFER_MAGIC_NUMBER (0xDE)
-
-typedef struct {
- gcSpiHandleRx SPIRxHandler;
- unsigned short usTxPacketLength;
- unsigned short usRxPacketLength;
- unsigned long ulSpiState;
- unsigned char *pTxPacket;
- unsigned char *pRxPacket;
-} tSpiInformation;
-STATIC tSpiInformation sSpiInformation;
-
-STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE];
-unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE];
-
-STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj;
-
-// set the pins to use to communicate with the CC3000
-// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef*
-void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) {
- SPI_HANDLE = spi;
- PIN_CS = pin_cs;
- PIN_EN = pin_en;
- PIN_IRQ = pin_irq;
-}
-
-void SpiClose(void)
-{
- if (sSpiInformation.pRxPacket) {
- sSpiInformation.pRxPacket = 0;
- }
-
- tSLInformation.WlanInterruptDisable();
-
- //HAL_SPI_DeInit(SPI_HANDLE);
-}
-
-void SpiOpen(gcSpiHandleRx pfRxHandler)
-{
- DEBUG_printf("SpiOpen\n");
-
- /* initialize SPI state */
- sSpiInformation.ulSpiState = eSPI_STATE_POWERUP;
- sSpiInformation.SPIRxHandler = pfRxHandler;
- sSpiInformation.usTxPacketLength = 0;
- sSpiInformation.pTxPacket = NULL;
- sSpiInformation.pRxPacket = (unsigned char *)spi_buffer;
- sSpiInformation.usRxPacketLength = 0;
- spi_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
- wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
-
- /* SPI configuration */
- SPI_InitTypeDef *init = &SPI_HANDLE->spi->Init;
- init->Mode = SPI_MODE_MASTER;
- init->Direction = SPI_DIRECTION_2LINES;
- init->DataSize = SPI_DATASIZE_8BIT;
- init->CLKPolarity = SPI_POLARITY_LOW;
- init->CLKPhase = SPI_PHASE_2EDGE;
- init->NSS = SPI_NSS_SOFT;
- init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
- init->FirstBit = SPI_FIRSTBIT_MSB;
- init->TIMode = SPI_TIMODE_DISABLED;
- init->CRCCalculation = SPI_CRCCALCULATION_DISABLED;
- init->CRCPolynomial = 7;
- spi_init(SPI_HANDLE, false);
-
- // configure wlan CS and EN pins
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Pull = GPIO_NOPULL;
- GPIO_InitStructure.Alternate = 0;
-
- GPIO_InitStructure.Pin = PIN_CS->pin_mask;
- HAL_GPIO_Init(PIN_CS->gpio, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pin = PIN_EN->pin_mask;
- HAL_GPIO_Init(PIN_EN->gpio, &GPIO_InitStructure);
-
- HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET);
- HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, GPIO_PIN_RESET);
-
- /* do a dummy read, this ensures SCLK is low before
- actual communications start, it might be required */
- CS_LOW();
- uint8_t buf[1];
- HAL_SPI_Receive(SPI_HANDLE->spi, buf, sizeof(buf), SPI_TIMEOUT);
- CS_HIGH();
-
- // register EXTI
- extint_register((mp_obj_t)PIN_IRQ, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t)&irq_callback_obj, true);
- extint_enable(PIN_IRQ->pin);
-
- DEBUG_printf("SpiOpen finished; IRQ.pin=%d IRQ_LINE=%d\n", PIN_IRQ->pin, PIN_IRQ->pin);
-}
-
-long ReadWlanInterruptPin(void)
-{
- return HAL_GPIO_ReadPin(PIN_IRQ->gpio, PIN_IRQ->pin_mask);
-}
-
-void WriteWlanPin(unsigned char val)
-{
- HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask,
- (WLAN_ENABLE)? GPIO_PIN_SET:GPIO_PIN_RESET);
-}
-
-STATIC void SpiWriteDataSynchronous(unsigned char *data, unsigned short size)
-{
- DEBUG_printf("SpiWriteDataSynchronous(data=%p [%x %x %x %x], size=%u)\n", data, data[0], data[1], data[2], data[3], size);
- __disable_irq();
- if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) {
- //BREAK();
- }
- __enable_irq();
- DEBUG_printf(" - rx data = [%x %x %x %x]\n", data[0], data[1], data[2], data[3]);
-}
-
-STATIC void SpiReadDataSynchronous(unsigned char *data, unsigned short size)
-{
- memset(data, READ, size);
- __disable_irq();
- if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) {
- //BREAK();
- }
- __enable_irq();
-}
-
-STATIC void __delay_cycles(volatile int x)
-{
- x *= 6; // for 168 MHz CPU
- while (x--);
-}
-
-STATIC long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength)
-{
- DEBUG_printf("SpiFirstWrite %lu\n", sSpiInformation.ulSpiState);
-
- CS_LOW();
-
- // Assuming we are running on 24 MHz ~50 micro delay is 1200 cycles;
- __delay_cycles(1200);
-
- // SPI writes first 4 bytes of data
- SpiWriteDataSynchronous(ucBuf, 4);
-
- __delay_cycles(1200);
-
- SpiWriteDataSynchronous(ucBuf + 4, usLength - 4);
-
- // From this point on - operate in a regular way
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
-
- CS_HIGH();
-
- return(0);
-}
-
-long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength)
-{
- DEBUG_printf("SpiWrite %lu\n", sSpiInformation.ulSpiState);
-
- unsigned char ucPad = 0;
-
- // Figure out the total length of the packet in order to figure out if there
- // is padding or not
- if(!(usLength & 0x0001)) {
- ucPad++;
- }
-
- pUserBuffer[0] = WRITE;
- pUserBuffer[1] = HI(usLength + ucPad);
- pUserBuffer[2] = LO(usLength + ucPad);
- pUserBuffer[3] = 0;
- pUserBuffer[4] = 0;
-
- usLength += (SPI_HEADER_SIZE + ucPad);
-
- // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
- // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun
- // occurred - and we will stuck here forever!
- if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
- while (1);
- }
-
- if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) {
- while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED);
- }
-
- if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) {
- // This is time for first TX/RX transactions over SPI:
- // the IRQ is down - so need to send read buffer size command
- SpiFirstWrite(pUserBuffer, usLength);
- } else {
- //
- // We need to prevent here race that can occur in case 2 back to back packets are sent to the
- // device, so the state will move to IDLE and once again to not IDLE due to IRQ
- //
- tSLInformation.WlanInterruptDisable();
-
- while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE);
-
- sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ;
- sSpiInformation.pTxPacket = pUserBuffer;
- sSpiInformation.usTxPacketLength = usLength;
-
- // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation
- CS_LOW();
-
- // Re-enable IRQ - if it was not disabled - this is not a problem...
- tSLInformation.WlanInterruptEnable();
-
- // check for a missing interrupt between the CS assertion and enabling back the interrupts
- if (tSLInformation.ReadWlanInterruptPin() == 0) {
- SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength);
-
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
-
- CS_HIGH();
- }
- }
-
- // Due to the fact that we are currently implementing a blocking situation
- // here we will wait till end of transaction
- while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState);
-
- return(0);
-}
-
-#if 0
-unused
-STATIC void SpiReadPacket(void)
-{
- int length;
-
- /* read SPI header */
- SpiReadDataSynchronous(sSpiInformation.pRxPacket, SPI_HEADER_SIZE);
-
- /* parse data length */
- STREAM_TO_UINT8(sSpiInformation.pRxPacket, SPI_HEADER_SIZE-1, length);
-
- /* read the remainder of the packet */
- SpiReadDataSynchronous(sSpiInformation.pRxPacket + SPI_HEADER_SIZE, length);
-
- sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
-}
-#endif
-
-STATIC void SpiReadHeader(void)
-{
- SpiReadDataSynchronous(sSpiInformation.pRxPacket, 10);
-}
-
-STATIC void SpiTriggerRxProcessing(void)
-{
- SpiPauseSpi();
- CS_HIGH();
-
- // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
- // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun
- // occurred - and we will stuck here forever!
- if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
- while (1);
- }
-
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
- sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE);
-}
-
-
-STATIC long SpiReadDataCont(void)
-{
- long data_to_recv=0;
- unsigned char *evnt_buff, type;
-
- //determine what type of packet we have
- evnt_buff = sSpiInformation.pRxPacket;
- STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type);
-
- switch (type) {
- case HCI_TYPE_DATA:{
- // We need to read the rest of data..
- STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE),
- HCI_DATA_LENGTH_OFFSET, data_to_recv);
- if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) {
- data_to_recv++;
- }
-
- if (data_to_recv) {
- SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
- }
- break;
- }
- case HCI_TYPE_EVNT: {
- // Calculate the rest length of the data
- STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE),
- HCI_EVENT_LENGTH_OFFSET, data_to_recv);
- data_to_recv -= 1;
-
- // Add padding byte if needed
- if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) {
- data_to_recv++;
- }
-
- if (data_to_recv) {
- SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
- }
-
- sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
- break;
- }
- }
-
- return 0;
-}
-
-STATIC void SSIContReadOperation(void)
-{
- // The header was read - continue with the payload read
- if (!SpiReadDataCont()) {
- /* All the data was read - finalize handling by switching
- to the task and calling from task Event Handler */
- SpiTriggerRxProcessing();
- }
-}
-
-STATIC mp_obj_t irq_callback(mp_obj_t line) {
- DEBUG_printf("<< IRQ; state=%lu >>\n", sSpiInformation.ulSpiState);
- switch (sSpiInformation.ulSpiState) {
- case eSPI_STATE_POWERUP:
- /* This means IRQ line was low call a callback of HCI Layer to inform on event */
- DEBUG_printf(" - POWERUP\n");
- sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED;
- break;
- case eSPI_STATE_IDLE:
- DEBUG_printf(" - IDLE\n");
- sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ;
-
- /* IRQ line goes down - we are start reception */
- CS_LOW();
-
- // Wait for TX/RX Compete which will come as DMA interrupt
- SpiReadHeader();
-
- sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
-
- SSIContReadOperation();
- break;
- case eSPI_STATE_WRITE_IRQ:
- DEBUG_printf(" - WRITE IRQ\n");
- SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength);
-
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
-
- CS_HIGH();
- break;
- }
- return mp_const_none;
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback);
-
-void SpiPauseSpi(void) {
- DEBUG_printf("SpiPauseSpi\n");
- extint_disable(PIN_IRQ->pin);
-}
-
-void SpiResumeSpi(void) {
- DEBUG_printf("SpiResumeSpi\n");
- extint_enable(PIN_IRQ->pin);
-}
diff --git a/drivers/cc3000/src/evnt_handler.c b/drivers/cc3000/src/evnt_handler.c
deleted file mode 100644
index 80f34e469b244..0000000000000
--- a/drivers/cc3000/src/evnt_handler.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*****************************************************************************
-*
-* evnt_handler.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-//*****************************************************************************
-//
-//! \addtogroup evnt_handler_api
-//! @{
-//
-//******************************************************************************
-
-//******************************************************************************
-// INCLUDE FILES
-//******************************************************************************
-
-#include "cc3000_common.h"
-#include "string.h"
-#include "hci.h"
-#include "evnt_handler.h"
-#include "wlan.h"
-#include "socket.h"
-#include "netapp.h"
-#include "ccspi.h"
-
-
-
-//*****************************************************************************
-// COMMON DEFINES
-//*****************************************************************************
-
-#define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0)
-#define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1)
-#define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2)
-#define FLOW_CONTROL_EVENT_SIZE (4)
-
-#define BSD_RSP_PARAMS_SOCKET_OFFSET (0)
-#define BSD_RSP_PARAMS_STATUS_OFFSET (4)
-
-#define GET_HOST_BY_NAME_RETVAL_OFFSET (0)
-#define GET_HOST_BY_NAME_ADDR_OFFSET (4)
-
-#define ACCEPT_SD_OFFSET (0)
-#define ACCEPT_RETURN_STATUS_OFFSET (4)
-#define ACCEPT_ADDRESS__OFFSET (8)
-
-#define SL_RECEIVE_SD_OFFSET (0)
-#define SL_RECEIVE_NUM_BYTES_OFFSET (4)
-#define SL_RECEIVE__FLAGS__OFFSET (8)
-
-
-#define SELECT_STATUS_OFFSET (0)
-#define SELECT_READFD_OFFSET (4)
-#define SELECT_WRITEFD_OFFSET (8)
-#define SELECT_EXFD_OFFSET (12)
-
-
-#define NETAPP_IPCONFIG_IP_OFFSET (0)
-#define NETAPP_IPCONFIG_SUBNET_OFFSET (4)
-#define NETAPP_IPCONFIG_GW_OFFSET (8)
-#define NETAPP_IPCONFIG_DHCP_OFFSET (12)
-#define NETAPP_IPCONFIG_DNS_OFFSET (16)
-#define NETAPP_IPCONFIG_MAC_OFFSET (20)
-#define NETAPP_IPCONFIG_SSID_OFFSET (26)
-
-#define NETAPP_IPCONFIG_IP_LENGTH (4)
-#define NETAPP_IPCONFIG_MAC_LENGTH (6)
-#define NETAPP_IPCONFIG_SSID_LENGTH (32)
-
-
-#define NETAPP_PING_PACKETS_SENT_OFFSET (0)
-#define NETAPP_PING_PACKETS_RCVD_OFFSET (4)
-#define NETAPP_PING_MIN_RTT_OFFSET (8)
-#define NETAPP_PING_MAX_RTT_OFFSET (12)
-#define NETAPP_PING_AVG_RTT_OFFSET (16)
-
-#define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0)
-#define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4)
-#define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8)
-#define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10)
-#define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38)
-
-#define GET_MSS_VAL_RETVAL_OFFSET (0)
-
-//*****************************************************************************
-// GLOBAL VARAIABLES
-//*****************************************************************************
-
-UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL;
-
-
-//*****************************************************************************
-// Prototypes for the static functions
-//*****************************************************************************
-
-static INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent);
-
-static void update_socket_active_status(CHAR *resp_params);
-
-
-//*****************************************************************************
-//
-//! hci_unsol_handle_patch_request
-//!
-//! @param event_hdr event header
-//!
-//! @return none
-//!
-//! @brief Handle unsolicited event from type patch request
-//
-//*****************************************************************************
-void hci_unsol_handle_patch_request(CHAR *event_hdr)
-{
- CHAR *params = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE;
- UINT32 ucLength = 0;
- CHAR *patch;
-
- switch (*params)
- {
- case HCI_EVENT_PATCHES_DRV_REQ:
-
- if (tSLInformation.sDriverPatches)
- {
- patch = tSLInformation.sDriverPatches(&ucLength);
-
- if (patch)
- {
- hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ,
- tSLInformation.pucTxCommandBuffer, patch, ucLength);
- return;
- }
- }
-
- // Send 0 length Patches response event
- hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ,
- tSLInformation.pucTxCommandBuffer, 0, 0);
- break;
-
- case HCI_EVENT_PATCHES_FW_REQ:
-
- if (tSLInformation.sFWPatches)
- {
- patch = tSLInformation.sFWPatches(&ucLength);
-
- // Build and send a patch
- if (patch)
- {
- hci_patch_send(HCI_EVENT_PATCHES_FW_REQ,
- tSLInformation.pucTxCommandBuffer, patch, ucLength);
- return;
- }
- }
-
- // Send 0 length Patches response event
- hci_patch_send(HCI_EVENT_PATCHES_FW_REQ,
- tSLInformation.pucTxCommandBuffer, 0, 0);
- break;
-
- case HCI_EVENT_PATCHES_BOOTLOAD_REQ:
-
- if (tSLInformation.sBootLoaderPatches)
- {
- patch = tSLInformation.sBootLoaderPatches(&ucLength);
-
- if (patch)
- {
- hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ,
- tSLInformation.pucTxCommandBuffer, patch, ucLength);
- return;
- }
- }
-
- // Send 0 length Patches response event
- hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ,
- tSLInformation.pucTxCommandBuffer, 0, 0);
- break;
- }
-}
-
-
-
-//*****************************************************************************
-//
-//! hci_event_handler
-//!
-//! @param pRetParams incoming data buffer
-//! @param from from information (in case of data received)
-//! @param fromlen from information length (in case of data received)
-//!
-//! @return none
-//!
-//! @brief Parse the incoming events packets and issues corresponding
-//! event handler from global array of handlers pointers
-//
-//*****************************************************************************
-
-
-UINT8 * hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen)
-{
- UINT8 *pucReceivedData, ucArgsize;
- UINT16 usLength;
- UINT8 *pucReceivedParams;
- UINT16 usReceivedEventOpcode = 0;
- UINT32 retValue32;
- UINT8 * RecvParams;
- UINT8 *RetParams;
-
-
- while (1)
- {
- if (tSLInformation.usEventOrDataReceived != 0)
- {
- pucReceivedData = (tSLInformation.pucReceivedData);
-
- if (*pucReceivedData == HCI_TYPE_EVNT)
- {
- // Event Received
- STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET,
- usReceivedEventOpcode);
- pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE;
- RecvParams = pucReceivedParams;
- RetParams = pRetParams;
-
- // In case unsolicited event received - here the handling finished
- if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 0)
- {
- STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength);
-
- switch(usReceivedEventOpcode)
- {
- case HCI_CMND_READ_BUFFER_SIZE:
- {
- STREAM_TO_UINT8((CHAR *)pucReceivedParams, 0,
- tSLInformation.usNumberOfFreeBuffers);
- STREAM_TO_UINT16((CHAR *)pucReceivedParams, 1,
- tSLInformation.usSlBufferLength);
- }
- break;
-
- case HCI_CMND_WLAN_CONFIGURE_PATCH:
- case HCI_NETAPP_DHCP:
- case HCI_NETAPP_PING_SEND:
- case HCI_NETAPP_PING_STOP:
- case HCI_NETAPP_ARP_FLUSH:
- case HCI_NETAPP_SET_DEBUG_LEVEL:
- case HCI_NETAPP_SET_TIMERS:
- case HCI_EVNT_NVMEM_READ:
- case HCI_EVNT_NVMEM_CREATE_ENTRY:
- case HCI_CMND_NVMEM_WRITE_PATCH:
- case HCI_NETAPP_PING_REPORT:
- case HCI_EVNT_MDNS_ADVERTISE:
-
- STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET
- ,*(UINT8 *)pRetParams);
- break;
-
- case HCI_CMND_SETSOCKOPT:
- case HCI_CMND_WLAN_CONNECT:
- case HCI_CMND_WLAN_IOCTL_STATUSGET:
- case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE:
- case HCI_CMND_WLAN_IOCTL_DEL_PROFILE:
- case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY:
- case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM:
- case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START:
- case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP:
- case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX:
- case HCI_CMND_EVENT_MASK:
- case HCI_EVNT_WLAN_DISCONNECT:
- case HCI_EVNT_SOCKET:
- case HCI_EVNT_BIND:
- case HCI_CMND_LISTEN:
- case HCI_EVNT_CLOSE_SOCKET:
- case HCI_EVNT_CONNECT:
- case HCI_EVNT_NVMEM_WRITE:
-
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,0
- ,*(UINT32 *)pRetParams);
- break;
-
- case HCI_EVNT_READ_SP_VERSION:
-
- STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET
- ,*(UINT8 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 1;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams, 0, retValue32);
- UINT32_TO_STREAM((UINT8 *)pRetParams, retValue32);
- break;
-
- case HCI_EVNT_BSD_GETHOSTBYNAME:
-
- STREAM_TO_UINT32((CHAR *)pucReceivedParams
- ,GET_HOST_BY_NAME_RETVAL_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams
- ,GET_HOST_BY_NAME_ADDR_OFFSET,*(UINT32 *)pRetParams);
- break;
-
- case HCI_EVNT_GETMSSVALUE:
-
- STREAM_TO_UINT16((CHAR *)pucReceivedParams
- ,GET_MSS_VAL_RETVAL_OFFSET,*(UINT16 *)pRetParams);
-
- break;
-
- case HCI_EVNT_ACCEPT:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,ACCEPT_SD_OFFSET
- ,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams
- ,ACCEPT_RETURN_STATUS_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
-
- //This argument returns in network order
- memcpy((UINT8 *)pRetParams,
- pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr));
- break;
- }
-
- case HCI_EVNT_RECV:
- case HCI_EVNT_RECVFROM:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(UINT32 *)pRetParams);
-
- if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE)
- {
- set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE);
- }
- break;
- }
-
- case HCI_EVNT_SEND:
- case HCI_EVNT_SENDTO:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
-
- break;
- }
-
- case HCI_EVNT_SELECT:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_STATUS_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_READFD_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_EXFD_OFFSET,*(UINT32 *)pRetParams);
- break;
- }
-
- case HCI_CMND_GETSOCKOPT:
-
- STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus);
- //This argument returns in network order
- memcpy((UINT8 *)pRetParams, pucReceivedParams, 4);
- break;
-
- case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS:
-
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 2;
- STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 2;
- memcpy((UINT8 *)pRetParams, (CHAR *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH);
- break;
-
- case HCI_CMND_SIMPLE_LINK_START:
- break;
-
- case HCI_NETAPP_IPCONFIG:
-
- //Read IP address
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read subnet
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read default GW
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read DHCP server
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read DNS server
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read Mac address
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH);
- RecvParams += 6;
-
- //Read SSID
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH);
-
- }
- }
-
- if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode)
- {
- tSLInformation.usRxEventOpcode = 0;
- }
- }
- else
- {
- pucReceivedParams = pucReceivedData;
- STREAM_TO_UINT8((CHAR *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize);
-
- STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength);
-
- // Data received: note that the only case where from and from length
- // are not null is in recv from, so fill the args accordingly
- if (from)
- {
- STREAM_TO_UINT32((CHAR *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(UINT32 *)fromlen);
- memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen);
- }
-
- memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize,
- usLength - ucArgsize);
-
- tSLInformation.usRxDataPending = 0;
- }
-
- tSLInformation.usEventOrDataReceived = 0;
-
- SpiResumeSpi();
-
- // Since we are going to TX - we need to handle this event after the
- // ResumeSPi since we need interrupts
- if ((*pucReceivedData == HCI_TYPE_EVNT) &&
- (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ))
- {
- hci_unsol_handle_patch_request((CHAR *)pucReceivedData);
- }
-
- if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0))
- {
- return NULL;
- }
- }
- }
-
-}
-
-//*****************************************************************************
-//
-//! hci_unsol_event_handler
-//!
-//! @param event_hdr event header
-//!
-//! @return 1 if event supported and handled
-//! 0 if event is not supported
-//!
-//! @brief Handle unsolicited events
-//
-//*****************************************************************************
-INT32 hci_unsol_event_handler(CHAR *event_hdr)
-{
- CHAR * data = NULL;
- INT32 event_type;
- UINT32 NumberOfReleasedPackets;
- UINT32 NumberOfSentPackets;
-
- STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type);
-
- if (event_type & HCI_EVNT_UNSOL_BASE)
- {
- switch(event_type)
- {
-
- case HCI_EVNT_DATA_UNSOL_FREE_BUFF:
- {
- hci_event_unsol_flowcontrol_handler(event_hdr);
-
- NumberOfReleasedPackets = tSLInformation.NumberOfReleasedPackets;
- NumberOfSentPackets = tSLInformation.NumberOfSentPackets;
-
- if (NumberOfReleasedPackets == NumberOfSentPackets)
- {
- if (tSLInformation.InformHostOnTxComplete)
- {
- tSLInformation.sWlanCB(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0);
- }
- }
- return 1;
-
- }
- }
- }
-
- if(event_type & HCI_EVNT_WLAN_UNSOL_BASE)
- {
- switch(event_type)
- {
- case HCI_EVNT_WLAN_KEEPALIVE:
- case HCI_EVNT_WLAN_UNSOL_CONNECT:
- case HCI_EVNT_WLAN_UNSOL_DISCONNECT:
- case HCI_EVNT_WLAN_UNSOL_INIT:
- case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE:
-
- if( tSLInformation.sWlanCB )
- {
- tSLInformation.sWlanCB(event_type, 0, 0);
- }
- break;
-
- case HCI_EVNT_WLAN_UNSOL_DHCP:
- {
- UINT8 params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status
- UINT8 *recParams = params;
-
- data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE;
-
- //Read IP address
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read subnet
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read default GW
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read DHCP server
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read DNS server
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- // read the status
- STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams);
-
-
- if( tSLInformation.sWlanCB )
- {
- tSLInformation.sWlanCB(event_type, (CHAR *)params, sizeof(params));
- }
- }
- break;
-
- case HCI_EVNT_WLAN_ASYNC_PING_REPORT:
- {
- netapp_pingreport_args_t params;
- data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE;
- STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent);
- STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received);
- STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time);
- STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time);
- STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time);
-
- if( tSLInformation.sWlanCB )
- {
- tSLInformation.sWlanCB(event_type, (CHAR *)¶ms, sizeof(params));
- }
- }
- break;
- case HCI_EVNT_BSD_TCP_CLOSE_WAIT:
- {
- data = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE;
- if( tSLInformation.sWlanCB )
- {
- //data[0] represents the socket id, for which FIN was received by remote.
- //Upon receiving this event, the user can close the socket, or else the
- //socket will be closded after inacvitity timeout (by default 60 seconds)
- tSLInformation.sWlanCB(event_type, data, 1);
- }
- }
- break;
-
- //'default' case which means "event not supported"
- default:
- return (0);
- }
- return(1);
- }
-
- if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO)
- || (event_type == HCI_EVNT_WRITE))
- {
- CHAR *pArg;
- INT32 status;
-
- pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr);
- STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status);
-
- if (ERROR_SOCKET_INACTIVE == status)
- {
- // The only synchronous event that can come from SL device in form of
- // command complete is "Command Complete" on data sent, in case SL device
- // was unable to transmit
- STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, tSLInformation.slTransmitDataError);
- update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr));
-
- return (1);
- }
- else
- return (0);
- }
-
- //handle a case where unsolicited event arrived, but was not handled by any of the cases above
- if ((event_type != tSLInformation.usRxEventOpcode) && (event_type != HCI_EVNT_PATCHES_REQ))
- {
- return(1);
- }
-
- return(0);
-}
-
-//*****************************************************************************
-//
-//! hci_unsolicited_event_handler
-//!
-//! @param None
-//!
-//! @return ESUCCESS if successful, EFAIL if an error occurred
-//!
-//! @brief Parse the incoming unsolicited event packets and issues
-//! corresponding event handler.
-//
-//*****************************************************************************
-INT32 hci_unsolicited_event_handler(void)
-{
- UINT32 res = 0;
- UINT8 *pucReceivedData;
-
- if (tSLInformation.usEventOrDataReceived != 0)
- {
- pucReceivedData = (tSLInformation.pucReceivedData);
-
- if (*pucReceivedData == HCI_TYPE_EVNT)
- {
-
- // In case unsolicited event received - here the handling finished
- if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 1)
- {
-
- // There was an unsolicited event received - we can release the buffer
- // and clean the event received
- tSLInformation.usEventOrDataReceived = 0;
-
- res = 1;
- SpiResumeSpi();
- }
- }
- }
-
- return res;
-}
-
-//*****************************************************************************
-//
-//! set_socket_active_status
-//!
-//! @param Sd
-//! @param Status
-//! @return none
-//!
-//! @brief Check if the socket ID and status are valid and set
-//! accordingly the global socket status
-//
-//*****************************************************************************
-void set_socket_active_status(INT32 Sd, INT32 Status)
-{
- if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status))
- {
- socket_active_status &= ~(1 << Sd); /* clean socket's mask */
- socket_active_status |= (Status << Sd); /* set new socket's mask */
- }
-}
-
-
-//*****************************************************************************
-//
-//! hci_event_unsol_flowcontrol_handler
-//!
-//! @param pEvent pointer to the string contains parameters for IPERF
-//! @return ESUCCESS if successful, EFAIL if an error occurred
-//!
-//! @brief Called in case unsolicited event from type
-//! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received.
-//! Keep track on the number of packets transmitted and update the
-//! number of free buffer in the SL device.
-//
-//*****************************************************************************
-INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent)
-{
-
- INT32 temp, value;
- UINT16 i;
- UINT16 pusNumberOfHandles=0;
- CHAR *pReadPayload;
-
- STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles);
- pReadPayload = ((CHAR *)pEvent +
- HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles));
- temp = 0;
-
- for(i = 0; i < pusNumberOfHandles ; i++)
- {
- STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value);
- temp += value;
- pReadPayload += FLOW_CONTROL_EVENT_SIZE;
- }
-
- tSLInformation.usNumberOfFreeBuffers += temp;
- tSLInformation.NumberOfReleasedPackets += temp;
-
- return(ESUCCESS);
-}
-
-//*****************************************************************************
-//
-//! get_socket_active_status
-//!
-//! @param Sd Socket IS
-//! @return Current status of the socket.
-//!
-//! @brief Retrieve socket status
-//
-//*****************************************************************************
-
-INT32 get_socket_active_status(INT32 Sd)
-{
- if(M_IS_VALID_SD(Sd))
- {
- return (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE;
- }
- return SOCKET_STATUS_INACTIVE;
-}
-
-//*****************************************************************************
-//
-//! update_socket_active_status
-//!
-//! @param resp_params Socket IS
-//! @return Current status of the socket.
-//!
-//! @brief Retrieve socket status
-//
-//*****************************************************************************
-void update_socket_active_status(CHAR *resp_params)
-{
- INT32 status, sd;
-
- STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd);
- STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status);
-
- if(ERROR_SOCKET_INACTIVE == status)
- {
- set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
- }
-}
-
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitEvent
-//!
-//! @param usOpcode command operation code
-//! @param pRetParams command return parameters
-//!
-//! @return none
-//!
-//! @brief Wait for event, pass it to the hci_event_handler and
-//! update the event opcode in a global variable.
-//
-//*****************************************************************************
-
-void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams)
-{
- // In the blocking implementation the control to caller will be returned only
- // after the end of current transaction
- tSLInformation.usRxEventOpcode = usOpcode;
- hci_event_handler(pRetParams, 0, 0);
-}
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitData
-//!
-//! @param pBuf data buffer
-//! @param from from information
-//! @param fromlen from information length
-//!
-//! @return none
-//!
-//! @brief Wait for data, pass it to the hci_event_handler
-//! and update in a global variable that there is
-//! data to read.
-//
-//*****************************************************************************
-
-void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen)
-{
- // In the blocking implementation the control to caller will be returned only
- // after the end of current transaction, i.e. only after data will be received
- tSLInformation.usRxDataPending = 1;
- hci_event_handler(pBuf, from, fromlen);
-}
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/hci.c b/drivers/cc3000/src/hci.c
deleted file mode 100644
index 4391692b8bc2b..0000000000000
--- a/drivers/cc3000/src/hci.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*****************************************************************************
-*
-* hci.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup hci_app
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include "cc3000_common.h"
-#include "hci.h"
-#include "ccspi.h"
-#include "evnt_handler.h"
-#include "wlan.h"
-
-#define SL_PATCH_PORTION_SIZE (1000)
-
-
-//*****************************************************************************
-//
-//! hci_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param ucArgsLength length of the arguments
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI command.
-//
-//*****************************************************************************
-UINT16 hci_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength)
-{
- UINT8 *stream;
-
- stream = (pucBuff + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_CMND);
- stream = UINT16_TO_STREAM(stream, usOpcode);
- UINT8_TO_STREAM(stream, ucArgsLength);
-
- //Update the opcode of the event we will be waiting for
- SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE);
-
- return(0);
-}
-
-//*****************************************************************************
-//
-//! hci_data_send
-//!
-//! @param usOpcode command operation code
-//! @param ucArgs pointer to the command's arguments buffer
-//! @param usArgsLength length of the arguments
-//! @param ucTail pointer to the data buffer
-//! @param usTailLength buffer length
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI data write operation
-//
-//*****************************************************************************
-INT32 hci_data_send(UINT8 ucOpcode,
- UINT8 *ucArgs,
- UINT16 usArgsLength,
- UINT16 usDataLength,
- const UINT8 *ucTail,
- UINT16 usTailLength)
-{
- UINT8 *stream;
-
- stream = ((ucArgs) + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_DATA);
- UINT8_TO_STREAM(stream, ucOpcode);
- UINT8_TO_STREAM(stream, usArgsLength);
- stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength);
-
- // Send the packet over the SPI
- SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength);
-
- return(ESUCCESS);
-}
-
-
-//*****************************************************************************
-//
-//! hci_data_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the data buffer
-//! @param ucArgsLength arguments length
-//! @param ucDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepeare HCI header and initiate an HCI data write operation
-//
-//*****************************************************************************
-void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength,UINT16 ucDataLength)
-{
- UINT8 *stream = (pucBuff + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_DATA);
- UINT8_TO_STREAM(stream, usOpcode);
- UINT8_TO_STREAM(stream, ucArgsLength);
- stream = UINT16_TO_STREAM(stream, ucArgsLength + ucDataLength);
-
- // Send the command over SPI on data channel
- SpiWrite(pucBuff, ucArgsLength + ucDataLength + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE);
-
- return;
-}
-
-//*****************************************************************************
-//
-//! hci_patch_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param patch pointer to patch content buffer
-//! @param usDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepeare HCI header and initiate an HCI patch write operation
-//
-//*****************************************************************************
-void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength)
-{
- UINT8 *data_ptr = (pucBuff + SPI_HEADER_SIZE);
- UINT16 usTransLength;
- UINT8 *stream = (pucBuff + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_PATCH);
- UINT8_TO_STREAM(stream, ucOpcode);
- stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE);
-
- if (usDataLength <= SL_PATCH_PORTION_SIZE)
- {
- UINT16_TO_STREAM(stream, usDataLength);
- stream = UINT16_TO_STREAM(stream, usDataLength);
- memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength);
-
- // Update the opcode of the event we will be waiting for
- SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE);
- }
- else
- {
-
- usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE);
- UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE);
- stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE);
- memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE);
- usDataLength -= SL_PATCH_PORTION_SIZE;
- patch += SL_PATCH_PORTION_SIZE;
-
- // Update the opcode of the event we will be waiting for
- SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE);
-
- while (usDataLength)
- {
- if (usDataLength <= SL_PATCH_PORTION_SIZE)
- {
- usTransLength = usDataLength;
- usDataLength = 0;
-
- }
- else
- {
- usTransLength = SL_PATCH_PORTION_SIZE;
- usDataLength -= usTransLength;
- }
-
- *(UINT16 *)data_ptr = usTransLength;
- memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength);
- patch += usTransLength;
-
- // Update the opcode of the event we will be waiting for
- SpiWrite((UINT8 *)data_ptr, usTransLength + sizeof(usTransLength));
- }
- }
-}
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/inet_ntop.c b/drivers/cc3000/src/inet_ntop.c
deleted file mode 100644
index 83242efa00b07..0000000000000
--- a/drivers/cc3000/src/inet_ntop.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 1996-2001 Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
- * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
- * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include
-#include "cc3000_common.h"
-#include "socket.h"
-#include "inet_ntop.h"
-
-// We can't include stdio.h because it defines _types_fd_set, but we
-// need to use the CC3000 version of this type. So we must provide
-// our own declaration of snprintf. Grrr.
-int snprintf(char *str, size_t size, const char *fmt, ...);
-
-#define IN6ADDRSZ 16
-#define INADDRSZ 4
-#define INT16SZ 2
-
-#define ENOSPC (28)
-#define EAFNOSUPPORT (106)
-#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err)
-
-/*
- * Format an IPv4 address, more or less like inet_ntoa().
- *
- * Returns `dst' (as a const)
- * Note:
- * - uses no statics
- * - takes a unsigned char* not an in_addr as input
- */
-static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
-{
- size_t len;
- char tmp[sizeof "255.255.255.255"];
-
- tmp[0] = '\0';
- (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
- ((int)((unsigned char)src[3])) & 0xff,
- ((int)((unsigned char)src[2])) & 0xff,
- ((int)((unsigned char)src[1])) & 0xff,
- ((int)((unsigned char)src[0])) & 0xff);
-
- len = strlen(tmp);
- if(len == 0 || len >= size)
- {
- SET_ERRNO(ENOSPC);
- return (NULL);
- }
- strcpy(dst, tmp);
- return dst;
-}
-
-#ifdef ENABLE_IPV6
-/*
- * Convert IPv6 binary address into presentation (printable) format.
- */
-static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
-{
- /*
- * Note that int32_t and int16_t need only be "at least" large enough
- * to contain a value of the specified size. On some systems, like
- * Crays, there is no such thing as an integer variable with 16 bits.
- * Keep this in mind if you think this function should have been coded
- * to use pointer overlays. All the world's not a VAX.
- */
- char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
- char *tp;
- struct {
- long base;
- long len;
- } best, cur;
- unsigned long words[IN6ADDRSZ / INT16SZ];
- int i;
-
- /* Preprocess:
- * Copy the input (bytewise) array into a wordwise array.
- * Find the longest run of 0x00's in src[] for :: shorthanding.
- */
- memset(words, '\0', sizeof(words));
- for (i = 0; i < IN6ADDRSZ; i++)
- words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
-
- best.base = -1;
- cur.base = -1;
- best.len = 0;
- cur.len = 0;
-
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
- {
- if(words[i] == 0)
- {
- if(cur.base == -1)
- cur.base = i, cur.len = 1;
- else
- cur.len++;
- }
- else if(cur.base != -1)
- {
- if(best.base == -1 || cur.len > best.len)
- best = cur;
- cur.base = -1;
- }
- }
- if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
- best = cur;
- if(best.base != -1 && best.len < 2)
- best.base = -1;
-
- /* Format the result.
- */
- tp = tmp;
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
- {
- /* Are we inside the best run of 0x00's?
- */
- if(best.base != -1 && i >= best.base && i < (best.base + best.len))
- {
- if(i == best.base)
- *tp++ = ':';
- continue;
- }
-
- /* Are we following an initial run of 0x00s or any real hex?
- */
- if(i != 0)
- *tp++ = ':';
-
- /* Is this address an encapsulated IPv4?
- */
- if(i == 6 && best.base == 0 &&
- (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
- {
- if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
- {
- SET_ERRNO(ENOSPC);
- return (NULL);
- }
- tp += strlen(tp);
- break;
- }
- tp += snprintf(tp, 5, "%lx", words[i]);
- }
-
- /* Was it a trailing run of 0x00's?
- */
- if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
- *tp++ = ':';
- *tp++ = '\0';
-
- /* Check for overflow, copy, and we're done.
- */
- if((size_t)(tp - tmp) > size)
- {
- SET_ERRNO(ENOSPC);
- return (NULL);
- }
- strcpy(dst, tmp);
- return dst;
-}
-#endif /* ENABLE_IPV6 */
-
-/*
- * Convert a network format address to presentation format.
- *
- * Returns pointer to presentation format address (`buf').
- * Returns NULL on error and errno set with the specific
- * error, EAFNOSUPPORT or ENOSPC.
- *
- * On Windows we store the error in the thread errno, not
- * in the winsock error code. This is to avoid loosing the
- * actual last winsock error. So use macro ERRNO to fetch the
- * errno this funtion sets when returning NULL, not SOCKERRNO.
- */
-char *inet_ntop(int af, const void *src, char *buf, size_t size)
-{
- switch (af) {
- case AF_INET:
- return inet_ntop4((const unsigned char*)src, buf, size);
-#ifdef ENABLE_IPV6
- case AF_INET6:
- return inet_ntop6((const unsigned char*)src, buf, size);
-#endif
- default:
- SET_ERRNO(EAFNOSUPPORT);
- return NULL;
- }
-}
diff --git a/drivers/cc3000/src/inet_pton.c b/drivers/cc3000/src/inet_pton.c
deleted file mode 100644
index 5f5ae5f9d7f1e..0000000000000
--- a/drivers/cc3000/src/inet_pton.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* This is from the BIND 4.9.4 release, modified to compile by itself */
-
-/* Copyright (c) 1996 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-#include
-#include "cc3000_common.h"
-#include "socket.h"
-#include "inet_pton.h"
-
-#define IN6ADDRSZ 16
-#define INADDRSZ 4
-#define INT16SZ 2
-
-static int inet_pton4(const char *src, unsigned char *dst);
-#ifdef ENABLE_IPV6
-static int inet_pton6(const char *src, unsigned char *dst);
-#endif
-
-#define EAFNOSUPPORT (106)
-#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err)
-
-/* int
- * inet_pton(af, src, dst)
- * convert from presentation format (which usually means ASCII printable)
- * to network format (which is usually some kind of binary format).
- * return:
- * 1 if the address was valid for the specified address family
- * 0 if the address wasn't valid (`dst' is untouched in this case)
- * -1 if some other error occurred (`dst' is untouched in this case, too)
- * notice:
- * On Windows we store the error in the thread errno, not
- * in the winsock error code. This is to avoid loosing the
- * actual last winsock error. So use macro ERRNO to fetch the
- * errno this funtion sets when returning (-1), not SOCKERRNO.
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton(int af, const char *src, void *dst)
-{
- switch (af) {
- case AF_INET:
- return (inet_pton4(src, (unsigned char *)dst));
-#ifdef ENABLE_IPV6
- case AF_INET6:
- return (inet_pton6(src, (unsigned char *)dst));
-#endif
- default:
- SET_ERRNO(EAFNOSUPPORT);
- return (-1);
- }
- /* NOTREACHED */
-}
-
-/* int
- * inet_pton4(src, dst)
- * like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- * 1 if `src' is a valid dotted quad, else 0.
- * notice:
- * does not touch `dst' unless it's returning 1.
- * author:
- * Paul Vixie, 1996.
- */
-static int inet_pton4(const char *src, unsigned char *dst)
-{
- static const char digits[] = "0123456789";
- int saw_digit, octets, ch;
- unsigned char tmp[INADDRSZ], *tp;
-
- saw_digit = 0;
- octets = 0;
- tp = tmp;
- *tp = 0;
- while((ch = *src++) != '\0') {
- const char *pch;
-
- if((pch = strchr(digits, ch)) != NULL) {
- unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
-
- if(saw_digit && *tp == 0)
- return (0);
- if(val > 255)
- return (0);
- *tp = (unsigned char)val;
- if(! saw_digit) {
- if(++octets > 4)
- return (0);
- saw_digit = 1;
- }
- }
- else if(ch == '.' && saw_digit) {
- if(octets == 4)
- return (0);
- *++tp = 0;
- saw_digit = 0;
- }
- else
- return (0);
- }
- if(octets < 4)
- return (0);
- memcpy(dst, tmp, INADDRSZ);
- return (1);
-}
-
-#ifdef ENABLE_IPV6
-/* int
- * inet_pton6(src, dst)
- * convert presentation level address to network order binary form.
- * return:
- * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- * (1) does not touch `dst' unless it's returning 1.
- * (2) :: in a full address is silently ignored.
- * credit:
- * inspired by Mark Andrews.
- * author:
- * Paul Vixie, 1996.
- */
-static int inet_pton6(const char *src, unsigned char *dst)
-{
- static const char xdigits_l[] = "0123456789abcdef",
- xdigits_u[] = "0123456789ABCDEF";
- unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
- const char *xdigits, *curtok;
- int ch, saw_xdigit;
- unsigned int val;
-
- memset((tp = tmp), 0, IN6ADDRSZ);
- endp = tp + IN6ADDRSZ;
- colonp = NULL;
- /* Leading :: requires some special handling. */
- if(*src == ':')
- if(*++src != ':')
- return (0);
- curtok = src;
- saw_xdigit = 0;
- val = 0;
- while((ch = *src++) != '\0') {
- const char *pch;
-
- if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
- pch = strchr((xdigits = xdigits_u), ch);
- if(pch != NULL) {
- val <<= 4;
- val |= (pch - xdigits);
- if(++saw_xdigit > 4)
- return (0);
- continue;
- }
- if(ch == ':') {
- curtok = src;
- if(!saw_xdigit) {
- if(colonp)
- return (0);
- colonp = tp;
- continue;
- }
- if(tp + INT16SZ > endp)
- return (0);
- *tp++ = (unsigned char) (val >> 8) & 0xff;
- *tp++ = (unsigned char) val & 0xff;
- saw_xdigit = 0;
- val = 0;
- continue;
- }
- if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
- inet_pton4(curtok, tp) > 0) {
- tp += INADDRSZ;
- saw_xdigit = 0;
- break; /* '\0' was seen by inet_pton4(). */
- }
- return (0);
- }
- if(saw_xdigit) {
- if(tp + INT16SZ > endp)
- return (0);
- *tp++ = (unsigned char) (val >> 8) & 0xff;
- *tp++ = (unsigned char) val & 0xff;
- }
- if(colonp != NULL) {
- /*
- * Since some memmove()'s erroneously fail to handle
- * overlapping regions, we'll do the shift by hand.
- */
- const long n = tp - colonp;
- long i;
-
- if(tp == endp)
- return (0);
- for (i = 1; i <= n; i++) {
- endp[- i] = colonp[n - i];
- colonp[n - i] = 0;
- }
- tp = endp;
- }
- if(tp != endp)
- return (0);
- memcpy(dst, tmp, IN6ADDRSZ);
- return (1);
-}
-#endif /* ENABLE_IPV6 */
diff --git a/drivers/cc3000/src/netapp.c b/drivers/cc3000/src/netapp.c
deleted file mode 100644
index a6f60feda0d4c..0000000000000
--- a/drivers/cc3000/src/netapp.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*****************************************************************************
-*
-* netapp.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-
-#include
-#include "netapp.h"
-#include "hci.h"
-#include "socket.h"
-#include "evnt_handler.h"
-#include "nvmem.h"
-
-#define MIN_TIMER_VAL_SECONDS 10
-#define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \
- { \
- t = MIN_TIMER_VAL_SECONDS; \
- }
-
-
-#define NETAPP_DHCP_PARAMS_LEN (20)
-#define NETAPP_SET_TIMER_PARAMS_LEN (20)
-#define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4)
-#define NETAPP_PING_SEND_PARAMS_LEN (16)
-
-
-//*****************************************************************************
-//
-//! netapp_config_mac_adrress
-//!
-//! @param mac device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Configure device MAC address and store it in NVMEM.
-//! The value of the MAC address configured through the API will
-//! be stored in CC3000 non volatile memory, thus preserved
-//! over resets.
-//
-//*****************************************************************************
-INT32 netapp_config_mac_adrress(UINT8 * mac)
-{
- return nvmem_set_mac_address(mac);
-}
-
-//*****************************************************************************
-//
-//! netapp_dhcp
-//!
-//! @param aucIP device mac address, 6 bytes. Saved: yes
-//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes
-//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes
-//! @param aucDNSServer device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief netapp_dhcp is used to configure the network interface,
-//! static or dynamic (DHCP).\n In order to activate DHCP mode,
-//! aucIP, aucSubnetMask, aucDefaultGateway must be 0.
-//! The default mode of CC3000 is DHCP mode.
-//! Note that the configuration is saved in non volatile memory
-//! and thus preserved over resets.
-//!
-//! @note If the mode is altered a reset of CC3000 device is required
-//! in order to apply changes.\nAlso note that asynchronous event
-//! of DHCP_EVENT, which is generated when an IP address is
-//! allocated either by the DHCP server or due to static
-//! allocation is generated only upon a connection to the
-//! AP was established.
-//!
-//*****************************************************************************
-INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer)
-{
- INT8 scRet;
- UINT8 *ptr;
- UINT8 *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- ARRAY_TO_STREAM(args,aucIP,4);
- ARRAY_TO_STREAM(args,aucSubnetMask,4);
- ARRAY_TO_STREAM(args,aucDefaultGateway,4);
- args = UINT32_TO_STREAM(args, 0);
- ARRAY_TO_STREAM(args,aucDNSServer,4);
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet);
-
- return(scRet);
-}
-
-
-//*****************************************************************************
-//
-//! netapp_timeout_values
-//!
-//! @param aucDHCP DHCP lease time request, also impact
-//! the DHCP renew timeout. Range: [0-0xffffffff] seconds,
-//! 0 or 0xffffffff == infinity lease timeout.
-//! Resolution:10 seconds. Influence: only after
-//! reconnecting to the AP.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds.
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 14400 seconds.
-//!
-//! @param aucARP ARP refresh timeout, if ARP entry is not updated by
-//! incoming packet, the ARP entry will be deleted by
-//! the end of the timeout.
-//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 3600 seconds.
-//!
-//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout
-//! Range: [0-0xffffffff] seconds, 0 == infinity timeout
-//! Resolution: 10 seconds.
-//! Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 10 seconds.
-//!
-//! @param aucInactivity Socket inactivity timeout, socket timeout is
-//! refreshed by incoming or outgoing packet, by the
-//! end of the socket timeout the socket will be closed
-//! Range: [0-0xffffffff] sec, 0 == infinity timeout.
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 60 seconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Set new timeout values. Function set new timeout values for:
-//! DHCP lease timeout, ARP refresh timeout, keepalive event
-//! timeout and socket inactivity timeout
-//!
-//! @note If a parameter set to non zero value which is less than 10s,
-//! it will be set automatically to 10s.
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP,UINT32 *aucKeepalive, UINT32 *aucInactivity)
-{
- INT8 scRet;
- UINT8 *ptr;
- UINT8 *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Set minimal values of timers
- MIN_TIMER_SET(*aucDHCP)
- MIN_TIMER_SET(*aucARP)
- MIN_TIMER_SET(*aucKeepalive)
- MIN_TIMER_SET(*aucInactivity)
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, *aucDHCP);
- args = UINT32_TO_STREAM(args, *aucARP);
- args = UINT32_TO_STREAM(args, *aucKeepalive);
- args = UINT32_TO_STREAM(args, *aucInactivity);
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet);
-
- return(scRet);
-}
-#endif
-
-
-//*****************************************************************************
-//
-//! netapp_ping_send
-//!
-//! @param ip destination IP address
-//! @param pingAttempts number of echo requests to send
-//! @param pingSize send buffer size which may be up to 1400 bytes
-//! @param pingTimeout Time to wait for a response,in milliseconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief send ICMP ECHO_REQUEST to network hosts
-//!
-//! @note If an operation finished successfully asynchronous ping report
-//! event will be generated. The report structure is as defined
-//! by structure netapp_pingreport_args_t.
-//!
-//! @warning Calling this function while a previous Ping Requests are in
-//! progress will stop the previous ping request.
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32
- netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout)
-{
- INT8 scRet;
- UINT8 *ptr, *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, *ip);
- args = UINT32_TO_STREAM(args, ulPingAttempts);
- args = UINT32_TO_STREAM(args, ulPingSize);
- args = UINT32_TO_STREAM(args, ulPingTimeout);
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet);
-
- return(scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_report
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Request for ping status. This API triggers the CC3000 to send
-//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT.
-//! This event will carry the report structure:
-//! netapp_pingreport_args_t. This structure is filled in with ping
-//! results up till point of triggering API.
-//! netapp_pingreport_args_t:\n packets_sent - echo sent,
-//! packets_received - echo reply, min_round_time - minimum
-//! round time, max_round_time - max round time,
-//! avg_round_time - average round time
-//!
-//! @note When a ping operation is not active, the returned structure
-//! fields are 0.
-//!
-//*****************************************************************************
-
-
-#ifndef CC3000_TINY_DRIVER
-void netapp_ping_report()
-{
- UINT8 *ptr;
- ptr = tSLInformation.pucTxCommandBuffer;
- INT8 scRet;
-
- scRet = EFAIL;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_PING_REPORT, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_stop
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief Stop any ping request.
-//!
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_ping_stop()
-{
- INT8 scRet;
- UINT8 *ptr;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_PING_STOP, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet);
-
- return(scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ipconfig
-//!
-//! @param[out] ipconfig This argument is a pointer to a
-//! tNetappIpconfigRetArgs structure. This structure is
-//! filled in with the network interface configuration.
-//! tNetappIpconfigRetArgs:\n aucIP - ip address,
-//! aucSubnetMask - mask, aucDefaultGateway - default
-//! gateway address, aucDHCPServer - dhcp server address
-//! aucDNSServer - dns server address, uaMacAddr - mac
-//! address, uaSSID - connected AP ssid
-//!
-//! @return none
-//!
-//! @brief Obtain the CC3000 Network interface information.
-//! Note that the information is available only after the WLAN
-//! connection was established. Calling this function before
-//! associated, will cause non-defined values to be returned.
-//!
-//! @note The function is useful for figuring out the IP Configuration of
-//! the device when DHCP is used and for figuring out the SSID of
-//! the Wireless network the device is associated with.
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig )
-{
- UINT8 *ptr;
-
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_IPCONFIG, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig );
-
-}
-#else
-void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig )
-{
-
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_arp_flush
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Flushes ARP table
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_arp_flush(void)
-{
- INT8 scRet;
- UINT8 *ptr;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet);
-
- return(scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_set_debug_level
-//!
-//! @param[in] level debug level. Bitwise [0-8],
-//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical
-//! message, 1 information message, 2 - core messages, 3 -
-//! HCI messages, 4 - Network stack messages, 5 - wlan
-//! messages, 6 - wlan driver messages, 7 - epprom messages,
-//! 8 - general messages. Default: 0x13f. Saved: no
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Debug messages sent via the UART debug channel, this function
-//! enable/disable the debug level
-//!
-//*****************************************************************************
-
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_set_debug_level(UINT32 ulLevel)
-{
- INT8 scRet;
- UINT8 *ptr, *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- //
- // Fill in temporary command buffer
- //
- args = UINT32_TO_STREAM(args, ulLevel);
-
-
- //
- // Initiate a HCI command
- //
- hci_command_send(HCI_NETAPP_SET_DEBUG_LEVEL, ptr, NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN);
-
- //
- // Wait for command complete event
- //
- SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet);
-
- return(scRet);
-
-}
-#endif
diff --git a/drivers/cc3000/src/nvmem.c b/drivers/cc3000/src/nvmem.c
deleted file mode 100644
index c6e170a746504..0000000000000
--- a/drivers/cc3000/src/nvmem.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*****************************************************************************
-*
-* nvmem.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup nvmem_api
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include "nvmem.h"
-#include "hci.h"
-#include "socket.h"
-#include "evnt_handler.h"
-
-//*****************************************************************************
-//
-// Prototypes for the structures for APIs.
-//
-//*****************************************************************************
-
-#define NVMEM_READ_PARAMS_LEN (12)
-#define NVMEM_CREATE_PARAMS_LEN (8)
-#define NVMEM_WRITE_PARAMS_LEN (16)
-
-//*****************************************************************************
-//
-//! nvmem_read
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID,
-//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID,
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID,
-//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID,
-//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to read
-//! @param ulOffset ulOffset in file from where to read
-//! @param buff output buffer pointer
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads data from the file referred by the ulFileId parameter.
-//! Reads data from file ulOffset till length. Err if the file can't
-//! be used, is invalid, or if the read is out of bounds.
-//!
-//*****************************************************************************
-
-INT32 nvmem_read(UINT32 ulFileId, UINT32 ulLength, UINT32 ulOffset, UINT8 *buff)
-{
- UINT8 ucStatus = 0xFF;
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulFileId);
- args = UINT32_TO_STREAM(args, ulLength);
- args = UINT32_TO_STREAM(args, ulOffset);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN);
- SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus);
-
- // In case there is data - read it - even if an error code is returned
- // Note: It is the user responsibility to ignore the data in case of an error code
-
- // Wait for the data in a synchronous way. Here we assume that the buffer is
- // big enough to store also parameters of nvmem
-
- SimpleLinkWaitData(buff, 0, 0);
-
- return(ucStatus);
-}
-
-//*****************************************************************************
-//
-//! nvmem_write
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to write
-//! @param ulEntryOffset offset in file to start write operation from
-//! @param buff data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write data to nvmem.
-//! writes data to file referred by the ulFileId parameter.
-//! Writes data to file ulOffset till ulLength.The file id will be
-//! marked invalid till the write is done. The file entry doesn't
-//! need to be valid - only allocated.
-//!
-//*****************************************************************************
-
-INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff)
-{
- INT32 iRes;
- UINT8 *ptr;
- UINT8 *args;
-
- iRes = EFAIL;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulFileId);
- args = UINT32_TO_STREAM(args, 12);
- args = UINT32_TO_STREAM(args, ulLength);
- args = UINT32_TO_STREAM(args, ulEntryOffset);
-
- memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE +
- NVMEM_WRITE_PARAMS_LEN),buff,ulLength);
-
- // Initiate a HCI command but it will come on data channel
- hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN,
- ulLength);
-
- SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes);
-
- return(iRes);
-}
-
-
-//*****************************************************************************
-//
-//! nvmem_set_mac_address
-//!
-//! @param mac mac address to be set
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write MAC address to EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-
-UINT8 nvmem_set_mac_address(UINT8 *mac)
-{
- return nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
-}
-
-//*****************************************************************************
-//
-//! nvmem_get_mac_address
-//!
-//! @param[out] mac mac address
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read MAC address from EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-
-UINT8 nvmem_get_mac_address(UINT8 *mac)
-{
- return nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
-}
-
-//*****************************************************************************
-//
-//! nvmem_write_patch
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! @param spLength number of bytes to write
-//! @param spData SP data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief program a patch to a specific file ID.
-//! The SP data is assumed to be organized in 2-dimensional.
-//! Each line is SP_PORTION_SIZE bytes long. Actual programming is
-//! applied in SP_PORTION_SIZE bytes portions.
-//!
-//*****************************************************************************
-
-UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData)
-{
- UINT8 status = 0;
- UINT16 offset = 0;
- UINT8* spDataPtr = (UINT8*)spData;
-
- while ((status == 0) && (spLength >= SP_PORTION_SIZE))
- {
- status = nvmem_write(ulFileId, SP_PORTION_SIZE, offset, spDataPtr);
- offset += SP_PORTION_SIZE;
- spLength -= SP_PORTION_SIZE;
- spDataPtr += SP_PORTION_SIZE;
- }
-
- if (status !=0)
- {
- // NVMEM error occurred
- return status;
- }
-
- if (spLength != 0)
- {
- // if reached here, a reminder is left
- status = nvmem_write(ulFileId, spLength, offset, spDataPtr);
- }
-
- return status;
-}
-
-//*****************************************************************************
-//
-//! nvmem_read_sp_version
-//!
-//! @param[out] patchVer first number indicates package ID and the second
-//! number indicates package build number
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read patch version. read package version (WiFi FW patch,
-//! driver-supplicant-NS patch, bootloader patch)
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-UINT8 nvmem_read_sp_version(UINT8* patchVer)
-{
- UINT8 *ptr;
- // 1st byte is the status and the rest is the SP version
- UINT8 retBuf[5];
-
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command, no args are required
- hci_command_send(HCI_CMND_READ_SP_VERSION, ptr, 0);
- SimpleLinkWaitEvent(HCI_CMND_READ_SP_VERSION, retBuf);
-
- // package ID
- *patchVer = retBuf[3];
- // package build number
- *(patchVer+1) = retBuf[4];
-
- return(retBuf[0]);
-}
-#endif
-
-//*****************************************************************************
-//
-//! nvmem_create_entry
-//!
-//! @param ulFileId nvmem file Id:\n
-//! * NVMEM_AES128_KEY_FILEID: 12
-//! * NVMEM_SHARED_MEM_FILEID: 13
-//! * and fileIDs 14 and 15
-//! @param ulNewLen entry ulLength
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Create new file entry and allocate space on the NVMEM.
-//! Applies only to user files.
-//! Modify the size of file.
-//! If the entry is unallocated - allocate it to size
-//! ulNewLen (marked invalid).
-//! If it is allocated then deallocate it first.
-//! To just mark the file as invalid without resizing -
-//! set ulNewLen=0.
-//!
-//*****************************************************************************
-
-INT32 nvmem_create_entry(UINT32 ulFileId, UINT32 ulNewLen)
-{
- UINT8 *ptr;
- UINT8 *args;
- UINT8 retval;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulFileId);
- args = UINT32_TO_STREAM(args, ulNewLen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN);
-
- SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval);
-
- return(retval);
-}
-
-
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/patch.c b/drivers/cc3000/src/patch.c
deleted file mode 100644
index 227be3c9f2a30..0000000000000
--- a/drivers/cc3000/src/patch.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*****************************************************************************
- *
- * {PatchProgrammer_DR_Patch.c}
- *
- * Burn Patches to EEPROM
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * ALL RIGHTS RESERVED
- *
- *****************************************************************************/
-//
-// Service Pack version P1.13.7.15.28 - Driver patches
-// This file contains the CC3K driver and firmware patches
-// From CC3000-FRAM-PATCH V:1.13.7 15-MAY-2014
-
-unsigned short fw_length = 5700;
-unsigned short drv_length = 8024;
-
-const unsigned char wlan_drv_patch[8024] = { 0x00, 0x01, 0x00, 0x00, 0x50, 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x18, 0x00, 0xE4, 0x62, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7A, 0x63, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x0C, 0x49, 0x08, 0x60, 0x0C, 0x48, 0x19, 0x30, 0xF7, 0x46, 0x30, 0xB5, 0x05, 0x1C, 0xAC, 0x69, 0x68, 0x68, 0x5F, 0x30, 0x09, 0xD1, 0x60, 0x6B, 0x0C, 0x38, 0x01, 0x21, 0x8E, 0x46, 0x06, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x00, 0x20, 0x60, 0x63, 0xAC, 0x69, 0x6C, 0x60, 0x04, 0x48, 0x5B, 0x30, 0x30, 0xBD, 0x40, 0x3B, 0x08, 0x00, 0x49, 0xD0, 0x01, 0x00, 0x09, 0xEA, 0x02, 0x00, 0x91, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x05, 0x1C, 0xA8, 0x88, 0x00, 0x90, 0x28, 0x89, 0x01, 0x90, 0xE9, 0x68, 0x02, 0x91, 0x28, 0x7C, 0x03, 0x90, 0x2A, 0x6A, 0x00, 0x20, 0x17, 0x56, 0x68, 0x60, 0x00, 0x29, 0x4C, 0xD0, 0x00, 0x2F, 0x4A, 0xDC ,
-0xCA, 0x49, 0x0C, 0x1C, 0x08, 0x26, 0x04, 0x90, 0x21, 0x88, 0x00, 0x98, 0x81, 0x42, 0x0C, 0xD1, 0x62, 0x88, 0x01, 0x98, 0x82, 0x42, 0x08, 0xD1, 0x46, 0x20, 0x02, 0x5D, 0x03, 0x98, 0x82, 0x42, 0x03, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xB8, 0x42, 0x0A, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x22, 0xD1, 0x00, 0x98, 0x81, 0x42, 0x1F, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xFF, 0xFF, 0xD2, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB8, 0x42, 0x1B, 0xD1, 0x04, 0x20, 0x02, 0x1C, 0x02, 0x98, 0xB9, 0x49, 0x01, 0x23, 0x9E, 0x46, 0xEC, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x17, 0xD0, 0x20, 0x1D, 0x02, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x0D, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x09, 0xD0, 0xA0, 0x6D, 0x00, 0x28, 0x06, 0xD0, 0xAC, 0x34, 0x04, 0x98, 0x01, 0x30, 0x04, 0x90, 0x01, 0x3E, 0xC1, 0xD1, 0x07, 0xE0, 0x04, 0x98, 0x00, 0x06, 0x00, 0x0E ,
-0xAC, 0x21, 0x41, 0x43, 0xA6, 0x48, 0x40, 0x18, 0x68, 0x60, 0xA6, 0x48, 0xAD, 0x30, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xB5, 0xC2, 0x68, 0x90, 0x69, 0x02, 0x21, 0x01, 0x23, 0x9E, 0x46, 0xA2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xA2, 0x48, 0x61, 0x30, 0x00, 0xBD, 0x01, 0x79, 0x0B, 0x29, 0x03, 0xD0, 0x89, 0x00, 0x9F, 0x4A, 0x51, 0x5A, 0x01, 0xE0, 0x01, 0x21, 0x49, 0x02, 0x41, 0x60, 0x9D, 0x48, 0x0D, 0x30, 0xF7, 0x46, 0x01, 0x1C, 0xFF, 0xFF, 0x68, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x9C, 0x48, 0x02, 0x68, 0x9C, 0x48, 0x01, 0x2A, 0x01, 0xD1, 0x25, 0x30, 0xF7, 0x46, 0x9B, 0x4A, 0x12, 0x68, 0x4A, 0x60, 0x19, 0x30, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x99, 0x48, 0x98, 0x49, 0x08, 0x18, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x97, 0x48, 0xE7, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xFF, 0xB5, 0x46, 0x69, 0x40, 0x68, 0x01, 0x90, 0x94, 0x49, 0x0A, 0x7C, 0x9A, 0x4F, 0x01, 0x2A, 0x63, 0xD0, 0x09, 0x7C, 0x03, 0x29 ,
-0x60, 0xD0, 0x91, 0x4A, 0x92, 0x4B, 0x00, 0x21, 0x02, 0x91, 0x59, 0x56, 0x24, 0x23, 0x59, 0x43, 0x53, 0x18, 0x03, 0x93, 0x01, 0x28, 0x17, 0xD1, 0x8A, 0x18, 0x04, 0x23, 0x6C, 0x46, 0x8C, 0x49, 0x15, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x28, 0x43, 0x20, 0x70, 0x01, 0x32, 0x01, 0x31, 0x01, 0x34, 0x01, 0x3B, 0xF5, 0xD1, 0x31, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x40, 0xD0, 0x35, 0x1D, 0x82, 0x48, 0x00, 0x78, 0xFF, 0x28, 0xFF, 0xFF, 0xFE, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x11, 0xD0, 0x00, 0x28, 0x0F, 0xD0, 0x03, 0x98, 0x01, 0x1D, 0x28, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x7E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x00, 0x28, 0x05, 0xD1, 0x7A, 0x48, 0xA6, 0x46, 0x7B, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x05, 0xE0, 0x28, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0x78, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x99, 0x01, 0x29, 0x01, 0xD1, 0x00, 0x28, 0x1E, 0xD1 ,
-0x01, 0x99, 0x5F, 0x31, 0x01, 0xD0, 0x00, 0x28, 0x0F, 0xD1, 0xA8, 0x20, 0x81, 0x5D, 0x00, 0x29, 0x08, 0xD0, 0x49, 0x1E, 0x81, 0x55, 0x80, 0x5D, 0x00, 0x28, 0x09, 0xD1, 0x38, 0x1C, 0xFF, 0x30, 0x08, 0x30, 0x11, 0xE0, 0x03, 0x21, 0x02, 0x91, 0x00, 0xE0, 0xA8, 0x20, 0x02, 0x99, 0x81, 0x55, 0x38, 0x1C, 0xFF, 0x30, 0x16, 0x30, 0x07, 0xE0, 0x01, 0x98, 0x01, 0x28, 0x02, 0xD1, 0x38, 0x1C, 0xA3, 0x30, 0x01, 0xE0, 0x38, 0x1C, 0x9F, 0x30, 0x00, 0x90, 0xFF, 0xBD, 0x00, 0xB5, 0x02, 0x1C, 0x10, 0x6A, 0xD1, 0x69, 0x52, 0x69, 0xC3, 0x69, 0x5A, 0x60, 0xFF, 0xFF, 0x94, 0x67, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x22, 0x96, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5E, 0x48, 0xFF, 0x30, 0x6E, 0x30, 0x00, 0xBD, 0x10, 0xB5, 0x0A, 0x1C, 0x41, 0x69, 0x00, 0x6A, 0x93, 0x69, 0xDB, 0x69, 0x58, 0x60, 0x90, 0x69, 0x01, 0x24, 0xA6, 0x46, 0x56, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xA6, 0x46, 0x56, 0x48, 0xFE, 0x44 ,
-0x00, 0x47, 0x55, 0x48, 0xFF, 0x30, 0xB6, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0x6E, 0x69, 0x53, 0x48, 0x02, 0x68, 0x5C, 0x21, 0x88, 0x5D, 0x04, 0x28, 0x15, 0xD1, 0x07, 0x20, 0x88, 0x55, 0x10, 0x0B, 0x11, 0xD2, 0x01, 0x24, 0xA6, 0x46, 0x4E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x0A, 0xD0, 0x47, 0x21, 0x89, 0x57, 0xC1, 0x60, 0x11, 0x21, 0xC9, 0x02, 0x00, 0x22, 0x04, 0x23, 0xA6, 0x46, 0xE8, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x01, 0x20, 0x68, 0x60, 0x43, 0x48, 0xED, 0x49, 0x08, 0x18, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0xAE, 0x69, 0x9C, 0x20, 0x80, 0x19, 0x4B, 0x21, 0x89, 0x00, 0x01, 0x24, 0xFF, 0xFF, 0x2A, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA6, 0x46, 0xE8, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5C, 0x21, 0x88, 0x5D, 0x07, 0x28, 0x01, 0xD1, 0x09, 0x20, 0x00, 0xE0, 0x05, 0x20, 0xAA, 0x69, 0x88, 0x54, 0x30, 0x1C, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x68, 0x60, 0xE8, 0x48 ,
-0x4D, 0x30, 0x70, 0xBD, 0xF0, 0xB5, 0x41, 0x68, 0x82, 0x68, 0x88, 0x23, 0x5E, 0x18, 0x37, 0x88, 0x0B, 0x6F, 0x00, 0x2B, 0x01, 0xD1, 0x00, 0x2F, 0x10, 0xD1, 0x06, 0x2F, 0x02, 0xDD, 0x00, 0x21, 0xC9, 0x43, 0x07, 0xE0, 0x33, 0x88, 0x9B, 0x00, 0xC9, 0x18, 0x0A, 0x67, 0x31, 0x88, 0x01, 0x31, 0x31, 0x80, 0x01, 0x21, 0x81, 0x60, 0xE1, 0x48, 0x1D, 0x30, 0xF0, 0xBD, 0x0B, 0x1C, 0x01, 0x24, 0x5D, 0x6F, 0x1D, 0x67, 0x04, 0x33, 0x01, 0x34, 0x06, 0x2C, 0xE1, 0xDA, 0xF8, 0xE7, 0x00, 0xB5, 0x00, 0x21, 0xC1, 0x60, 0xE9, 0x48, 0x01, 0x68, 0x10, 0x31, 0xE6, 0x48, 0x20, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE5, 0x48, 0xFB, 0x30, 0x00, 0xBD, 0xFF, 0xFF, 0xC0, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0x54, 0x19, 0x1B, 0x00, 0x91, 0x1A, 0x01, 0x00, 0x4B, 0xAD, 0x03, 0x00, 0x61, 0x4E, 0x01, 0x00, 0x06, 0x32, 0x08, 0x00, 0x1F, 0x0B, 0x02, 0x00, 0x54, 0x3F ,
-0x08, 0x00, 0x45, 0xC1, 0x00, 0x00, 0x84, 0x3C, 0x08, 0x00, 0x1B, 0x02, 0x00, 0x00, 0xED, 0x17, 0x00, 0x00, 0xF3, 0xC1, 0x01, 0x00, 0x34, 0x19, 0x1B, 0x00, 0x08, 0x19, 0x1B, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xCB, 0x67, 0x03, 0x00, 0x0D, 0x47, 0x02, 0x00, 0x39, 0x42, 0x03, 0x00, 0xBD, 0xE7, 0x02, 0x00, 0xB1, 0x40, 0x03, 0x00, 0xB9, 0xEA, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0x24, 0x41, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0xF0, 0xB5, 0x88, 0xB0, 0x06, 0x91, 0x07, 0x90, 0x86, 0x69, 0xF0, 0x1C, 0xD9, 0xA1, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x14, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x32, 0xD1, 0xF2, 0x79, 0xD7, 0x48, 0x02, 0x70, 0x35, 0x7A, 0x77, 0x7A, 0x78, 0x1B, 0xFF, 0xFF, 0x56, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x43, 0x1C, 0x93, 0x42, 0x1D, 0xD0, 0x16, 0x2A, 0x0C, 0xDB, 0x00, 0x2D, 0x0A, 0xD1, 0xD6, 0x48, 0x04, 0x70, 0x0A, 0x20 ,
-0x81, 0x19, 0xD0, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x74, 0xE0, 0xD2, 0x48, 0x04, 0x70, 0xCC, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0xB1, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x67, 0xE0, 0x8F, 0xC6, 0x03, 0x00, 0xC9, 0x48, 0x04, 0x70, 0xC9, 0x48, 0x04, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xC2, 0x48, 0xA6, 0x46, 0xAA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x59, 0xE0, 0xF0, 0x1C, 0x03, 0x21, 0x0A, 0x1C, 0xBC, 0xA1, 0xA6, 0x46, 0xC6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x4F, 0xD1, 0xF1, 0x79, 0xBB, 0x48, 0x01, 0x70, 0xBB, 0x4D, 0xB2, 0x79, 0x2A, 0x70, 0x03, 0x20, 0x17, 0x49, 0xF4, 0x31, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x28, 0x78, 0x00, 0x28, 0x0B, 0xD1, 0xFF, 0xE7, 0xB8, 0x49, 0x0C, 0x70, 0xB8, 0x49, 0xFF, 0xFF, 0xEC, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x03, 0x20, 0x0F, 0x49, 0xF5, 0x31, 0xA6, 0x46 ,
-0xB6, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x20, 0x1C, 0xF2, 0x79, 0x35, 0x7A, 0x77, 0x7A, 0x79, 0x1B, 0x4B, 0x1C, 0x93, 0x42, 0x20, 0xD0, 0xA9, 0x49, 0x09, 0x78, 0x16, 0x29, 0x0F, 0xDB, 0x00, 0x2D, 0x0D, 0xD1, 0xAB, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xE9, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0x8B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x1A, 0xE0, 0xC0, 0x46, 0xC7, 0x04, 0x00, 0x00, 0xA5, 0x49, 0x08, 0x70, 0xE3, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0A, 0xE0, 0x9E, 0x49, 0x08, 0x70, 0x9E, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xDB, 0x48, 0xA6, 0x46, 0x7D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x96, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x06, 0xD0, 0x94, 0x48, 0x00, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x93, 0x48, 0x00, 0x78, 0x00, 0x28, 0xFF, 0xFF, 0x82, 0x6A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 ,
-0x00, 0xD1, 0x8C, 0xE0, 0x03, 0x20, 0x17, 0x21, 0x89, 0x01, 0xA6, 0x46, 0x90, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x87, 0x48, 0x01, 0x78, 0x87, 0x48, 0x07, 0x78, 0x84, 0x4E, 0x83, 0x4D, 0xE0, 0x48, 0x00, 0x68, 0x00, 0x28, 0x2E, 0xD1, 0x07, 0x98, 0x41, 0x61, 0x06, 0x62, 0xC6, 0x48, 0x06, 0x9A, 0x10, 0x64, 0x02, 0x2F, 0x01, 0xD0, 0x03, 0x2F, 0x01, 0xD1, 0x03, 0x22, 0x00, 0xE0, 0x3A, 0x1C, 0x06, 0x9B, 0xDA, 0x63, 0x2A, 0x78, 0x9A, 0x63, 0x01, 0x2F, 0x03, 0xD1, 0x05, 0x29, 0x04, 0xD0, 0x0D, 0x29, 0x02, 0xD0, 0xEC, 0x48, 0xDB, 0x30, 0x64, 0xE0, 0x00, 0x25, 0x00, 0x95, 0x01, 0x91, 0x02, 0x96, 0x03, 0x95, 0x04, 0x90, 0x2B, 0x1C, 0x20, 0x1C, 0x01, 0x1C, 0x8E, 0x46, 0xE6, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0xE6, 0x48, 0x04, 0x60, 0x28, 0x1C, 0xA6, 0x46, 0xE5, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x4C, 0xE0, 0x0D, 0x27, 0x00, 0x20, 0x39, 0x1C, 0x05, 0xAA, 0xA6, 0x46, 0xE3, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x46 ,
-0xFF, 0xFF, 0x18, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x80, 0x8A, 0x40, 0x08, 0x05, 0xD2, 0x38, 0x1C, 0x50, 0x21, 0xA6, 0x46, 0xDC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x38, 0x1C, 0x21, 0x1C, 0x0B, 0x1C, 0x29, 0x1C, 0x00, 0x22, 0xA6, 0x46, 0xD9, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x2B, 0x78, 0x0D, 0x20, 0x31, 0x1C, 0x22, 0x1C, 0xA6, 0x46, 0xD5, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x28, 0x78, 0x01, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x57, 0x49, 0x23, 0x1C, 0xA6, 0x46, 0xD0, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x55, 0x4E, 0x28, 0x78, 0x02, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x31, 0x1C, 0x23, 0x1C, 0xA6, 0x46, 0xCA, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x30, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x28, 0x78, 0x03, 0x30, 0x02, 0x1C, 0x4C, 0x48, 0x03, 0x78, 0x0D, 0x20, 0x8F, 0x49, 0xA6, 0x46, 0xC3, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xBF, 0x48, 0x04, 0x60, 0x00, 0x20, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xB9, 0x48, 0xEC, 0x49 ,
-0x08, 0x18, 0x08, 0xB0, 0xF0, 0xBD, 0xC0, 0x46, 0x7B, 0xC0, 0xFF, 0xFF, 0xAE, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x1C, 0xE9, 0x48, 0x02, 0x68, 0xE9, 0x48, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x22, 0x0A, 0x62, 0x8A, 0x61, 0x1D, 0x30, 0xF7, 0x46, 0xD7, 0x30, 0xF7, 0x46, 0xC0, 0x46, 0x9F, 0x03, 0x00, 0x00, 0x7D, 0xB8, 0x03, 0x00, 0x01, 0x1C, 0xE2, 0x48, 0x02, 0x68, 0xE2, 0x48, 0x00, 0x2A, 0x02, 0xD0, 0xFF, 0x30, 0xB4, 0x30, 0xF7, 0x46, 0x00, 0x22, 0xCA, 0x61, 0x8A, 0x61, 0x4F, 0x30, 0xF7, 0x46, 0xC9, 0x21, 0x01, 0x00, 0x91, 0xE1, 0x00, 0x00, 0xDB, 0x48, 0x01, 0x68, 0x8A, 0x69, 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0x88, 0x61, 0x00, 0x20, 0x08, 0x61, 0xD8, 0x48, 0x23, 0x30, 0xF7, 0x46, 0x89, 0x17, 0x02, 0x00, 0x70, 0xB5, 0x05, 0x1C, 0xD5, 0x4E, 0x29, 0x6A, 0xEA, 0x69, 0x30, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x0B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x69, 0xA6, 0x46, 0xD1, 0x49 ,
-0xFE, 0x44, 0x08, 0x47, 0xA8, 0x69, 0x06, 0x30, 0xA8, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x68, 0x60, 0xEE, 0x60, 0xCE, 0x48, 0xFF, 0xFF, 0x44, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x6D, 0x30, 0x70, 0xBD, 0x46, 0x17, 0x1B, 0x00, 0x30, 0x3F, 0x08, 0x00, 0x41, 0xEB, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x30, 0xB5, 0xEE, 0x48, 0x01, 0x6D, 0x80, 0x6C, 0x08, 0x43, 0x18, 0xD0, 0xEC, 0x49, 0x08, 0x1C, 0x07, 0x22, 0xFF, 0x23, 0x09, 0x33, 0x1B, 0x58, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0x30, 0x1D, 0x30, 0x01, 0x3A, 0xF6, 0xD1, 0x0B, 0xE0, 0x02, 0x20, 0xF0, 0x4A, 0xF1, 0x4B, 0x01, 0x24, 0xA6, 0x46, 0xF0, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xA6, 0x46, 0xEF, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xEF, 0x48, 0xFF, 0x30, 0x5C, 0x30, 0x30, 0xBD, 0xC0, 0x46, 0x53, 0x53, 0x49, 0x44, 0x00, 0xC0, 0x46, 0xC0, 0x4B, 0x45, 0x59, 0x00, 0xEE, 0x62, 0x08, 0x00, 0xF0, 0x62, 0x08, 0x00, 0xEC, 0x62, 0x08, 0x00, 0xED, 0x62, 0x08, 0x00 ,
-0xE7, 0x7E, 0x03, 0x00, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0xF0, 0xB5, 0xFF, 0xFF, 0xDA, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x87, 0xB0, 0x00, 0x91, 0x01, 0x90, 0x6B, 0x48, 0x01, 0x68, 0xCC, 0x4A, 0x14, 0x1C, 0x02, 0x94, 0x07, 0x26, 0x00, 0x25, 0x03, 0x95, 0x04, 0x94, 0x05, 0x95, 0xDF, 0x48, 0x00, 0x68, 0x08, 0x43, 0x27, 0xD0, 0xE0, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0A, 0xDD, 0x03, 0x90, 0x40, 0x1C, 0x00, 0x99, 0x88, 0x60, 0xC2, 0x49, 0xFF, 0x20, 0x1D, 0x30, 0x68, 0x43, 0x0C, 0x18, 0xE0, 0x68, 0x04, 0x91, 0x02, 0x99, 0xC9, 0x68, 0x88, 0x42, 0x10, 0xDB, 0x88, 0x42, 0x10, 0xD1, 0x02, 0x98, 0x01, 0x27, 0xBE, 0x46, 0xCE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x90, 0x20, 0x1C, 0xBE, 0x46, 0xCB, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x99, 0x88, 0x42, 0x01, 0xDA, 0x05, 0x95, 0x02, 0x94 ,
-0x51, 0x48, 0x01, 0x68, 0xFF, 0x27, 0x09, 0x37, 0x38, 0x59, 0x00, 0x28, 0x06, 0xD0, 0xC7, 0x48, 0x00, 0x68, 0x07, 0x2E, 0x00, 0xD1, 0x2E, 0x1C, 0x08, 0x43, 0x04, 0xD0, 0xFF, 0x34, 0x1D, 0x34, 0x01, 0x35, 0x07, 0x2D, 0xC2, 0xDB, 0x07, 0x2E, 0xFF, 0xFF, 0x70, 0x6D, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0A, 0xD1, 0xC0, 0x48, 0x00, 0x68, 0x08, 0x43, 0x06, 0xD0, 0x05, 0x9E, 0x30, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0xBA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x98, 0x47, 0x61, 0x00, 0x21, 0x81, 0x61, 0xFF, 0x22, 0x1D, 0x32, 0x72, 0x43, 0x04, 0x99, 0x89, 0x18, 0xC1, 0x61, 0x06, 0x62, 0xB4, 0x48, 0x39, 0x30, 0x07, 0xB0, 0xF0, 0xBD, 0x10, 0xB5, 0x04, 0x1C, 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x40, 0x1E, 0x00, 0xD5, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x61, 0xAE, 0x48, 0x21, 0x30, 0x10, 0xBD, 0xC0, 0x46, 0x10, 0x63, 0x08, 0x00, 0x70, 0xB5, 0x04, 0x1C, 0xE5, 0x69, 0x66, 0x69 ,
-0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xA7, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x60, 0x60, 0xAB, 0x19, 0xA6, 0x4A, 0xA5, 0x49, 0x93, 0x42, 0x02, 0xD3, 0x9A, 0x1A, 0x82, 0x42, 0x02, 0xD9, 0x08, 0x1C, 0x99, 0x30, 0x70, 0xBD, 0x08, 0x1C, 0xAB, 0x30, 0x70, 0xBD, 0x08, 0x6B, 0x41, 0x7D, 0x02, 0x88, 0x92, 0x00, 0xFF, 0xFF, 0x06, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x51, 0x1A, 0x3C, 0x39, 0xFF, 0x22, 0x5F, 0x32, 0x91, 0x42, 0x03, 0xD9, 0x65, 0x21, 0x01, 0x80, 0x02, 0x21, 0x81, 0x73, 0x9B, 0x48, 0x99, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0xF8, 0xB5, 0x40, 0x68, 0x24, 0x21, 0x41, 0x43, 0x97, 0x48, 0x45, 0x18, 0x28, 0x1D, 0x0C, 0x21, 0x49, 0x19, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x91, 0x4C, 0x00, 0x28, 0x1B, 0xD0, 0x2B, 0x1C, 0x04, 0x22, 0x6E, 0x46, 0x91, 0x49, 0x1F, 0x7B, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33 ,
-0x01, 0x31, 0x01, 0x36, 0x01, 0x3A, 0xF5, 0xD1, 0x0C, 0x20, 0x41, 0x19, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x87, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x02, 0xD0, 0x20, 0x1C, 0x4A, 0x30, 0xF8, 0xBD, 0x20, 0x1C, 0xF8, 0xBD, 0xB1, 0xBD, 0x00, 0x00, 0x15, 0x95, 0x00, 0x00, 0x58, 0x3F, 0x08, 0x00, 0xF3, 0xF8, 0x00, 0x00, 0xE9, 0x09, 0x02, 0x00, 0xFF, 0xFF, 0x9C, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2B, 0x09, 0x02, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0xF8, 0xB5, 0x05, 0x1C, 0xAA, 0x69, 0x7D, 0x49, 0x00, 0x20, 0x08, 0x56, 0x24, 0x21, 0x41, 0x43, 0x76, 0x48, 0x43, 0x18, 0x04, 0x24, 0x6E, 0x46, 0x76, 0x49, 0x1F, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33, 0x01, 0x31, 0x01, 0x36, 0x01, 0x3C, 0xF5, 0xD1, 0x11, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x6D, 0x48, 0x04, 0xD0, 0x6E, 0x49, 0x09, 0x78 ,
-0x69, 0x60, 0x45, 0x30, 0xF8, 0xBD, 0xEC, 0x61, 0xAF, 0x30, 0xF8, 0xBD, 0x70, 0xB5, 0xC5, 0x68, 0x81, 0x68, 0x0A, 0x89, 0x6D, 0x4E, 0x00, 0x2A, 0x22, 0xD0, 0x01, 0x24, 0xC2, 0x6D, 0xA2, 0x18, 0xC2, 0x65, 0x08, 0x89, 0x0D, 0x28, 0x1B, 0xD1, 0x68, 0x6B, 0x21, 0x1C, 0xA6, 0x46, 0x63, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x22, 0x1C, 0x28, 0x1C, 0x00, 0x21, 0xA6, 0x46, 0x60, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x2C, 0x60, 0xE9, 0x6B, 0xFF, 0xFF, 0x32, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0x5C, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x1C, 0x3D, 0x30, 0x70, 0xBD, 0x30, 0x1C, 0x23, 0x30, 0x70, 0xBD, 0xC0, 0x46, 0xB1, 0x02, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x19, 0xC6, 0x00, 0x00, 0x5C, 0x3F, 0x08, 0x00, 0x1D, 0xC2, 0x00, 0x00, 0x68, 0x44, 0x08, 0x00, 0x43, 0x12, 0x03, 0x00, 0x34, 0x63, 0x08, 0x00, 0x2F, 0x7A, 0x02, 0x00 ,
-0xB4, 0x36, 0x08, 0x00, 0x8F, 0xF4, 0x01, 0x00, 0xF0, 0xB5, 0x05, 0x1C, 0xAB, 0x69, 0xEC, 0x69, 0x60, 0x68, 0x00, 0x68, 0x2A, 0x30, 0x01, 0x78, 0x0A, 0x06, 0x41, 0x78, 0x09, 0x04, 0x8A, 0x18, 0x81, 0x78, 0x09, 0x02, 0x8A, 0x18, 0xC1, 0x78, 0x8A, 0x18, 0x8E, 0x26, 0xF1, 0x5A, 0x09, 0x0A, 0x01, 0x70, 0xF0, 0x5C, 0x61, 0x68, 0x09, 0x68, 0x2B, 0x26, 0x70, 0x54, 0x8C, 0x20, 0xC0, 0x18, 0x61, 0x68, 0x0E, 0x68, 0x01, 0x88, 0x09, 0x0A, 0x2C, 0x27, 0xB9, 0x55, 0x61, 0x68, 0x09, 0x68, 0xFF, 0xFF, 0xC8, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2D, 0x26, 0x00, 0x78, 0x70, 0x54, 0x60, 0x68, 0x01, 0x68, 0x32, 0x31, 0x08, 0x78, 0x00, 0x02, 0x49, 0x78, 0x08, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x8C, 0x21, 0xCB, 0x58, 0x35, 0x49, 0x41, 0x40, 0x08, 0x04, 0x00, 0x0C, 0xC0, 0x18, 0x80, 0x1A, 0x01, 0x21, 0x8E, 0x46, 0x32, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x61, 0x68, 0x0A, 0x68, 0x32, 0x23, 0x01, 0x0A, 0x99, 0x54 ,
-0x61, 0x68, 0x09, 0x68, 0x33, 0x22, 0x50, 0x54, 0x60, 0x68, 0x68, 0x60, 0x2C, 0x48, 0xF0, 0xBD, 0x00, 0x00, 0x1B, 0x00, 0x34, 0x04, 0x1B, 0x00, 0x02, 0x6A, 0x8B, 0x69, 0xDB, 0x69, 0x1B, 0x68, 0x83, 0x60, 0x88, 0x69, 0xC0, 0x69, 0x41, 0x68, 0x8A, 0x42, 0x00, 0xDA, 0x42, 0x60, 0x25, 0x48, 0x79, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x57, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x91, 0x30, 0xF7, 0x46, 0x32, 0x04, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x15, 0x09, 0x02, 0x00, 0xC5, 0x93, 0x00, 0x00, 0x0D, 0x91, 0x00, 0x00, 0x40, 0x1E, 0x80, 0x00, 0x1E, 0x4B, 0xFF, 0xFF, 0x5E, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x19, 0x50, 0x1C, 0x49, 0x0A, 0x50, 0xF7, 0x46, 0xC0, 0x46, 0xBD, 0xB5, 0x00, 0x00, 0x95, 0x92, 0x00, 0x00, 0xFD, 0x93, 0x00, 0x00, 0x54, 0x3F, 0x08, 0x00, 0x29, 0x4F, 0x03, 0x00, 0xDF, 0xE8, 0x02, 0x00, 0x36, 0x89, 0x41, 0x00, 0x81, 0x06, 0x00, 0x00, 0xB1, 0x78, 0x00, 0x00, 0x94, 0xEC, 0x01, 0x00 ,
-0x08, 0x19, 0x1B, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x67, 0x66, 0x03, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xA7, 0x2F, 0x02, 0x00, 0x91, 0x44, 0x03, 0x00, 0x91, 0x63, 0x03, 0x00, 0x5B, 0x44, 0x03, 0x00, 0xE7, 0x44, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xA2, 0x03, 0x00, 0x6A, 0x1E, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0xD7, 0xE8, 0x01, 0x00, 0xE9, 0x78, 0x02, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x7B, 0x08, 0x00, 0xFC, 0xB5, 0x04, 0x1C, 0xA5, 0x69, 0x60, 0x6A, 0x01, 0x90, 0x20, 0x69, 0x00, 0x28, 0x35, 0xD4, 0x08, 0x28, 0x33, 0xDA, 0xE1, 0x69, 0x09, 0x68, 0xFF, 0xFF, 0xF4, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x2F, 0xD1, 0xAC, 0x21, 0x41, 0x43, 0x9E, 0x4A, 0x51, 0x5C, 0x49, 0x08, 0x27, 0xD3, 0x00, 0x06, 0x00, 0x16, 0xA2, 0x68, 0x69, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x39, 0x30, 0x1F, 0xD0 ,
-0x00, 0x2E, 0x1D, 0xD0, 0x00, 0x98, 0x07, 0x68, 0x00, 0x99, 0x0C, 0x39, 0x01, 0x98, 0x01, 0x60, 0x28, 0x1D, 0x10, 0x21, 0x79, 0x1A, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x91, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x22, 0x2A, 0x80, 0xA8, 0x1C, 0x08, 0x21, 0x79, 0x1A, 0x01, 0x23, 0x9E, 0x46, 0x8C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x03, 0xE0, 0x38, 0x20, 0x00, 0xE0, 0x00, 0x20, 0xC6, 0x43, 0x26, 0x60, 0x89, 0x48, 0x7C, 0x30, 0x20, 0x62, 0xFC, 0xBD, 0x30, 0xB5, 0x05, 0x1C, 0x28, 0x69, 0xA9, 0x69, 0x90, 0x29, 0x1D, 0xD1, 0x69, 0x69, 0x09, 0x78, 0x04, 0x29, 0x19, 0xD0, 0x05, 0x29, 0x17, 0xD0, 0x0A, 0x29, 0x15, 0xD0, 0x06, 0x29, 0x13, 0xD0, 0x0C, 0x29, 0x01, 0xDB, 0xFF, 0xFF, 0x8A, 0x71, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x0F, 0xD1, 0x01, 0x24, 0xA6, 0x46, 0x7D, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x7C, 0x48, 0x7D, 0x49, 0x00, 0x22, 0xA6, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x7C, 0x48 ,
-0xFF, 0x30, 0x5F, 0x30, 0x28, 0x62, 0x30, 0xBD, 0xF0, 0xB5, 0x89, 0xB0, 0x05, 0x90, 0x41, 0x69, 0x02, 0x69, 0x75, 0x48, 0x79, 0x4E, 0x82, 0x42, 0x3A, 0xD0, 0x04, 0x30, 0x82, 0x42, 0x25, 0xD0, 0x74, 0x4D, 0xAA, 0x42, 0x00, 0xD0, 0xCC, 0xE0, 0x08, 0x68, 0x06, 0x1C, 0x0C, 0x22, 0x8F, 0x1A, 0x4A, 0x68, 0x89, 0x18, 0x09, 0x1D, 0x10, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x09, 0xD1, 0xAC, 0x22, 0x72, 0x43, 0xCB, 0x48, 0x80, 0x18, 0x46, 0x22, 0x12, 0x5C, 0x11, 0x2A, 0x01, 0xD1, 0x44, 0x22, 0x14, 0x54, 0x28, 0x1C, 0x3A, 0x1C, 0xA6, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x69, 0x48, 0xEC, 0x30, 0xAB, 0xE0, 0x08, 0x68, 0xC0, 0x00, 0x30, 0x18, 0x8A, 0x68, 0x02, 0x2A, 0x02, 0xD0, 0xFF, 0xFF, 0x20, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xE7, 0x20, 0x80, 0x00, 0xA2, 0xE0, 0xCA, 0x68, 0x89, 0x18, 0x09, 0x7B, 0x41, 0x60, 0x80, 0x21, 0x01, 0x60, 0x3B, 0x20 ,
-0x00, 0x01, 0x99, 0xE0, 0x08, 0x68, 0x06, 0x90, 0xC0, 0x00, 0x34, 0x58, 0x10, 0x20, 0x04, 0x90, 0x01, 0x25, 0xAE, 0x46, 0x57, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x07, 0x90, 0x00, 0x28, 0x00, 0xD1, 0x89, 0xE0, 0x0C, 0x21, 0x07, 0x98, 0x0F, 0x18, 0xB0, 0x49, 0xAC, 0x20, 0x06, 0x9A, 0x50, 0x43, 0x08, 0x18, 0x48, 0x22, 0x13, 0x5C, 0x5B, 0x06, 0x5B, 0x0E, 0x13, 0x54, 0x06, 0x9A, 0xD2, 0x00, 0xB6, 0x18, 0x71, 0x68, 0x00, 0x29, 0x47, 0xD1, 0x00, 0x2C, 0x01, 0xDD, 0x08, 0x2C, 0x21, 0xDB, 0x00, 0x22, 0x69, 0x46, 0x0A, 0x70, 0x01, 0x92, 0x0A, 0x81, 0x8A, 0x72, 0xCD, 0x72, 0x0D, 0x73, 0x4D, 0x73, 0x01, 0x88, 0x44, 0x48, 0x06, 0x23, 0xAE, 0x46, 0x44, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x04, 0x1C, 0x02, 0xDC, 0x00, 0x20, 0xC0, 0x43, 0x36, 0xE0, 0x34, 0x60, 0xAC, 0x20, 0x60, 0x43, 0x9A, 0x49, 0xFF, 0xFF, 0xB6, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x18, 0x5C, 0x22, 0x28, 0x1C, 0x50, 0x54, 0x48, 0x20 ,
-0x42, 0x5C, 0x52, 0x06, 0x52, 0x0E, 0x42, 0x54, 0xAC, 0x20, 0x60, 0x43, 0x94, 0x49, 0x08, 0x18, 0x5C, 0x21, 0x09, 0x5C, 0x49, 0x1E, 0x02, 0x29, 0x16, 0xD9, 0x03, 0x39, 0x08, 0xD0, 0x00, 0x20, 0x30, 0x56, 0xAE, 0x46, 0xEA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x80, 0x20, 0x30, 0x60, 0xDB, 0xE7, 0x08, 0x94, 0x80, 0x21, 0x31, 0x60, 0x48, 0x22, 0x13, 0x5C, 0x19, 0x43, 0x11, 0x54, 0xAE, 0x46, 0xE4, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0xE0, 0x01, 0x20, 0xCE, 0xE7, 0x06, 0x98, 0x39, 0x1C, 0x04, 0xAA, 0xAE, 0x46, 0xE0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x1C, 0x08, 0x90, 0x06, 0x98, 0x38, 0x60, 0x08, 0x98, 0x78, 0x60, 0x00, 0x28, 0x15, 0xD0, 0xAC, 0x20, 0x60, 0x43, 0x7C, 0x49, 0x09, 0x18, 0x48, 0x88, 0x02, 0x04, 0x02, 0x20, 0x10, 0x43, 0xB8, 0x60, 0x48, 0x68, 0x02, 0x0E, 0x01, 0x02, 0x09, 0x0E, 0x09, 0x02, 0x11, 0x43, 0x02, 0x04, 0x12, 0x0E, 0xFF, 0xFF, 0x4C, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 ,
-0x12, 0x04, 0x0A, 0x43, 0x00, 0x06, 0x10, 0x43, 0xF8, 0x60, 0x07, 0x98, 0x0D, 0x49, 0x00, 0x22, 0x10, 0x23, 0xAE, 0x46, 0xCE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x13, 0x48, 0x00, 0xE0, 0x16, 0x20, 0xCC, 0x49, 0x09, 0x18, 0x05, 0x98, 0x01, 0x62, 0x09, 0xB0, 0xF0, 0xBD, 0x5D, 0x0D, 0x1B, 0x00, 0x81, 0xE7, 0x02, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x27, 0x1A, 0x02, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0xD5, 0xF4, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x91, 0x19, 0x02, 0x00, 0x50, 0x65, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0x50, 0x19, 0x1B, 0x00, 0x29, 0x16, 0x01, 0x00, 0x2A, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0x8B, 0xB0, 0x07, 0x90, 0x05, 0x69, 0x47, 0x69, 0x0C, 0x20, 0x38, 0x1A, 0x08, 0x90, 0xB6, 0x49, 0x8D, 0x42, 0x16, 0xD1, 0x78, 0x68, 0x0F, 0x30, 0x00, 0x11, 0x00, 0x01, 0x78, 0x60, 0x38, 0x68, 0x0B, 0x28, 0x0E, 0xD8, 0x00, 0x23, 0x68, 0x46 ,
-0xFF, 0xFF, 0xE2, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x03, 0x70, 0x08, 0x98, 0x05, 0x22, 0x01, 0x24, 0xA6, 0x46, 0xAE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0xAE, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xAC, 0x48, 0x85, 0x42, 0x23, 0xD1, 0xAC, 0x48, 0x02, 0x78, 0x6C, 0x46, 0x22, 0x72, 0x43, 0x78, 0x63, 0x72, 0x81, 0x78, 0xA1, 0x72, 0xC0, 0x78, 0xE0, 0x72, 0x00, 0x91, 0x01, 0x90, 0x03, 0x20, 0xA6, 0x49, 0x01, 0x39, 0x01, 0x26, 0xB6, 0x46, 0xF3, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x04, 0x20, 0x20, 0x70, 0x08, 0x98, 0x9F, 0x49, 0x00, 0x22, 0x02, 0xAB, 0x01, 0x24, 0xA6, 0x46, 0x9B, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x9A, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xEB, 0x49, 0x8D, 0x42, 0x14, 0xD1, 0x02, 0x22, 0x68, 0x46, 0x02, 0x70, 0x3A, 0x68, 0xAC, 0x20, 0x42, 0x43, 0x30, 0x48, 0x68, 0x30, 0x83, 0x18, 0x08, 0x98, 0x00, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x8F, 0x4C, 0xFE, 0x44 ,
-0x20, 0x47, 0x8E, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0xFF, 0xFF, 0x78, 0x74, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x08, 0x62, 0xEF, 0x48, 0x85, 0x42, 0x00, 0xD0, 0x04, 0xE1, 0x03, 0x20, 0x8C, 0x49, 0x01, 0x22, 0x96, 0x46, 0xEC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x86, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x09, 0x90, 0x38, 0x68, 0xEA, 0x4D, 0x00, 0x28, 0x00, 0xD1, 0xE2, 0xE0, 0x01, 0x24, 0xA6, 0x46, 0xE6, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x00, 0xD1, 0xD6, 0xE0, 0xE4, 0x48, 0x02, 0x68, 0x03, 0x20, 0x7F, 0x49, 0x01, 0x31, 0xA6, 0x46, 0xE2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xDF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x5A, 0xD1, 0xDF, 0x4D, 0x2E, 0x20, 0x41, 0x19, 0xB8, 0x68, 0x03, 0x30, 0x08, 0x70, 0x38, 0x7A, 0x48, 0x70, 0x2E, 0x1C, 0x30, 0x36, 0xB8, 0x68, 0x28, 0x18, 0x30, 0x30, 0xDA, 0x49, 0x0A, 0x68, 0x30, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xD8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18 ,
-0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xD9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x41, 0x19, 0x97, 0x22, 0xFF, 0xFF, 0x0E, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x30, 0x50, 0x54, 0xB8, 0x68, 0x46, 0x19, 0x9E, 0x36, 0x30, 0x70, 0x01, 0x36, 0xB8, 0x68, 0x01, 0xE0, 0x14, 0x0D, 0x1B, 0x00, 0x30, 0x18, 0xCA, 0x49, 0x0A, 0x68, 0x9E, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xC8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18, 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xC9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x40, 0x00, 0xC0, 0x49, 0x09, 0x68, 0x08, 0x18, 0x28, 0x18, 0xC0, 0x49, 0x0A, 0x79, 0x02, 0x70, 0x4A, 0x79, 0x42, 0x70, 0x8A, 0x79, 0x82, 0x70, 0xC9, 0x79, 0xC1, 0x70, 0x04, 0x30, 0x0F, 0x21, 0x41, 0x1A, 0x0A, 0x78, 0xBB, 0x68, 0x9A, 0x18, 0x0A, 0x70, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x0C, 0xB5, 0x49, 0x08, 0x60, 0xB1, 0x48, 0x04, 0x60, 0x02, 0x20, 0x01, 0x1C ,
-0x11, 0x22, 0xA6, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x63, 0xD4, 0x03, 0x20, 0xA6, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0x90, 0x00, 0x25, 0x01, 0x1C, 0xFF, 0xFF, 0xA4, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8D, 0x42, 0x50, 0xD0, 0x29, 0x1C, 0x2B, 0x22, 0xA6, 0x46, 0xAD, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0C, 0x20, 0x0A, 0x99, 0x40, 0x18, 0xAC, 0x22, 0x72, 0x43, 0xAB, 0x49, 0x8F, 0x18, 0x78, 0x63, 0x29, 0x1C, 0x18, 0x22, 0xA6, 0x46, 0xA6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x9F, 0x48, 0x02, 0x68, 0x79, 0x6B, 0x4A, 0x60, 0x0A, 0x98, 0xAC, 0x30, 0x08, 0x60, 0x08, 0x68, 0x9A, 0x49, 0xA6, 0x46, 0xA0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x29, 0x1C, 0x03, 0xA8, 0x10, 0x22, 0xA6, 0x46, 0x9C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE0, 0x21, 0x68, 0x46, 0x01, 0x74, 0x45, 0x74, 0x85, 0x74, 0xFB, 0x21, 0xC1, 0x74, 0xEE, 0x49, 0xC1, 0x81, 0x02, 0x21, 0x81, 0x81, 0x79, 0x6B, 0xCA, 0x68 ,
-0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0xC8, 0x60, 0x48, 0x68, 0x00, 0x90, 0x2A, 0x1C, 0x30, 0x1C, 0x0A, 0x9D, 0x29, 0x1C, 0x03, 0xAB, 0xA6, 0x46, 0xE6, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x07, 0x1C, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xEF, 0x49, 0xFF, 0xFF, 0x3A, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xFE, 0x44, 0x08, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0xEE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x11, 0xE0, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x20, 0xC7, 0x43, 0x08, 0xE0, 0x07, 0x1C, 0x06, 0xE0, 0x00, 0x20, 0x00, 0x21, 0xCF, 0x43, 0x01, 0xE0, 0x00, 0x20, 0x07, 0x1C, 0x28, 0x60, 0x00, 0x23, 0x68, 0x46, 0x03, 0x70, 0x3A, 0x06, 0x12, 0x0E, 0x08, 0x98, 0x6F, 0x49, 0x01, 0x24, 0xA6, 0x46, 0x09, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x07, 0x98, 0x09, 0x99, 0x01, 0x62, 0x0B, 0xB0, 0xF0, 0xBD, 0xC1, 0x18, 0x01, 0x00, 0xF1, 0x1B, 0x01, 0x00, 0xF3, 0x1C, 0x02, 0x00, 0x7B, 0xC0 ,
-0x02, 0x00, 0x91, 0xF0, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0xA3, 0xC0, 0x02, 0x00, 0xA9, 0xE9, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xAC, 0x05, 0x00, 0x00, 0xFE, 0xB5, 0x07, 0x1C, 0x7D, 0x69, 0xBE, 0x69, 0x0C, 0x20, 0x30, 0x1A, 0x01, 0x90, 0xDF, 0x4C, 0x0A, 0x2D, 0x13, 0xD1, 0xFF, 0xFF, 0xD0, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0x68, 0xDB, 0x49, 0x08, 0x60, 0x01, 0x20, 0x86, 0x46, 0xDA, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x0A, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xE6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x38, 0x62, 0x03, 0x2D, 0x79, 0xD1, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x02, 0x90, 0x70, 0x68, 0x00, 0x28, 0x0C, 0xD1, 0x00, 0x21, 0xCF, 0x48, 0x01, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x61, 0xD0, 0x01, 0x21, 0x8E, 0x46, 0xCD, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x5B, 0xE0, 0xCC, 0x48, 0xB1, 0x68, 0x01, 0x60 ,
-0xF1, 0x68, 0x41, 0x60, 0x31, 0x69, 0x81, 0x60, 0x71, 0x69, 0xC1, 0x60, 0xB1, 0x69, 0xC1, 0x63, 0xF1, 0x69, 0x01, 0x64, 0x31, 0x6A, 0xC1, 0x64, 0x01, 0x24, 0xA6, 0x46, 0xC5, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xA6, 0x46, 0xC4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x70, 0x68, 0x7D, 0x25, 0xED, 0x00, 0xA8, 0x42, 0x21, 0xD8, 0x01, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xFF, 0xFF, 0x66, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x1C, 0xE0, 0xB9, 0x48, 0x00, 0x23, 0x19, 0x1C, 0x59, 0x43, 0x3E, 0x22, 0x4A, 0x43, 0x82, 0x83, 0x02, 0x30, 0x01, 0x33, 0x10, 0x2B, 0xF6, 0xDB, 0xA6, 0x46, 0xB4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xB5, 0x48, 0x0D, 0xE0, 0xB5, 0x4D, 0x28, 0x1C, 0xA6, 0x46, 0xB2, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x04, 0xE0, 0xA6, 0x46, 0xAF, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x75, 0x68, 0xAE, 0x48, 0x05, 0x60, 0x05, 0x1C, 0xA7, 0x4E, 0x30, 0x68 ,
-0x00, 0x28, 0x06, 0xD1, 0xAD, 0x48, 0x00, 0x68, 0xA6, 0x46, 0xAC, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x60, 0x00, 0x94, 0x2B, 0x68, 0xAA, 0x49, 0xAB, 0x4A, 0xA6, 0x46, 0xAB, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0x9C, 0x48, 0x04, 0x60, 0x03, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xA7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x38, 0x62, 0xFE, 0xBD, 0xC0, 0x46, 0x13, 0x7F, 0x03, 0x00, 0x12, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x00, 0x20, 0x01, 0x24, 0xA6, 0x46, 0xA0, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9F, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x7D, 0x21, 0xC9, 0x00, 0xA6, 0x46, 0x9E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x9B, 0x49, 0x08, 0x18, 0x99, 0x49, 0x08, 0x80, 0x9B, 0x48, 0x0A, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x11, 0x10, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xB9, 0x90 ,
-0x00, 0x00, 0x6C, 0x64, 0x08, 0x00, 0xE7, 0x7E, 0x03, 0x00, 0x74, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0x6D, 0xC6, 0x03, 0x00, 0x08, 0x19, 0x1B, 0x00, 0x11, 0x18, 0x02, 0x00, 0xD1, 0x78, 0x02, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0xFE, 0xB5, 0x02, 0x90, 0x45, 0x69, 0x68, 0x46, 0x01, 0x21, 0x8E, 0x46, 0x89, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x89, 0x48, 0x04, 0x1C, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x00, 0x27, 0x3E, 0x1C, 0x20, 0x88, 0xFF, 0xFF, 0x92, 0x78, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x40, 0x08, 0x22, 0xD3, 0x20, 0x1D, 0x89, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x07, 0xD1, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x21, 0x88, 0x09, 0x04, 0x89, 0x16, 0x81, 0x42, 0x3D, 0xD0, 0x02, 0x20, 0x00, 0x5F, 0x00, 0x99, 0x08, 0x1A, 0x00, 0x04, 0x00, 0x14, 0x3C, 0x28, 0x03, 0xDD, 0x20, 0x88, 0x40, 0x10, 0x40, 0x00 ,
-0x20, 0x80, 0x78, 0x1C, 0x07, 0x06, 0x3F, 0x0E, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x2A, 0x34, 0x01, 0x36, 0x14, 0x2E, 0xD5, 0xDB, 0x00, 0x2A, 0x02, 0xD1, 0xAB, 0x20, 0x40, 0x00, 0x50, 0xE0, 0x00, 0x9B, 0x6D, 0x48, 0x14, 0x21, 0x00, 0x22, 0x04, 0x88, 0x64, 0x08, 0x03, 0xD3, 0x2A, 0x30, 0x01, 0x32, 0x01, 0x39, 0xF8, 0xD1, 0x12, 0x06, 0x12, 0x0E, 0x14, 0x2F, 0x16, 0xD1, 0x66, 0x48, 0x00, 0x88, 0x00, 0x06, 0x44, 0x16, 0x64, 0x49, 0x00, 0x22, 0x01, 0x20, 0x4E, 0x8D, 0x36, 0x06, 0x76, 0x16, 0xA6, 0x42, 0x02, 0xDD, 0x34, 0x1C, 0x02, 0x06, 0xFF, 0xFF, 0x28, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x2A, 0x31, 0x01, 0x30, 0x14, 0x28, 0xF3, 0xDB, 0x02, 0xE0, 0x32, 0x06, 0x12, 0x0E, 0x00, 0x9B, 0x2A, 0x20, 0x42, 0x43, 0x5A, 0x48, 0x11, 0x18, 0x0C, 0x88, 0x01, 0x20, 0x20, 0x43, 0x00, 0x04, 0x00, 0x0C, 0x08, 0x80, 0xFE, 0x24, 0xA0, 0x43, 0x14, 0x24, 0x64, 0x57, 0x64, 0x06, 0x24, 0x0E ,
-0x04, 0x43, 0x52, 0x48, 0x14, 0x52, 0x14, 0x18, 0x63, 0x80, 0x08, 0x88, 0x80, 0x05, 0x82, 0x0D, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x80, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x68, 0x02, 0x69, 0x20, 0x1D, 0x91, 0x1C, 0x52, 0x78, 0x01, 0x23, 0x9E, 0x46, 0x4B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x04, 0x61, 0xFE, 0x20, 0x47, 0x49, 0x09, 0x18, 0x02, 0x98, 0x01, 0x62, 0xFE, 0xBD, 0x82, 0x69, 0x41, 0x69, 0x03, 0x69, 0x02, 0x2B, 0x0A, 0xD1, 0x01, 0x2A, 0x01, 0xD1, 0x00, 0x29, 0x05, 0xD0, 0x02, 0x2A, 0x04, 0xD1, 0x00, 0x29, 0x02, 0xD1, 0x11, 0x21, 0x00, 0xE0, 0x06, 0x21, 0x41, 0x61, 0xF7, 0x46, 0xFF, 0xFF, 0xBE, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xC0, 0x46, 0x14, 0xE9, 0x00, 0x00, 0xC9, 0x18, 0x02, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x3A, 0x48, 0x00, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x01, 0x20, 0x86, 0x46, 0x38, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x01, 0x24, 0xA6, 0x46, 0x37, 0x48, 0xFE, 0x44 ,
-0x00, 0x47, 0xA6, 0x46, 0x36, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x35, 0x48, 0x0E, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x49, 0x19, 0x01, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x18, 0xB5, 0x43, 0x69, 0x81, 0x69, 0x31, 0x48, 0x81, 0x29, 0x00, 0xD1, 0x0B, 0x38, 0x00, 0x21, 0x00, 0x91, 0x1A, 0x68, 0x9B, 0x68, 0x01, 0x24, 0xA6, 0x46, 0x2D, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0x18, 0xB5, 0x40, 0x69, 0x00, 0x21, 0x00, 0x91, 0x02, 0x68, 0x83, 0x68, 0x27, 0x48, 0x01, 0x30, 0x01, 0x24, 0xA6, 0x46, 0x26, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0x19, 0x9E, 0x00, 0x00, 0xB9, 0xEC, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x80, 0x3F, 0x08, 0x00, 0xFF, 0xFF, 0x54, 0x7A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB7, 0x5D, 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0xD3, 0x8E, 0x00, 0x00, 0xF7, 0xC6, 0x00, 0x00, 0xE5, 0x90, 0x00, 0x00, 0x68, 0x64, 0x08, 0x00, 0xC0, 0x27, 0x09, 0x00, 0xA0, 0x3B ,
-0x08, 0x00, 0x3D, 0x5D, 0x03, 0x00, 0x19, 0xC6, 0x00, 0x00, 0xE8, 0x3A, 0x08, 0x00, 0x81, 0x5D, 0x03, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0x4B, 0x4F, 0x03, 0x00, 0x6B, 0xC0, 0x03, 0x00, 0x95, 0x1E, 0x01, 0x00, 0xDA, 0x40, 0x08, 0x00, 0xDC, 0x05, 0x00, 0x00, 0x55, 0xAA, 0x03, 0x00, 0x0D, 0x91, 0x00, 0x00, 0xD7, 0x56, 0x03, 0x00, 0x08, 0x51, 0x08, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x65, 0xB8, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x84, 0x17, 0x1B, 0x00, 0xB5, 0x86, 0x01, 0x00, 0x3D, 0x47, 0x02, 0x00, 0x73, 0x49, 0x02, 0x00, 0x5F, 0x90, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, 0xF7, 0xF6, 0x00, 0x00, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x76, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0xFF, 0xFF, 0xEA, 0x7A, 0x08, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5 ,
-0x68, 0x46, 0xFF, 0xF7, 0xB6, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x55, 0xFC, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x27, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xDD, 0xFA, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x68, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x3D, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xBE, 0xFD, 0xFF, 0xBD, 0x78, 0x7B, 0x08, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xF8, 0xF0, 0x43, 0xFA, 0x00, 0xBD, 0x35, 0x66, 0x08, 0x00, 0x67, 0x66, 0x08, 0x00, 0x71, 0x65, 0x08, 0x00, 0x4D, 0x66, 0x08, 0x00, 0x25, 0x64, 0x08, 0x00, 0x81, 0x66, 0x08, 0x00, 0x8D, 0x66, 0x08, 0x00, 0x99, 0x66, 0x08, 0x00, 0x87, 0x67, 0x08, 0x00, 0xA7, 0x67, 0x08, 0x00, 0xD1, 0x67, 0x08, 0x00, 0x1B, 0x68, 0x08, 0x00, 0x57, 0x68, 0x08, 0x00, 0x2D, 0x69, 0x08, 0x00, 0xB1, 0x6B, 0x08, 0x00, 0xD5, 0x6B, 0x08, 0x00, 0xF9, 0x6B ,
-0x08, 0x00, 0x15, 0x6C, 0x08, 0x00, 0xA1, 0x68, 0x08, 0x00, 0x59, 0x6C, 0x08, 0x00, 0xA7, 0x6D, 0x08, 0x00, 0xFF, 0x6D, 0x08, 0x00, 0x29, 0x6E, 0x08, 0x00, 0xF9, 0x6E, 0x08, 0x00, 0xD9, 0x6C, 0x08, 0x00, 0xA5, 0x6E, 0x08, 0x00, 0xCD, 0x6D, 0x08, 0x00, 0x81, 0x6F, 0x08, 0x00, 0x1D, 0x70, 0x08, 0x00, 0x31, 0x64, 0x08, 0x00, 0x39, 0x70, 0x08, 0x00, 0x3F, 0x70, 0x08, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x00, 0xB2, 0x4E, 0x01, 0x00, 0x5A, 0xC1, 0x00, 0x00, 0x96, 0x1A, 0x01, 0x00, 0x22, 0x0B, 0x02, 0x00, 0x60, 0xD0, 0x01, 0x00, 0x06, 0x1A, 0x00, 0x00, 0xB8, 0xC6, 0x01, 0x00, 0xD8, 0x42, 0x03, 0x00, 0x16, 0x42, 0x03, 0x00, 0xEE, 0xDB, 0x00, 0x00, 0x62, 0xDC, 0x00, 0x00, 0xC8, 0xE1, 0x00, 0x00, 0x8A, 0x17, 0x02, 0x00, 0x38, 0xBE, 0x00, 0x00, 0x26, 0xC6, 0x00, 0x00, 0x56, 0xC2, 0x00, 0x00, 0x62, 0x12, 0x03, 0x00, 0xE4, 0xF4, 0x01, 0x00, 0x3A, 0xEC, 0x00, 0x00, 0x5E, 0x92, 0x00, 0x00 ,
-0xFE, 0xE8, 0x02, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x64, 0xEC, 0x01, 0x00, 0xFE, 0x44, 0x03, 0x00, 0x1C, 0x94, 0x00, 0x00, 0xA8, 0x66, 0x03, 0x00, 0x74, 0xE9, 0x02, 0x00, 0x68, 0x1E, 0x01, 0x00, 0xBC, 0xDA, 0x00, 0x00, 0xEA, 0xE1, 0x00, 0x00, 0x24, 0xE9, 0x01, 0x00, 0x70, 0x79, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x1C, 0xF0, 0xB5, 0x88, 0xB0, 0xCA, 0x4C, 0x03, 0x20, 0x22, 0x78, 0x63, 0x78, 0xCA, 0x4E, 0x31, 0x1C, 0x01, 0x39, 0x01, 0x25, 0xAE, 0x46, 0xC7, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0xA2, 0x78, 0xE3, 0x78, 0x03, 0x20, 0x31, 0x1C, 0xAE, 0x46, 0xC3, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x03, 0x20, 0x31, 0x1C, 0x01, 0x31, 0xAE, 0x46, 0xC1, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xC1, 0x48, 0x21, 0x78, 0x01, 0x70, 0x61, 0x78, 0x41, 0x70, 0xE1, 0x78, 0xC1, 0x70, 0xA1, 0x78, 0x81, 0x70, 0xBF, 0x48, 0x04, 0x1C, 0x33, 0x3C, 0x20, 0x1C, 0x00, 0x21, 0xDC, 0x22, 0xAE, 0x46 ,
-0xBA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x84, 0x20, 0xA0, 0x70, 0x05, 0x27, 0xE7, 0x71, 0x0C, 0x26, 0x26, 0x73, 0x0D, 0x20, 0x00, 0x19, 0x98, 0xA1, 0x32, 0x1C, 0xAE, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20, 0x60, 0x76, 0x1A, 0x20, 0x00, 0x19, 0x97, 0xA1, 0x06, 0x91, 0x04, 0x22, 0xAE, 0x46, 0xAE, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xFF, 0xFF, 0x96, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA7, 0x77, 0x1F, 0x34, 0x95, 0xA1, 0x07, 0x91, 0x20, 0x1C, 0x3A, 0x1C, 0xAE, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x28, 0x1C, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0xC0, 0x25, 0x65, 0x74, 0xA6, 0x74, 0x09, 0x22, 0xE2, 0x74, 0xA3, 0x4C, 0x20, 0x1C, 0x8C, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9F, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x07, 0x22, 0x62, 0x72, 0x9E, 0x4C, 0x0A, 0x34, 0x20, 0x1C, 0x89, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20 ,
-0xE0, 0x71, 0x98, 0x4C, 0x12, 0x34, 0x20, 0x1C, 0x06, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x27, 0x71, 0x93, 0x4C, 0x17, 0x34, 0x20, 0x1C, 0x07, 0x99, 0x3A, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x8E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x01, 0x20, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0x02, 0x20, 0xE0, 0x73, 0x25, 0x74, 0x66, 0x74, 0xFF, 0xFF, 0x2C, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA5, 0x74, 0x2F, 0x27, 0xE7, 0x74, 0x10, 0x20, 0x60, 0x75, 0x80, 0x26, 0xA6, 0x75, 0x01, 0x20, 0xE0, 0x75, 0x11, 0x20, 0xA0, 0x76, 0x94, 0x20, 0xE0, 0x76, 0x24, 0x20, 0x60, 0x77, 0x0A, 0x22, 0xA2, 0x77, 0x80, 0x4C, 0x36, 0x34, 0x20, 0x1C, 0x6D, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x18, 0x22, 0xA2, 0x72, 0x7A, 0x4C, 0x41, 0x34, 0x20, 0x1C, 0x6B, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x76, 0x4B, 0xFE, 0x44, 0x18, 0x47 ,
-0x25, 0x76, 0x67, 0x76, 0x21, 0x20, 0xE0, 0x76, 0x26, 0x77, 0x01, 0x20, 0x60, 0x77, 0x72, 0x48, 0x61, 0x30, 0x11, 0x21, 0x01, 0x70, 0x94, 0x21, 0x41, 0x70, 0x04, 0x21, 0x01, 0x72, 0xD2, 0x21, 0x41, 0x72, 0xC5, 0x72, 0x1E, 0x21, 0x01, 0x73, 0x45, 0x73, 0x9E, 0x21, 0x81, 0x73, 0x01, 0x21, 0x01, 0x74, 0x46, 0x74, 0x81, 0x74, 0x11, 0x21, 0x41, 0x75, 0x94, 0x21, 0x81, 0x75, 0x04, 0x21, 0x01, 0x76, 0xAD, 0x20, 0x66, 0x49, 0x08, 0x60, 0x00, 0x24, 0x0F, 0x25, 0xFF, 0xFF, 0xC2, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x29, 0x06, 0x09, 0x0E, 0x00, 0x20, 0x6A, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x6B, 0x46, 0x18, 0x88, 0x40, 0x08, 0x0E, 0xD3, 0xA0, 0x00, 0x0F, 0x21, 0xCA, 0x43, 0x69, 0x46, 0x0E, 0x88, 0x16, 0x40, 0x01, 0xAF, 0x3E, 0x52, 0x49, 0x88, 0x11, 0x40, 0x68, 0x44, 0xC1, 0x80, 0x60, 0x1C, 0x04, 0x04, 0x24, 0x0C, 0x01, 0x3D, 0x0B, 0x2D, 0xE0, 0xDA, 0x60, 0x1E ,
-0x00, 0x04, 0x00, 0x0C, 0x1D, 0xD0, 0x86, 0x46, 0x01, 0x1C, 0x01, 0xAD, 0x01, 0x22, 0xAE, 0x88, 0x90, 0x00, 0xC7, 0x5A, 0xB7, 0x42, 0x0A, 0xDA, 0xBC, 0x46, 0x07, 0x1C, 0x6F, 0x44, 0x7F, 0x88, 0x68, 0x44, 0x06, 0x80, 0xEE, 0x88, 0x46, 0x80, 0x60, 0x46, 0xA8, 0x80, 0xEF, 0x80, 0x04, 0x35, 0x50, 0x1C, 0x02, 0x04, 0x12, 0x0C, 0x01, 0x39, 0xE9, 0xD1, 0x70, 0x46, 0x01, 0x38, 0x86, 0x46, 0xE2, 0xD1, 0x99, 0x88, 0x68, 0x46, 0xC0, 0x88, 0x40, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x42, 0x4B, 0x18, 0x80, 0x42, 0x49, 0x08, 0x1A, 0xFF, 0xFF, 0x58, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x58, 0x80, 0x02, 0x2C, 0x1E, 0xDB, 0x65, 0x1E, 0x01, 0xAA, 0x01, 0x20, 0x01, 0x1C, 0x8C, 0x00, 0x6B, 0x46, 0xE6, 0x5A, 0x93, 0x88, 0xD4, 0x88, 0xE7, 0x18, 0xB7, 0x42, 0x0C, 0xDA, 0x06, 0x24, 0x44, 0x43, 0x38, 0x4B, 0x1B, 0x19, 0x1F, 0x80, 0x1C, 0x88, 0x34, 0x1B, 0x5C, 0x80, 0x01, 0x24, 0x1C, 0x71, 0x40, 0x1C, 0x00, 0x04 ,
-0x00, 0x0C, 0x04, 0x32, 0x49, 0x1C, 0x09, 0x06, 0x09, 0x0E, 0x01, 0x3D, 0xE4, 0xD1, 0x00, 0x24, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x01, 0x20, 0x86, 0x46, 0x30, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x2F, 0x49, 0x22, 0x1C, 0x08, 0x68, 0x00, 0x28, 0x02, 0xD0, 0x01, 0x20, 0x90, 0x40, 0x04, 0x43, 0x04, 0x31, 0x01, 0x32, 0x20, 0x2A, 0xF5, 0xD3, 0x2A, 0x48, 0x04, 0x60, 0x08, 0xB0, 0xF0, 0xBD, 0x5F, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0xC0, 0x46, 0xC0, 0x5F, 0x75, 0x64, 0x70, 0x00, 0xC0, 0xFF, 0xFF, 0xEE, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x46, 0xC0, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0xC0, 0x46, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0xC0, 0x46, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x00, 0x64, 0x65, 0x76, 0x3D, 0x43, 0x43, 0x33, 0x30, 0x30, 0x30, 0x00, 0xC0, 0x76, 0x65 ,
-0x6E, 0x64, 0x6F, 0x72, 0x3D, 0x54, 0x65, 0x78, 0x61, 0x73, 0x2D, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x00, 0xC0, 0x46, 0xC0, 0x00, 0x00, 0x18, 0x00, 0xF3, 0x7E, 0x03, 0x00, 0xC6, 0x05, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0xA7, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0x48, 0x32, 0x08, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0x81, 0x03, 0x18, 0x00, 0x80, 0x7B, 0x08, 0x00, 0x84, 0xF3, 0x1A, 0x00, 0x0D, 0x49, 0x0E, 0x48, 0xFF, 0xFF, 0x84, 0x03, 0x18, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x88, 0x67, 0x0E, 0x48, 0x88, 0x64, 0x0E, 0x48, 0x48, 0x64, 0x0E, 0x48, 0xC8, 0x64, 0x0E, 0x48, 0x08, 0x65, 0x11, 0x48, 0x02, 0x1C, 0x04, 0x32, 0x0C, 0x4B, 0x13, 0x60, 0x0C, 0x4B, 0x93, 0x62, 0x0C, 0x4A ,
-0x8A, 0x66, 0x0D, 0x49, 0x01, 0x60, 0x0D, 0x48, 0x0E, 0x49, 0x01, 0x60, 0x0E, 0x49, 0x41, 0x60, 0xF7, 0x46, 0x1C, 0x21, 0x08, 0x00, 0x1B, 0x7B, 0x08, 0x00, 0x11, 0x7B, 0x08, 0x00, 0x07, 0x7B, 0x08, 0x00, 0x39, 0x7B, 0x08, 0x00, 0x2F, 0x7B, 0x08, 0x00, 0x25, 0x7B, 0x08, 0x00, 0xFD, 0x7A, 0x08, 0x00, 0xDF, 0x7A, 0x08, 0x00, 0x50, 0x23, 0x08, 0x00, 0xD5, 0x7A, 0x08, 0x00, 0x58, 0x26, 0x08, 0x00, 0xF3, 0x7A, 0x08, 0x00, 0xE9, 0x7A, 0x08, 0x00 };
-
-
-const unsigned char cRMdefaultParams[128] = { 0x03, 0x00, 0x01, 0x01, 0x14, 0x14, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x01, 0x77, 0x80, 0x1D, 0x1F, 0x22, 0x26, 0x28, 0x29, 0x1A, 0x1F, 0x22, 0x24, 0x26, 0x28, 0x16, 0x1D, 0x1E, 0x20, 0x24, 0x25, 0x1E, 0x2D, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x15, 0x15, 0x15, 0x11, 0x15, 0x15, 0x0E, 0x00};
-
-//
-//Service Pack version P1.13.7.15.15 - FW patches
-//
-const unsigned char fw_patch[5700] = { 0x00, 0x01, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x25, 0xF0, 0x95, 0xFB, 0xE0, 0x6B, 0xD0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x38, 0xFB, 0x2C, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x0A, 0xFB, 0x04, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB8, 0xF1, 0x90, 0x0F, 0xA4, 0x16, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x66, 0xE0, 0x04, 0xA8, 0x35, 0x1D, 0x21, 0xF0, 0x99, 0xFC, 0x68, 0x46, 0x23, 0xF0, 0x28, 0xFB, 0x9A, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x07, 0xD1, 0x28, 0x46, 0x05, 0xF0, 0xC3, 0xFE, 0x01, 0x46, 0x01, 0xAA, 0x00, 0x20, 0x21, 0xF0, 0x50, 0xF9, 0x28, 0x46, 0x05, 0xF0, 0xBB, 0xFE, 0x01, 0xA9, 0x21, 0xF0, 0x2A, 0xFA, 0xE9, 0x79, 0x4F, 0xEA, 0xE0, 0x00, 0x40, 0xB2, 0x11, 0xB1, 0x00, 0xF1, 0x06, 0x00, 0x40, 0xB2, 0xA8, 0x71, 0x1F, 0x38, 0x40, 0x00, 0xE8, 0x71, 0x30, 0x46 ,
-0x01, 0xF0, 0x0D, 0xFF, 0x10, 0xF1, 0x00, 0x09, 0x4F, 0xF0, 0x00, 0x01, 0x09, 0xD0, 0x28, 0x68, 0x40, 0x0C, 0x09, 0xD3, 0xE8, 0x68, 0xC0, 0x0B, 0x03, 0xD2, 0x48, 0x46, 0xFF, 0xF7, 0xDD, 0xFE, 0x01, 0x21, 0x28, 0x68, 0x40, 0x0C, 0x0A, 0xD2, 0x38, 0x68, 0x40, 0x1C, 0x38, 0x60, 0x20, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0x20, 0x60, 0x22, 0x68, 0x38, 0x68, 0x10, 0x43, 0x20, 0x60, 0xE8, 0x68, 0xC0, 0x0B, 0x0F, 0xD3, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0xC8, 0xF8, 0x00, 0x00, 0x20, 0x68, 0x6F, 0xF3, 0x1F, 0x40, 0x20, 0x60, 0xD8, 0xF8, 0x00, 0x20, 0x20, 0x68, 0x40, 0xEA, 0x02, 0x40, 0x20, 0x60, 0x49, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x03, 0xD1, 0x30, 0x46, 0x07, 0xF0, 0xBE, 0xF9, 0x02, 0xE0, 0x48, 0x46, 0x07, 0xF0, 0x06, 0xFA, 0x6C, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x46, 0x0E, 0xF0, 0x85, 0xFB, 0x00, 0x9E, 0x00, 0x2E, 0x96, 0xD1, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46 ,
-0x9C, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0xF0, 0x2A, 0xFE, 0x74, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x21, 0x21, 0xF0, 0x41, 0xFA, 0x20, 0x68, 0x18, 0x4B, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x1C, 0xF9, 0x0A, 0xE0, 0x20, 0x68, 0x00, 0x68, 0x0C, 0x21, 0x40, 0xF0, 0x20, 0x00, 0x21, 0xF0, 0x14, 0xF9, 0x10, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x20, 0xF0, 0x97, 0xF9, 0x01, 0x98, 0x5C, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x20, 0xF0, 0x71, 0xF9, 0x03, 0x98, 0x00, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x20, 0xF9, 0x1C, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x12, 0xF9, 0x54, 0x58, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xA8, 0x20, 0xF0, 0xF5, 0xF8, 0x04, 0xAB, 0x04, 0x62, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x79, 0x1F, 0xF0, 0x1B, 0xFD, 0x69, 0xE0, 0x60, 0x93, 0x00, 0x00, 0x40, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA6, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x39, 0xFB, 0x28, 0x46, 0x90, 0xA8, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x69, 0xF9, 0x1E, 0x48, 0x34, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x68, 0xFF, 0x29, 0x98, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD4, 0x21, 0xD4, 0xB2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xD0, 0x1A, 0xF0, 0x47, 0xFC, 0x20, 0x98, 0xAC, 0xC5, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0xF0 ,
-0xDB, 0xFA, 0x09, 0x49, 0x28, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0xF0, 0x9E, 0xFA, 0xDC, 0xD3, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x18, 0xF0, 0xAB, 0xFC, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xDF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0xF0, 0xA8, 0xFD, 0xCC, 0xEB, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x78, 0x17, 0xF0, 0x77, 0xF8, 0x38, 0x78, 0x16, 0xF0, 0xF0, 0xFF, 0xA8, 0xF7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x49, 0x09, 0x68, 0x23, 0x22, 0x41, 0x61, 0xC8, 0xF7, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x31, 0x39, 0x2E, 0x33, 0x31, 0x34, 0x5F, 0x4E, 0x65, 0x77, 0x5F, 0x43, 0x43, 0x41, 0x5F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 0xC0, 0x74, 0x56, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xF9, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x16, 0xF0, 0x79, 0xF8 ,
-0x12, 0xE0, 0x38, 0xFA, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x16, 0xF0, 0x03, 0xF8, 0x32, 0x20, 0x94, 0xFB, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0C, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x14, 0xF0, 0x05, 0xFF, 0x01, 0xF0, 0x10, 0x1B, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x46, 0xBF, 0x18, 0x30, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x30, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0xF0, 0xD8, 0xFC, 0x9C, 0x31, 0x01, 0x00, 0x08, 0x00 ,
-0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x51, 0xFC, 0xFE, 0xF7, 0xF0, 0x35, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x27, 0xFA, 0xFE, 0xF7, 0xF0, 0x3D, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA9, 0x11, 0xF0, 0x27, 0xFE, 0x20, 0x6F, 0xD0, 0x62, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xB8, 0xFB, 0x80, 0x7E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDF, 0xF8, 0x58, 0x82, 0xE0, 0x7E, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x6A, 0xFE, 0x0B, 0xF0, 0x9A, 0xF9, 0x03, 0x20, 0xA8, 0xF5, 0x88, 0x71, 0x08, 0x60, 0xF2, 0xF7, 0x16, 0xF9, 0x7A, 0x48, 0x6B, 0x49, 0x9C, 0x7F, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x51, 0x4D, 0xC4, 0x7F, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0xF1, 0x52, 0x00, 0x3A, 0x4A, 0xA8, 0x81, 0x28, 0x83, 0xE8, 0x83, 0xE8, 0x84, 0xA8, 0x85, 0x2A, 0x60, 0x39, 0x48, 0x41, 0xF2, 0x11, 0x12, 0x2A, 0x85, 0x18, 0x90, 0x19, 0x91 ,
-0x39, 0x49, 0x1A, 0x91, 0x39, 0x49, 0x1B, 0x91, 0x39, 0x49, 0x20, 0x46, 0xDF, 0xF8, 0xC4, 0x90, 0x1C, 0x91, 0x38, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x31, 0x4E, 0x1D, 0x91, 0x48, 0x80, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x7C, 0xFA, 0xB4, 0x80, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x12, 0x66, 0x09, 0x84, 0x6B, 0x00, 0x20, 0x94, 0x70, 0x00, 0x20, 0xB4, 0x70, 0x00, 0x20, 0xC4, 0x78, 0x00, 0x20, 0x50, 0x7A, 0x00, 0x20, 0xFE, 0xFF, 0x03, 0x00, 0xA4, 0x70, 0x00, 0x20, 0xB0, 0x70, 0x00, 0x20, 0xB8, 0x70, 0x00, 0x20, 0x60, 0x55, 0x30, 0x80, 0x3C, 0x5C, 0x00, 0x20, 0x04, 0x74, 0x00, 0x20, 0xB8, 0xE4, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x78, 0x07, 0xF0, 0x01, 0xFC, 0x20, 0x78, 0x07, 0xF0, 0x7A, 0xFB, 0x04, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF1, 0x8C, 0x0D, 0x04, 0x68, 0x0F, 0x30, 0x03, 0x94, 0xFE, 0xF7, 0xDB, 0xFA, 0x04, 0xF1, 0x14, 0x00 ,
-0x04, 0x90, 0x21, 0x7D, 0x00, 0x20, 0x21, 0xF0, 0x73, 0x01, 0x88, 0x29, 0x08, 0xBF, 0x01, 0x20, 0x05, 0x90, 0x03, 0x98, 0x00, 0x1D, 0x06, 0x90, 0x5D, 0x48, 0x00, 0x68, 0x01, 0x28, 0x40, 0xF0, 0xFA, 0x83, 0x5B, 0x4D, 0x5C, 0x48, 0xDF, 0xF8, 0x70, 0x91, 0x29, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0xDF, 0xF8, 0x74, 0xA1, 0x88, 0x42, 0x21, 0xD1, 0x10, 0x22, 0x00, 0x21, 0x48, 0x46, 0x4F, 0x46, 0xFB, 0xF7, 0xB7, 0xFE, 0x10, 0x22, 0x00, 0x21, 0x40, 0x46, 0xFB, 0xF7, 0xB2, 0xFE, 0x54, 0x49, 0x08, 0x68, 0x40, 0xF4, 0x80, 0x10, 0x08, 0x60, 0x01, 0x20, 0x51, 0x46, 0x08, 0x60, 0x00, 0x21, 0x29, 0x60, 0x39, 0x78, 0x46, 0x46, 0x00, 0x91, 0x31, 0x78, 0x41, 0xF2, 0x11, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x41, 0xFC, 0x51, 0x46, 0x07, 0x91, 0x08, 0x68, 0x56, 0x49, 0xDF, 0xF8, 0x5C, 0xB1, 0x01, 0x28, 0x08, 0x91, 0x56, 0x49, 0xDF, 0xF8, 0x48, 0xA1, 0x09, 0x91, 0x55, 0x49 ,
-0x0A, 0x91, 0x44, 0x49, 0x0B, 0x91, 0x44, 0x49, 0x0C, 0x91, 0x44, 0x49, 0x0D, 0x91, 0x44, 0x49, 0x0E, 0x91, 0x44, 0x49, 0x0F, 0x91, 0x44, 0x49, 0x10, 0x91, 0x44, 0x49, 0xCC, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x11, 0x91, 0x44, 0x49, 0x12, 0x91, 0x44, 0x49, 0x13, 0x91, 0x44, 0x49, 0x14, 0x91, 0x44, 0x49, 0x15, 0x91, 0x44, 0x49, 0x16, 0x91, 0x9F, 0x49, 0x17, 0x91, 0x9F, 0x49, 0x18, 0x91, 0x9F, 0x49, 0x19, 0x91, 0x9F, 0x49, 0x1A, 0x91, 0x9F, 0x49, 0x1B, 0x91, 0x9F, 0x49, 0x1C, 0x91, 0x9F, 0x49, 0x1D, 0x91, 0x9F, 0x49, 0x1E, 0x91, 0x9F, 0x49, 0x1F, 0x91, 0x40, 0xF0, 0x00, 0x81, 0x04, 0x98, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF9, 0x80, 0x04, 0x99, 0x09, 0x78, 0x01, 0xF0, 0x0C, 0x01, 0x08, 0x29, 0x40, 0xF0, 0xF2, 0x80, 0x06, 0x99, 0x09, 0x88, 0xA1, 0xF1, 0x3C, 0x01, 0x0E, 0xB2, 0x05, 0x99, 0x11, 0xB1, 0xA6, 0xF1, 0x02, 0x06, 0x36, 0xB2, 0xC0, 0x09, 0x4F, 0xF0 ,
-0x00, 0x07, 0x15, 0xD3, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x10, 0xD0, 0x17, 0x2E, 0x0E, 0xD0, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x08, 0xD0, 0x17, 0x2E, 0x06, 0xD0, 0x36, 0x1F, 0x36, 0xB2, 0x03, 0x2E, 0x14, 0xBF, 0x17, 0x2E, 0x02, 0x27, 0x02, 0xE0, 0x03, 0x27, 0x00, 0xE0, 0x01, 0x27, 0x03, 0x2E, 0x18, 0xBF, 0x17, 0x2E, 0x04, 0x9A, 0x40, 0xF0, 0xC8, 0x80, 0x0A, 0x32, 0x12, 0xF8, 0x01, 0x1B, 0x05, 0x24, 0x12, 0xF8, 0x01, 0x3B, 0x4B, 0x40, 0x64, 0x1E, 0xD9, 0xB2, 0xF9, 0xD1, 0x81, 0xEA, 0x21, 0x11, 0x03, 0x2E, 0x94, 0x4E, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x01, 0x48, 0x46, 0x35, 0xD0, 0x43, 0x46, 0xCA, 0x5C, 0x52, 0x1C, 0xCA, 0x54, 0x0C, 0x18, 0x33, 0xE0, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0xC8, 0x48, 0x30, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x88, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00 ,
-0x18, 0x58, 0x02, 0x00, 0x20, 0x58, 0x02, 0x00, 0x28, 0x58, 0x02, 0x00, 0x30, 0x58, 0x02, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58, 0x02, 0x00, 0xE4, 0x58, 0x02, 0x00, 0xE2, 0x58, 0x02, 0x00, 0x14, 0x58, 0x02, 0x00, 0xEF, 0x58, 0x02, 0x00, 0xE0, 0x58, 0x02, 0x00, 0xEE, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x0C, 0x18, 0x20, 0x78, 0x40, 0x1C, 0x20, 0x70, 0x20, 0x78, 0x43, 0x46, 0x03, 0xEB, 0x01, 0x08, 0x0A, 0x28, 0x76, 0xDB, 0x98, 0xF8, 0x00, 0x00, 0x0A, 0x28, 0x72, 0xDB, 0x94, 0x48, 0x00, 0x25, 0x01, 0x60, 0x04, 0x98, 0x00, 0xF1, 0x0A, 0x09, 0x40, 0x78, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x04, 0xD2, 0x80, 0x08, 0x2E, 0xBF, 0x49, 0x46, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0x06, 0x22, 0xFA, 0xF7, 0xB9, 0xFC, 0x0C, 0x98, 0x06, 0x22, 0x49, 0x46, 0xFA, 0xF7, 0xB4, 0xFC, 0x9B, 0x48, 0x9A, 0x49, 0x5C, 0x4F, 0x02, 0x00, 0xC8, 0x00 ,
-0x00, 0x00, 0x00, 0x78, 0x08, 0x22, 0x08, 0x60, 0x58, 0x46, 0x07, 0x60, 0x0D, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAF, 0xFD, 0x08, 0x22, 0x0E, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAA, 0xFD, 0x08, 0x22, 0x0F, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA5, 0xFD, 0x08, 0x22, 0x10, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, 0x08, 0x22, 0x11, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x9B, 0xFD, 0x08, 0x22, 0x12, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x96, 0xFD, 0x07, 0x99, 0x02, 0x20, 0x08, 0x60, 0x13, 0x99, 0x28, 0x46, 0x08, 0x80, 0x08, 0x99, 0x08, 0x70, 0x14, 0x99, 0x08, 0x70, 0x15, 0x99, 0x08, 0x60, 0x16, 0x99, 0x08, 0x70, 0x17, 0x99, 0x08, 0x60, 0x18, 0x99, 0x08, 0x60, 0x19, 0x99, 0x08, 0x60, 0x09, 0x99, 0x08, 0x80, 0x0A, 0x99, 0x08, 0x80, 0x1A, 0x99, 0x08, 0x80, 0x7D, 0x49, 0x0D, 0x60, 0x1B, 0x99, 0x08, 0x70, 0x1C, 0x99, 0x08, 0x70, 0x1D, 0x99, 0x08, 0x70, 0x1E, 0x99, 0x08, 0x80, 0x1F, 0x99, 0x08, 0x80, 0x51, 0x46, 0x08, 0x80 ,
-0x20, 0x78, 0x00, 0x96, 0x04, 0x22, 0x01, 0x90, 0x98, 0xF8, 0x00, 0x00, 0x41, 0xF2, 0x14, 0x13, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x07, 0xFB, 0x07, 0x98, 0xA2, 0x49, 0x00, 0x68, 0x20, 0x91, 0xA2, 0x49, 0x05, 0x28, 0x21, 0x91, 0x9E, 0x49, 0x22, 0x91, 0x40, 0xF0, 0x37, 0x82, 0x04, 0x98, 0x40, 0x78, 0x24, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x05, 0xD2, 0x80, 0x08, 0x27, 0xBF, 0x04, 0x99, 0x0A, 0x31, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0xF8, 0xF7, 0x2D, 0xFC, 0x01, 0x28, 0x04, 0x98, 0x40, 0xF0, 0x23, 0x82, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x00, 0x03, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x07, 0xBF, 0x04, 0x99, 0x10, 0x31, 0x04, 0x99, 0x0A, 0x31, 0x13, 0xE0, 0x48, 0x58, 0x02, 0x00, 0x4C, 0x58, 0x02, 0x00, 0x50, 0x58, 0x02, 0x00, 0xF0, 0x58, 0x02, 0x00, 0xF2, 0x58, 0x02, 0x00, 0xF3, 0x58, 0x02, 0x00, 0xF4, 0x58, 0x02, 0x00, 0xEA, 0x58 ,
-0x02, 0x00, 0xEC, 0x58, 0x02, 0x00, 0x04, 0x99, 0x18, 0x31, 0x0C, 0x98, 0xF8, 0xF7, 0x06, 0xFC, 0x04, 0x99, 0x01, 0x28, 0x40, 0xF0, 0xFC, 0x81, 0x49, 0x78, 0x01, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF6, 0x81, 0x59, 0x46, 0x09, 0x68, 0x04, 0x9A, 0x8E, 0x46, 0x51, 0x46, 0xD2, 0x8A, 0x0B, 0x88, 0x12, 0x11, 0x93, 0x42, 0x00, 0xF0, 0x37, 0x82, 0x0A, 0x80, 0x06, 0x99, 0x09, 0x88, 0x3C, 0x39, 0x0B, 0xB2, 0x71, 0x46, 0x49, 0x1E, 0x09, 0xD0, 0x49, 0x1E, 0x04, 0xD0, 0x49, 0x1E, 0x08, 0xD1, 0xA3, 0xF1, 0x10, 0x03, 0x04, 0xE0, 0xA3, 0xF1, 0x14, 0x03, 0x01, 0xE0, 0xA3, 0xF1, 0x08, 0x03, 0x1B, 0xB2, 0x05, 0x98, 0x10, 0xB1, 0xA3, 0xF1, 0x02, 0x03, 0x1B, 0xB2, 0xEC, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0xF1, 0xCE, 0x81, 0x16, 0x98, 0x40, 0xF2, 0x77, 0x51, 0x99, 0x42, 0x0B, 0x90, 0x14, 0x98, 0x05, 0x90, 0x00, 0xF0, 0xA3, 0x81, 0x08, 0x46, 0x00, 0xF1, 0x3C, 0x00, 0x98, 0x42 ,
-0x05, 0x9A, 0x00, 0xF0, 0x9A, 0x81, 0xDF, 0xF8, 0x48, 0x82, 0x14, 0x78, 0x0B, 0x9A, 0xBB, 0x2C, 0x12, 0x78, 0x0C, 0x92, 0x63, 0xD1, 0xDD, 0xF8, 0x68, 0xC0, 0xBC, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x18, 0xBF, 0x90, 0x42, 0x5B, 0xD1, 0x1C, 0x2B, 0x4F, 0xF0, 0x00, 0x00, 0xC0, 0xF2, 0x82, 0x81, 0x3D, 0x2B, 0x13, 0x9D, 0x80, 0xF2, 0x7E, 0x81, 0xA3, 0xF1, 0x1C, 0x01, 0x09, 0xB2, 0x29, 0x80, 0x1E, 0x9A, 0xDD, 0xF8, 0x30, 0x90, 0xB2, 0xF9, 0x00, 0x60, 0xB9, 0xF1, 0x01, 0x0F, 0x15, 0xD1, 0xDD, 0xF8, 0x24, 0x90, 0x03, 0x2E, 0x0D, 0xDA, 0xB9, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x07, 0xD0, 0x01, 0x26, 0x16, 0x80, 0x4A, 0x46, 0x0E, 0x46, 0x03, 0xE0, 0xC0, 0x46, 0x90, 0x57, 0x02, 0x00, 0x76, 0x1C, 0x16, 0x80, 0x1B, 0x9A, 0x16, 0x78, 0x1D, 0x9A, 0x16, 0x70, 0x0C, 0x9A, 0x1F, 0x9E, 0x02, 0x2A, 0x28, 0xD1, 0xB6, 0xF9, 0x00, 0x20, 0xBE, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x03, 0x2A, 0x35, 0x46, 0x0B, 0xDA, 0x0A, 0x9E ,
-0xB6, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x04, 0xD0, 0x01, 0x22, 0x2A, 0x80, 0x0A, 0x46, 0x35, 0x46, 0x00, 0xE0, 0xB4, 0x51, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x52, 0x1C, 0x2A, 0x80, 0x1C, 0x99, 0x0A, 0x78, 0x1D, 0x99, 0x0A, 0x70, 0x0F, 0xE0, 0xC0, 0x46, 0x58, 0x57, 0x02, 0x00, 0xA6, 0x64, 0x00, 0x20, 0x54, 0x57, 0x02, 0x00, 0x28, 0x80, 0x05, 0x99, 0x08, 0x70, 0x08, 0x9A, 0x11, 0x78, 0x41, 0xF0, 0x04, 0x01, 0x11, 0x70, 0x04, 0x46, 0x45, 0x46, 0xAC, 0xF8, 0x00, 0x00, 0x28, 0x70, 0xCC, 0x2C, 0x09, 0x9A, 0x40, 0xF0, 0x00, 0x81, 0xDD, 0xF8, 0x7C, 0xC0, 0x0A, 0x99, 0x1E, 0x9F, 0x45, 0x46, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x00, 0x90, 0x28, 0x78, 0xCD, 0xF8, 0x50, 0xC0, 0x16, 0x91, 0x0A, 0x97, 0x13, 0x92, 0x09, 0x95, 0x0C, 0x99, 0x01, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x49, 0x0F, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0x0C, 0x99, 0x02, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x46, 0x0F ,
-0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0xB3, 0xF5, 0x14, 0x7F, 0x40, 0xF3, 0xBA, 0x80, 0x40, 0xF2, 0x51, 0x31, 0x99, 0x42, 0x08, 0x99, 0x40, 0xF3, 0xB4, 0x80, 0x09, 0x78, 0x06, 0x29, 0x00, 0xF0, 0xB0, 0x80, 0xA3, 0xF2, 0x51, 0x21, 0x0B, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x4F, 0xEA, 0x21, 0x11, 0xCA, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x15, 0x9D, 0x21, 0xF0, 0x0F, 0x01, 0xA3, 0xEB, 0x01, 0x03, 0x1D, 0x99, 0x2E, 0x68, 0x7C, 0x52, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0xE0, 0x5F, 0xFA, 0x83, 0xF8, 0x60, 0xB1, 0x31, 0x18, 0x11, 0xF8, 0x01, 0x1C, 0x51, 0x40, 0xCB, 0xB2, 0x07, 0xE0, 0xC0, 0x46, 0x58, 0x58, 0x02, 0x00, 0x54, 0x58, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0x13, 0x46, 0x19, 0x99, 0xDD, 0xF8, 0x6C, 0xA0, 0xDD, 0xF8, 0x70, 0xB0, 0xD1, 0xF8, 0x00, 0xC0, 0x00, 0xF0, 0x0F, 0x01, 0x99, 0x42, 0x22, 0xD0, 0x0A, 0x9B, 0x86, 0x45, 0x9A, 0xF8 ,
-0x00, 0x10, 0xB3, 0xF9, 0x00, 0x30, 0x9B, 0xF8, 0x00, 0x50, 0x15, 0xDD, 0x37, 0x5C, 0x44, 0x1C, 0x82, 0xEA, 0x07, 0x0C, 0x04, 0xF0, 0x0F, 0x07, 0x67, 0x45, 0x0B, 0xD0, 0xA6, 0x45, 0x06, 0x44, 0x0A, 0xDD, 0x76, 0x78, 0x72, 0x40, 0x86, 0x1C, 0x06, 0xF0, 0x0F, 0x06, 0x96, 0x42, 0x03, 0xD1, 0xC0, 0x1C, 0x4D, 0xE0, 0x80, 0x1C, 0x4B, 0xE0, 0x05, 0x9E, 0x00, 0x22, 0x32, 0x70, 0x4A, 0xE0, 0x00, 0xF0, 0x1F, 0x01, 0x01, 0x22, 0x8A, 0x40, 0x17, 0x99, 0xC4, 0x10, 0x0B, 0x68, 0x24, 0xF0, 0x03, 0x01, 0x5C, 0xF8, 0x01, 0x70, 0x3A, 0x42, 0x32, 0xD1, 0x5F, 0x58, 0x3A, 0x42, 0x06, 0x44, 0x1F, 0xD0, 0x18, 0x9B, 0x37, 0x78, 0x1B, 0x68, 0xB8, 0x45, 0x04, 0xD1, 0x58, 0x58, 0x02, 0x42, 0x19, 0xD0, 0x63, 0x46, 0x15, 0xE0, 0xA1, 0x10, 0x8C, 0x00, 0x19, 0x59, 0x91, 0x43, 0x19, 0x51, 0x00, 0x90, 0x30, 0x78, 0x01, 0x90, 0x44, 0x53, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x20, 0x06, 0x21, 0x02, 0x46, 0x4D, 0xF6 ,
-0x80, 0x53, 0xF3, 0xF7, 0x63, 0xF9, 0x09, 0x99, 0x28, 0x68, 0x0E, 0x78, 0x36, 0x18, 0x06, 0xE0, 0xE3, 0x58, 0x02, 0x00, 0xA0, 0x10, 0x81, 0x00, 0x58, 0x58, 0x02, 0x43, 0x5A, 0x50, 0x86, 0xF8, 0x00, 0x80, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x13, 0x98, 0xB0, 0xF9, 0x00, 0x90, 0x09, 0x98, 0x00, 0x78, 0x0A, 0x9A, 0x40, 0x1C, 0x9B, 0xF8, 0x00, 0x50, 0x9A, 0xF8, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x09, 0x9A, 0xC0, 0xB2, 0x10, 0x70, 0x0C, 0x9A, 0x01, 0x2A, 0x03, 0xD1, 0x88, 0x42, 0xC8, 0xBF, 0x8A, 0xF8, 0x00, 0x00, 0x0C, 0x99, 0x02, 0x29, 0x07, 0xD1, 0xA8, 0x42, 0xC8, 0xBF, 0x8B, 0xF8, 0x00, 0x00, 0x02, 0xE0, 0x0A, 0x98, 0xB0, 0xF9, 0x00, 0x30, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x03, 0x2B, 0x04, 0xD1, 0x11, 0x98, 0x01, 0x22, 0x49, 0x46, 0x00, 0xF0, 0x72, 0xFB, 0x16, 0x98, 0xB0, 0xF9, 0x00, 0x10, 0x14, 0x98, 0x00, 0x29, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xDD, 0x03, 0x28, 0x03, 0xD1, 0x12, 0x98 ,
-0x02, 0x22, 0x00, 0xF0, 0x64, 0xFB, 0x05, 0x98, 0x04, 0x78, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x08, 0x98, 0xBB, 0x2C, 0x01, 0x78, 0x02, 0xD0, 0xAA, 0x2C, 0x2F, 0xD0, 0x31, 0xE0, 0x0C, 0x98, 0x01, 0x28, 0x0B, 0xD1, 0x0D, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x0C, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x0F, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x11, 0x98, 0x10, 0x60, 0x47, 0x4A, 0x15, 0x98, 0x02, 0x60, 0x0C, 0x98, 0x02, 0x28, 0x0B, 0xD1, 0x0E, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x10, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x12, 0x98, 0x10, 0x60, 0x41, 0x4A, 0x15, 0x98, 0x02, 0x60, 0xCC, 0x20, 0x0F, 0xE0, 0x08, 0x99, 0x09, 0x78, 0x0C, 0xE0, 0x02, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x0B, 0x99, 0x08, 0x70, 0x1A, 0x99, 0x0B, 0x80, 0x13, 0x99, 0x00, 0x20, 0x08, 0x80, 0x08, 0x98, 0x01, 0x78, 0xBB, 0x20, 0x05, 0x9A, 0x10, 0x70, 0x06, 0x29, 0x07, 0x99, 0x11, 0xD1, 0x06, 0x20, 0x08, 0x60, 0x20, 0x98 ,
-0x00, 0x25, 0x05, 0x70, 0x21, 0x98, 0x29, 0x46, 0x04, 0x22, 0xFB, 0xF7, 0x27, 0xFB, 0x01, 0x20, 0x00, 0xF0, 0x3A, 0xFA, 0x02, 0x20, 0x00, 0xF0, 0x37, 0xFA, 0x22, 0x98, 0x05, 0x60, 0x07, 0x98, 0x04, 0x99, 0x00, 0x68, 0x07, 0x28, 0x44, 0xD1, 0x09, 0x78, 0x03, 0x9C, 0x80, 0x29, 0x40, 0xD1, 0x38, 0x34, 0x21, 0x78, 0x64, 0x1C, 0x22, 0x46, 0x00, 0x29, 0x3A, 0xD1, 0x20, 0x98, 0x90, 0xF8, 0x00, 0xA0, 0x22, 0x98, 0x05, 0x90, 0xD0, 0xF8, 0x00, 0x90, 0x51, 0x46, 0x48, 0x46, 0xFD, 0xF7, 0x79, 0xF9, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x9F, 0x15, 0x78, 0x51, 0x46, 0x48, 0x46, 0x17, 0xF8, 0x08, 0x30, 0xFD, 0xF7, 0xD4, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6F, 0xF9, 0x1E, 0x46, 0x1B, 0x1D, 0xC0, 0xB2, 0x38, 0x5C, 0x00, 0x1D, 0xA8, 0x42, 0x28, 0x46, 0x07, 0xDD, 0x80, 0x18, 0x82, 0x1C, 0x10, 0x78, 0x2D, 0x18, 0xAD, 0x1C, 0xAD, 0xB2, 0xAB, 0x42, 0xF7, 0xDC, 0x04, 0xF8, 0x01, 0x6B, 0x11, 0x49, 0x32, 0x46 ,
-0x20, 0x46, 0x01, 0xEB, 0x48, 0x11, 0xFA, 0xF7, 0xDC, 0xF9, 0xAD, 0x1B, 0xFF, 0x20, 0x34, 0x19, 0xAD, 0x1E, 0x04, 0xF8, 0x01, 0x0B, 0x25, 0x70, 0x05, 0x98, 0x01, 0x68, 0x49, 0x1C, 0x01, 0x60, 0x07, 0x98, 0x00, 0x68, 0x07, 0x28, 0x04, 0xD0, 0x06, 0x99, 0x08, 0x68, 0x20, 0xF4, 0x80, 0x30, 0x08, 0x60, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC0, 0x46, 0x94, 0x57, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x6E, 0x48, 0x2D, 0xE9, 0xF0, 0x47, 0x6E, 0x4D, 0x82, 0x89, 0x4A, 0xF6, 0x55, 0x21, 0xAD, 0xF5, 0xFE, 0x7D, 0x91, 0x42, 0x4F, 0xF0, 0x00, 0x01, 0xAD, 0xF1, 0x38, 0x0D, 0x12, 0xD1, 0x29, 0x60, 0x68, 0x4A, 0x11, 0x70, 0x41, 0xF2, 0x10, 0x41, 0x81, 0x81, 0x4F, 0xF6, 0xFF, 0x70, 0x66, 0x49, 0x08, 0x60, 0x28, 0x68, 0x00, 0x90, 0x02, 0x22, 0x05, 0x21, 0x03, 0x20, 0x41, 0xF2, 0x34, 0x23, 0xF3, 0xF7, 0x48, 0xF8, 0x29, 0x68, 0x61, 0x4C, 0x01, 0x29, 0x20, 0x68, 0x40, 0xF0, 0xAF, 0x80 ,
-0x5F, 0x4D, 0x02, 0x28, 0x29, 0x68, 0x23, 0xD1, 0x9C, 0x55, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x68, 0x5F, 0x4A, 0x12, 0x5C, 0x00, 0x92, 0x01, 0x91, 0x5E, 0x49, 0x09, 0x68, 0x02, 0x91, 0x5B, 0x49, 0x0B, 0x5C, 0x03, 0x20, 0x07, 0x21, 0x04, 0x22, 0xF3, 0xF7, 0x2E, 0xF8, 0x5B, 0x49, 0x4A, 0x79, 0x59, 0x48, 0x00, 0x92, 0x02, 0x79, 0x01, 0x92, 0x40, 0x79, 0x04, 0x22, 0x02, 0x90, 0x03, 0x20, 0x0B, 0x79, 0x07, 0x21, 0xF3, 0xF7, 0x20, 0xF8, 0x03, 0x20, 0x20, 0x60, 0xEC, 0xF7, 0x1A, 0xFF, 0x20, 0x68, 0x29, 0x68, 0x04, 0x28, 0x15, 0xD1, 0x0D, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x00, 0x25, 0x8D, 0xF8, 0x14, 0x50, 0x8D, 0xF8, 0x15, 0x10, 0x28, 0x46, 0x63, 0x21, 0x00, 0xF0, 0xAA, 0xFB, 0x63, 0x21, 0x28, 0x46, 0x00, 0xF0, 0xFA, 0xFA, 0x03, 0xA9, 0x04, 0xA8, 0xE0, 0xF7, 0xCA, 0xFC, 0x05, 0x20, 0x20, 0x60, 0x46, 0x4D, 0x05, 0x28, 0x29, 0x68, 0x01, 0xF1, 0x01, 0x01, 0x29, 0x60, 0x1D, 0xD1 ,
-0x44, 0x4A, 0x8A, 0x42, 0x1A, 0xD1, 0x43, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0x06, 0x21, 0x41, 0x4E, 0x33, 0x46, 0x22, 0x3B, 0xF2, 0xF7, 0xEB, 0xFF, 0x3E, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x33, 0x46, 0x06, 0x21, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xE0, 0xFF, 0x00, 0x20, 0x28, 0x60, 0x20, 0x68, 0x06, 0x28, 0x47, 0xD1, 0x4F, 0xF0, 0x64, 0x56, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x07, 0x0A, 0xC4, 0xF8, 0x00, 0xA0, 0x03, 0x20, 0x48, 0xF2, 0x70, 0x53, 0x01, 0x22, 0x04, 0x21, 0xF2, 0xF7, 0xD0, 0xFF, 0xDF, 0xF8, 0xCC, 0x80, 0x31, 0x4F, 0x48, 0xF2, 0x70, 0x59, 0x01, 0x25, 0x49, 0xEA, 0x05, 0x03, 0x01, 0x22, 0x04, 0x21, 0x03, 0x20, 0xF2, 0xF7, 0xC3, 0xFF, 0x00, 0x24, 0x17, 0xF8, 0x02, 0x0F, 0x20, 0xE0, 0x69, 0x01, 0x04, 0xEB, 0x08, 0x02, 0x88, 0x18, 0xC6, 0x1C, 0x43, 0x78, 0x00, 0x93, 0x80, 0x78, 0x01, 0x90, 0x30, 0x78, 0x02, 0x90 ,
-0x53, 0x5C, 0x51, 0x46, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xAE, 0xFF, 0x38, 0x78, 0x01, 0x1B, 0xB1, 0xF1, 0xFF, 0x3F, 0x08, 0xD1, 0xF0, 0x78, 0x00, 0x90, 0xB3, 0x78, 0x03, 0x20, 0x02, 0x22, 0x05, 0x21, 0xF2, 0xF7, 0xA1, 0xFF, 0x38, 0x78, 0x24, 0x1D, 0xE4, 0xB2, 0xA0, 0x42, 0xDC, 0xDC, 0xAD, 0x1C, 0xED, 0xB2, 0x04, 0x2D, 0xCD, 0xDB, 0x63, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0xF1, 0xF7, 0xA3, 0xFC, 0xE1, 0xF7, 0x85, 0xFD, 0x7F, 0xB0, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46, 0x04, 0x74, 0x00, 0x20, 0x50, 0x57, 0x02, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x40, 0x00, 0x3D, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x58, 0x57, 0x02, 0x00, 0x90, 0x57, 0x02, 0x00, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00, 0x2C, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x88, 0x57, 0x02, 0x00, 0x54, 0x57, 0x02, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58 ,
-0x02, 0x00, 0x66, 0x55, 0xDD, 0xEE, 0xDB, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x58, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x4A, 0x4A, 0x49, 0x4D, 0x00, 0x90, 0xB2, 0xF9, 0x00, 0x20, 0x43, 0xA3, 0x29, 0x78, 0x01, 0x93, 0x43, 0xA3, 0x01, 0x28, 0x02, 0x93, 0x47, 0x4E, 0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0x91, 0x1E, 0xD0, 0x43, 0x48, 0x04, 0x78, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0xC8, 0xFF, 0x40, 0x46, 0x01, 0x78, 0x00, 0x68, 0x07, 0xF1, 0x06, 0x07, 0x07, 0xF8, 0x01, 0x1B, 0x07, 0xF8, 0x01, 0x4B, 0x4F, 0xF0, 0x00, 0x01, 0x07, 0xF8, 0x01, 0x1B, 0x20, 0xB9, 0x39, 0x70, 0x28, 0x78, 0x4E, 0x46, 0x0A, 0x21, 0x58, 0xE0, 0xDF, 0xF8, 0xE4, 0xB0, 0x0F, 0xE0, 0xD4, 0xB2, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0xAA, 0xFF, 0xFF, 0x1D, 0x00, 0x20, 0xDF, 0xF8, 0xCC, 0xB0, 0x07, 0xF8, 0x01, 0x4B, 0x07, 0xF8, 0x01, 0x0B, 0x16, 0x2C, 0xB2, 0x46, 0xAE, 0xBF, 0x14, 0x20, 0x84, 0x59 ,
-0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x60, 0x1E, 0xC0, 0xB2, 0x38, 0x70, 0x4E, 0x46, 0x7F, 0x1C, 0x40, 0x1C, 0xC2, 0xB2, 0x28, 0x78, 0x5B, 0x46, 0x00, 0x21, 0x32, 0x54, 0x38, 0x46, 0x00, 0xF0, 0xBC, 0xF9, 0x28, 0x78, 0x16, 0x2C, 0x31, 0x5C, 0x01, 0xF1, 0x0A, 0x01, 0x31, 0x54, 0x00, 0xF1, 0x01, 0x00, 0xC0, 0xB2, 0x28, 0x70, 0x2B, 0xDB, 0x00, 0x99, 0x0A, 0xEB, 0x40, 0x10, 0x07, 0x46, 0x01, 0x29, 0xA4, 0xF1, 0x01, 0x09, 0x09, 0xD0, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0x79, 0xFF, 0x40, 0x46, 0x00, 0x78, 0xBF, 0x1D, 0x07, 0xF8, 0x01, 0x0B, 0x04, 0xE0, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0x6F, 0xFF, 0xFF, 0x1D, 0x07, 0xF8, 0x01, 0x4B, 0x15, 0x3C, 0x15, 0x21, 0x28, 0x78, 0xE2, 0xB2, 0x5B, 0x46, 0x07, 0xF8, 0x01, 0x1B, 0x32, 0x54, 0x07, 0xF8, 0x01, 0x9B, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF9, 0x28, 0x78, 0x31, 0x5C, 0x0A, 0x31, 0x31, 0x54, 0x40, 0x1C, 0x28, 0x70, 0xBD, 0xE8, 0xFE, 0x8F, 0xC0, 0x46 ,
-0x54, 0x54, 0x54, 0x4B, 0x45, 0x59, 0x00, 0xC0, 0x54, 0x54, 0x54, 0x53, 0x53, 0x49, 0x44, 0x00, 0x54, 0x58, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x94, 0x57, 0x02, 0x00, 0xFF, 0xB5, 0x0C, 0x46, 0x06, 0x46, 0xF7, 0xF7, 0x4C, 0x5A, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE3, 0xFE, 0x15, 0x49, 0x15, 0x4A, 0x0D, 0x68, 0x01, 0xA9, 0x92, 0xE8, 0x8C, 0x00, 0x81, 0xE8, 0x8C, 0x00, 0xF7, 0xF7, 0xFD, 0xFE, 0x01, 0x98, 0x11, 0x49, 0x28, 0x1A, 0x03, 0x9D, 0x25, 0x60, 0x02, 0x9A, 0x80, 0x18, 0x82, 0x42, 0x30, 0x60, 0x0E, 0xD8, 0x08, 0x46, 0x00, 0x68, 0x22, 0x68, 0x82, 0x42, 0x0E, 0xD2, 0x68, 0x46, 0xE8, 0xF7, 0xB9, 0xFF, 0x9D, 0xF8, 0x00, 0x00, 0x05, 0xF1, 0x01, 0x05, 0x30, 0xB9, 0x03, 0x95, 0x03, 0xE0, 0x25, 0x68, 0x6D, 0x1C, 0x25, 0x60, 0x0C, 0x46, 0x25, 0x60, 0x00, 0x20, 0x00, 0x90 ,
-0xFF, 0xBD, 0x60, 0x55, 0x30, 0x80, 0x24, 0x5D, 0x00, 0x20, 0x6C, 0x5D, 0x02, 0x00, 0x70, 0xB5, 0x4D, 0x00, 0x20, 0x2D, 0x4F, 0xF0, 0x00, 0x01, 0x0C, 0x46, 0x4F, 0xEA, 0x55, 0x13, 0x09, 0xD3, 0x50, 0xF8, 0x21, 0x60, 0xB6, 0xF1, 0xFF, 0x3F, 0x04, 0xD1, 0x49, 0x1C, 0xC9, 0xB2, 0x20, 0x3D, 0x5B, 0x1E, 0xF5, 0xD1, 0x4D, 0xB1, 0x20, 0x2D, 0x09, 0xD2, 0x01, 0x23, 0xAB, 0x40, 0x5B, 0x1E, 0x50, 0xF8, 0x21, 0x00, 0x18, 0x40, 0x83, 0x42, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x04, 0x07, 0x48, 0x03, 0x78, 0x2C, 0xB9, 0x01, 0x21, 0x91, 0x40, 0xC9, 0x43, 0xC9, 0xB2, 0x0B, 0x40, 0x03, 0xE0, 0x01, 0x21, 0x91, 0x40, 0xC9, 0xB2, 0x0B, 0x43, 0x03, 0x70, 0x70, 0xBD, 0xC0, 0x46, 0xEE, 0x58, 0x02, 0x00, 0x14, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x7E, 0xB5, 0x05, 0x46, 0x95, 0xF8, 0x36, 0x20, 0x0E, 0x46, 0x0F, 0x49, 0x07, 0x2A, 0x12, 0xBF, 0x08, 0x68, 0x01, 0x20, 0x08, 0x60, 0x0D, 0x4C, 0x00, 0x92, 0x21, 0x68 ,
-0x41, 0xF2, 0x12, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF2, 0xF7, 0x6B, 0xFD, 0x31, 0x46, 0x28, 0x46, 0xE7, 0xF7, 0x21, 0xFC, 0x21, 0x68, 0x00, 0x22, 0x05, 0x29, 0x02, 0xD1, 0x04, 0x49, 0x08, 0x31, 0x0A, 0x60, 0x7E, 0xBD, 0xC0, 0x46, 0x50, 0x57, 0x02, 0x00, 0x4C, 0x57, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x20, 0x0E, 0x49, 0x09, 0x68, 0x49, 0x08, 0x15, 0xD2, 0x0D, 0x49, 0x09, 0x78, 0x91, 0xB1, 0x44, 0xF2, 0xE9, 0x21, 0x68, 0xB9, 0x0B, 0x48, 0x01, 0x78, 0x07, 0x48, 0x01, 0x29, 0x03, 0xD1, 0x0A, 0x49, 0x09, 0x78, 0x0E, 0x29, 0x02, 0xD0, 0x44, 0xF2, 0xDE, 0x21, 0x41, 0x60, 0x01, 0x21, 0x00, 0xE0, 0x06, 0x48, 0x01, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x97, 0x3C, 0x80, 0x10, 0x0C, 0x30, 0x80, 0xDD, 0x6A, 0x00, 0x20, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x00, 0xB5, 0xAD, 0xF1, 0x18, 0x0D, 0x4F, 0xF0, 0x09, 0x00, 0x00, 0x90, 0x4F, 0xF4 ,
-0x0C, 0x60, 0x03, 0x90, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0x90, 0x02, 0x90, 0x08, 0x48, 0x08, 0x49, 0x05, 0x90, 0x08, 0x68, 0x20, 0xB9, 0xDC, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0x3A, 0xFA, 0x03, 0xE0, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0xC1, 0xFC, 0x06, 0xB0, 0x00, 0xBD, 0xC0, 0x46, 0x81, 0x5C, 0x02, 0x00, 0xDC, 0x7C, 0x00, 0x20, 0x1C, 0xB5, 0x0F, 0x4C, 0x22, 0x68, 0x01, 0x2A, 0x15, 0xD1, 0x0C, 0x48, 0x00, 0x68, 0x07, 0x28, 0x14, 0xBF, 0x40, 0x20, 0x4F, 0xF4, 0x05, 0x70, 0x63, 0x21, 0xF1, 0xF7, 0x0F, 0xFA, 0x20, 0x68, 0x00, 0x90, 0x43, 0xF2, 0x33, 0x33, 0x06, 0x21, 0x40, 0x20, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xF4, 0xFC, 0x1C, 0xBD, 0xF1, 0xF7, 0x01, 0xFA, 0x1C, 0xBD, 0x4C, 0x57, 0x02, 0x00, 0x50, 0x57, 0x02, 0x00, 0x1E, 0xB5, 0x04, 0x46, 0x0A, 0x49, 0x00, 0x20, 0x0A, 0x4A, 0x08, 0x60, 0x0A, 0x49, 0x00, 0x90, 0x01, 0x90, 0x11, 0x60 ,
-0x09, 0x4A, 0x45, 0xF2, 0x55, 0x53, 0x02, 0x91, 0x10, 0x60, 0x07, 0x21, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xD8, 0xFC, 0x20, 0x46, 0xE7, 0xF7, 0x59, 0xFD, 0x1E, 0xBD, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x4C, 0x57, 0x02, 0x00, 0x00, 0xB5, 0x0B, 0x49, 0x00, 0x20, 0x08, 0x60, 0xE0, 0x20, 0xF7, 0xF7, 0xAA, 0xFD, 0x09, 0x49, 0x09, 0x78, 0x49, 0xB1, 0x08, 0x49, 0x0A, 0x78, 0x08, 0x49, 0x00, 0x2A, 0x06, 0xBF, 0x01, 0x22, 0x09, 0x1F, 0x44, 0xF2, 0xA4, 0x5C, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE9, 0x22, 0x0A, 0x60, 0xF7, 0xF7, 0xA1, 0xFD, 0x00, 0xBD, 0xC0, 0x46, 0xDC, 0x7C, 0x00, 0x20, 0xDD, 0x6A, 0x00, 0x20, 0xA7, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x50, 0xB9, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x06, 0xD1, 0x08, 0x48, 0x00, 0x78, 0x0E, 0x28, 0x08, 0xBF, 0x44, 0xF2, 0xCB, 0x20, 0x01, 0xD0, 0x44, 0xF2, 0xDE, 0x20, 0x04, 0x49, 0x08, 0x60, 0x01, 0x20 ,
-0x41, 0xF8, 0x04, 0x0C, 0x70, 0x47, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x30, 0xB5, 0x0D, 0x46, 0x84, 0x69, 0xDC, 0xF7, 0x97, 0xFB, 0x24, 0x1D, 0x01, 0x28, 0x04, 0xEB, 0x45, 0x01, 0x06, 0xD1, 0x89, 0x8E, 0x04, 0xEB, 0x85, 0x04, 0x11, 0xB9, 0x21, 0x69, 0x01, 0xB9, 0x00, 0x20, 0x30, 0xBD, 0x30, 0xB5, 0x05, 0x46, 0x5A, 0xB1, 0x03, 0xEB, 0x41, 0x03, 0x1C, 0x78, 0x59, 0x78, 0x41, 0xEA, 0x04, 0x11, 0x52, 0x1E, 0x03, 0xF1, 0x02, 0x03, 0x05, 0xF8, 0x01, 0x1B, 0xF5, 0xD1, 0x30, 0xBD, 0x00, 0xB5, 0x00, 0x20, 0xE7, 0xF7, 0xD6, 0xFE, 0x03, 0x48, 0x01, 0x68, 0x03, 0x29, 0x04, 0xBF, 0x04, 0x21, 0x01, 0x60, 0x00, 0xBD, 0xC0, 0x46, 0x4C, 0x57, 0x02, 0x00, 0x03, 0x4A, 0x12, 0x68, 0x01, 0x2A, 0x04, 0xBF, 0x02, 0x48, 0x63, 0x21, 0xF1, 0xF7, 0x76, 0xB9, 0x50, 0x57, 0x02, 0x00, 0x02, 0x20, 0x01, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
diff --git a/drivers/cc3000/src/patch_prog.c b/drivers/cc3000/src/patch_prog.c
deleted file mode 100644
index fd128928fbaff..0000000000000
--- a/drivers/cc3000/src/patch_prog.c
+++ /dev/null
@@ -1,414 +0,0 @@
-#include
-#include
-#include "cc3000_common.h"
-#include "nvmem.h"
-#include "ccspi.h"
-#include "hci.h"
-#include "wlan.h"
-#include "patch_prog.h"
-#define BIT0 0x1
-#define BIT1 0x2
-#define BIT2 0x4
-#define BIT3 0x8
-#define BIT4 0x10
-#define BIT5 0x20
-#define BIT6 0x40
-#define BIT7 0x80
-
-static unsigned char ucStatus_Dr;
-static unsigned char ucStatus_FW;
-static unsigned char return_status = 0xFF;
-
-static signed char mac_status = -1;
-static unsigned char counter = 0;
-
-// Array to store RM parameters from EEPROM.
-static unsigned char cRMParamsFromEeprom[128];
-// Array to store MAC address from EEPROM.
-static unsigned char cMacFromEeprom[MAC_ADDR_LEN];
-// Smart Config Prefix
-static const char aucCC3000_prefix[] = {'T', 'T', 'T'};
-
-static void systick_sleep(unsigned long ms) {
- extern void HAL_Delay(volatile uint32_t Delay);
- HAL_Delay(ms);
-}
-
-// 2 dim array to store address and length of new FAT
-static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] =
-/* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830},
-/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}};
-/* 0. NVS */
-/* 1. NVS Shadow */
-/* 2. Wireless Conf */
-/* 3. Wireless Conf Shadow */
-/* 4. BT (WLAN driver) Patches */
-/* 5. WiLink (Firmware) Patches */
-/* 6. MAC addr */
-/* 7. Frontend Vars */
-/* 8. IP config */
-/* 9. IP config Shadow */
-/* 10. Bootloader Patches */
-/* 11. Radio Module params */
-/* 12. AES128 for smart config */
-/* 13. user file */
-/* 14. user file */
-/* 15. user file */
-
-//*****************************************************************************
-//
-//! sendDriverPatch
-//!
-//! \param pointer to the length
-//!
-//! \return none
-//!
-//! \brief The function returns a pointer to the driver patch:
-//! since there is no patch yet - it returns 0
-//
-//*****************************************************************************
-
-static char *sendDriverPatch(unsigned long *Length)
-{
- *Length = 0;
- return NULL;
-}
-
-
-//*****************************************************************************
-//
-//! sendBootLoaderPatch
-//!
-//! \param pointer to the length
-//!
-//! \return none
-//!
-//! \brief The function returns a pointer to the boot loader patch:
-//! since there is no patch yet - it returns 0
-//
-//*****************************************************************************
-
-static char *sendBootLoaderPatch(unsigned long *Length)
-{
- *Length = 0;
- return NULL;
-}
-
-//*****************************************************************************
-//
-//! sendWLFWPatch
-//!
-//! \param pointer to the length
-//!
-//! \return none
-//!
-//! \brief The function returns a pointer to the FW patch:
-//! since there is no patch yet - it returns 0
-//
-//*****************************************************************************
-
-static char *sendWLFWPatch(unsigned long *Length)
-{
- *Length = 0;
- return NULL;
-}
-
-//*****************************************************************************
-//
-//! CC3000_UsynchCallback
-//!
-//! \param Event type
-//!
-//! \return none
-//!
-//! \brief The function handles asynchronous events that come from CC3000
-//! device and operates a LED4 to have an on-board indication
-//
-//*****************************************************************************
-
-static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length)
-{
-
-}
-
-//*****************************************************************************
-//
-//! initDriver
-//!
-//! \param[in] cRequestPatch 0 to load with EEPROM patches
-//! and 1 to load with no patches
-//!
-//! \return none
-//!
-//! \brief The function initializes a CC3000 device
-//! and triggers it to start operation
-//
-//*****************************************************************************
-static int initDriver(unsigned short cRequestPatch)
-{
- // WLAN On API Implementation
- wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch,
- ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin);
-
- // Trigger a WLAN device
- wlan_start(cRequestPatch);
- wlan_smart_config_set_prefix((char*)aucCC3000_prefix);
- wlan_ioctl_set_connection_policy(0, 0, 0);
- wlan_ioctl_del_profile(255);
-
- // Mask out all non-required events from CC3000
- wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|
- HCI_EVNT_WLAN_UNSOL_INIT|
- HCI_EVNT_WLAN_ASYNC_PING_REPORT);
-
- //unsolicicted_events_timer_init();
- systick_sleep(100);
- return(0);
-}
-
-
-//*****************************************************************************
-//
-//! fat_read_content
-//!
-//! \param[out] is_allocated array of is_allocated in FAT table:\n
-//! an allocated entry implies the address and length of the
-//! file are valid.
-//! 0: not allocated; 1: allocated.
-//! \param[out] is_valid array of is_valid in FAT table:\n
-//! a valid entry implies the content of the file is relevant.
-//! 0: not valid; 1: valid.
-//! \param[out] write_protected array of write_protected in FAT table:\n
-//! a write protected entry implies it is not possible to write
-//! into this entry.
-//! 0: not protected; 1: protected.
-//! \param[out] file_address array of file address in FAT table:\n
-//! this is the absolute address of the file in the EEPROM.
-//! \param[out] file_length array of file length in FAT table:\n
-//! this is the upper limit of the file size in the EEPROM.
-//!
-//! \return on succes 0, error otherwise
-//!
-//! \brief parse the FAT table from eeprom
-//
-//*****************************************************************************
-static unsigned char __attribute__ ((unused))
-fat_read_content(unsigned char *is_allocated, unsigned char *is_valid,
- unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length)
-{
- unsigned short index;
- unsigned char ucStatus;
- unsigned char fatTable[48];
- unsigned char* fatTablePtr = fatTable;
-
- //
- // Read in 6 parts to work with tiny driver
- //
- for (index = 0; index < 6; index++)
- {
- ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr);
- fatTablePtr += 8;
- }
-
- fatTablePtr = fatTable;
-
- for (index = 0; index <= NVMEM_RM_FILEID; index++)
- {
- *is_allocated++ = (*fatTablePtr) & BIT0;
- *is_valid++ = ((*fatTablePtr) & BIT1) >> 1;
- *write_protected++ = ((*fatTablePtr) & BIT2) >> 2;
- *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7);
- *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7);
-
- //
- // Move to next file ID
- //
- fatTablePtr += 4;
- }
-
- return ucStatus;
-}
-
-//*****************************************************************************
-//
-//! fat_write_content
-//!
-//! \param[in] file_address array of file address in FAT table:\n
-//! this is the absolute address of the file in the EEPROM.
-//! \param[in] file_length array of file length in FAT table:\n
-//! this is the upper limit of the file size in the EEPROM.
-//!
-//! \return on succes 0, error otherwise
-//!
-//! \brief parse the FAT table from eeprom
-//
-//*****************************************************************************
-static unsigned char fat_write_content(unsigned short const *file_address,
- unsigned short const *file_length)
-{
- unsigned short index = 0;
- unsigned char ucStatus;
- unsigned char fatTable[48];
- unsigned char* fatTablePtr = fatTable;
-
- //
- // First, write the magic number.
- //
- ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS");
-
- for (; index <= NVMEM_RM_FILEID; index++)
- {
- //
- // Write address low char and mark as allocated.
- //
- *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0;
-
- //
- // Write address high char.
- //
- *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff);
-
- //
- // Write length low char.
- //
- *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff);
-
- //
- // Write length high char.
- //
- *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff);
- }
-
- //
- // Second, write the FAT.
- // Write in two parts to work with tiny driver.
- //
- ucStatus = nvmem_write(16, 24, 4, fatTable);
- ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]);
-
- //
- // Third, we want to erase any user files.
- //
- memset(fatTable, 0, sizeof(fatTable));
- ucStatus = nvmem_write(16, 16, 52, fatTable);
-
- return ucStatus;
-}
-
-void patch_prog_start()
-{
- unsigned short index;
- unsigned char *pRMParams;
-
- printf("Initializing module...\n");
-
- // Init module and request to load with no patches.
- // This is in order to overwrite restrictions to
- // write to specific places in EEPROM.
- initDriver(1);
-
- // Read MAC address.
- mac_status = nvmem_get_mac_address(cMacFromEeprom);
-
- return_status = 1;
-
- printf("Reading RM parameters...\n");
- while ((return_status) && (counter < 3)) {
- // Read RM parameters.
- // Read in 16 parts to work with tiny driver.
- return_status = 0;
- pRMParams = cRMParamsFromEeprom;
- for (index = 0; index < 16; index++) {
- return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams);
- pRMParams += 8;
- }
- counter++;
- }
-
- // If RM file is not valid, load the default one.
- if (counter == 3) {
- printf("RM is not valid, loading default one...\n");
- pRMParams = (unsigned char *)cRMdefaultParams;
- } else {
- printf("RM is valid.\n");
- pRMParams = cRMParamsFromEeprom;
- }
-
- return_status = 1;
-
- printf("Writing new FAT\n");
- while (return_status) {
- // Write new FAT.
- return_status = fat_write_content(aFATEntries[0], aFATEntries[1]);
- }
-
- return_status = 1;
-
- printf("Writing RM parameters...\n");
- while (return_status) {
- // Write RM parameters.
- // Write in 4 parts to work with tiny driver.
- return_status = 0;
-
- for (index = 0; index < 4; index++) {
- return_status |= nvmem_write(NVMEM_RM_FILEID,
- 32,
- 32*index,
- (pRMParams + 32*index));
- }
- }
-
- return_status = 1;
-
- // Write back the MAC address, only if exists.
- if (mac_status == 0) {
- // Zero out MCAST bit if set.
- cMacFromEeprom[0] &= 0xfe;
- printf("Writing back MAC address..\n");
- while (return_status) {
- return_status = nvmem_set_mac_address(cMacFromEeprom);
- }
- }
-
- // Update driver
- ucStatus_Dr = 1;
- printf("Updating driver patch...\n");
- while (ucStatus_Dr) {
- // Writing driver patch to EEPRROM - PROTABLE CODE
- // Note that the array itself is changing between the
- // different Service Packs.
- ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID,
- drv_length,
- wlan_drv_patch);
- }
-
- // Update firmware
- ucStatus_FW = 1;
- printf("Updating firmware patch...\n");
- while (ucStatus_FW) {
- // Writing FW patch to EEPRROM - PROTABLE CODE
- // Note that the array itself is changing between the
- // different Service Packs.
- ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID,
- fw_length,
- fw_patch);
- }
-
- printf("Update complete, resetting module\n"\
- "If this doesn't work, reset manually...\n");
-
- wlan_stop();
- systick_sleep(500);
-
- // Re-Init module and request to load with patches.
- initDriver(0);
-
- // If MAC does not exist, it is recommended
- // that the user will write a valid mac address.
- if (mac_status != 0) {
- printf("MAC address is not valid, please write a new one\n");
- }
-
- // Patch update done
- printf("All done, call wlan.patch_version()\n");
-}
diff --git a/drivers/cc3000/src/security.c b/drivers/cc3000/src/security.c
deleted file mode 100644
index 62b4f881343ad..0000000000000
--- a/drivers/cc3000/src/security.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/*****************************************************************************
-*
-* security.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup security_api
-//! @{
-//
-//*****************************************************************************
-
-#include "security.h"
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-// foreward sbox
-const UINT8 sbox[256] = {
-//0 1 2 3 4 5 6 7 8 9 A B C D E F
-0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
-0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
-0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
-0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
-0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
-0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
-0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
-0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
-0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
-0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
-0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
-0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
-0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
-0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
-0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
-0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
-// inverse sbox
-const UINT8 rsbox[256] =
-{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
-, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
-, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
-, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
-, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
-, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
-, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
-, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
-, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
-, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
-, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
-, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
-, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
-, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
-, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
-, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
-// round constant
-const UINT8 Rcon[11] = {
- 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
-
-
-UINT8 expandedKey[176];
-
-//*****************************************************************************
-//
-//! expandKey
-//!
-//! @param key AES128 key - 16 bytes
-//! @param expandedKey expanded AES128 key
-//!
-//! @return none
-//!
-//! @brief expend a 16 bytes key for AES128 implementation
-//!
-//*****************************************************************************
-
-void expandKey(UINT8 *expandedKey, UINT8 *key)
-{
- UINT16 ii, buf1;
- for (ii=0;ii<16;ii++)
- expandedKey[ii] = key[ii];
- for (ii=1;ii<11;ii++){
- buf1 = expandedKey[ii*16 - 4];
- expandedKey[ii*16 + 0] = sbox[expandedKey[ii*16 - 3]]^expandedKey[(ii-1)*16 + 0]^Rcon[ii];
- expandedKey[ii*16 + 1] = sbox[expandedKey[ii*16 - 2]]^expandedKey[(ii-1)*16 + 1];
- expandedKey[ii*16 + 2] = sbox[expandedKey[ii*16 - 1]]^expandedKey[(ii-1)*16 + 2];
- expandedKey[ii*16 + 3] = sbox[buf1 ]^expandedKey[(ii-1)*16 + 3];
- expandedKey[ii*16 + 4] = expandedKey[(ii-1)*16 + 4]^expandedKey[ii*16 + 0];
- expandedKey[ii*16 + 5] = expandedKey[(ii-1)*16 + 5]^expandedKey[ii*16 + 1];
- expandedKey[ii*16 + 6] = expandedKey[(ii-1)*16 + 6]^expandedKey[ii*16 + 2];
- expandedKey[ii*16 + 7] = expandedKey[(ii-1)*16 + 7]^expandedKey[ii*16 + 3];
- expandedKey[ii*16 + 8] = expandedKey[(ii-1)*16 + 8]^expandedKey[ii*16 + 4];
- expandedKey[ii*16 + 9] = expandedKey[(ii-1)*16 + 9]^expandedKey[ii*16 + 5];
- expandedKey[ii*16 +10] = expandedKey[(ii-1)*16 +10]^expandedKey[ii*16 + 6];
- expandedKey[ii*16 +11] = expandedKey[(ii-1)*16 +11]^expandedKey[ii*16 + 7];
- expandedKey[ii*16 +12] = expandedKey[(ii-1)*16 +12]^expandedKey[ii*16 + 8];
- expandedKey[ii*16 +13] = expandedKey[(ii-1)*16 +13]^expandedKey[ii*16 + 9];
- expandedKey[ii*16 +14] = expandedKey[(ii-1)*16 +14]^expandedKey[ii*16 +10];
- expandedKey[ii*16 +15] = expandedKey[(ii-1)*16 +15]^expandedKey[ii*16 +11];
- }
-
-}
-
-//*****************************************************************************
-//
-//! galois_mul2
-//!
-//! @param value argument to multiply
-//!
-//! @return multiplied argument
-//!
-//! @brief multiply by 2 in the galois field
-//!
-//*****************************************************************************
-
-UINT8 galois_mul2(UINT8 value)
-{
- if (value>>7)
- {
- value = value << 1;
- return (value^0x1b);
- } else
- return value<<1;
-}
-
-//*****************************************************************************
-//
-//! aes_encr
-//!
-//! @param[in] expandedKey expanded AES128 key
-//! @param[in/out] state 16 bytes of plain text and cipher text
-//!
-//! @return none
-//!
-//! @brief internal implementation of AES128 encryption.
-//! straight forward aes encryption implementation
-//! first the group of operations
-//! - addRoundKey
-//! - subbytes
-//! - shiftrows
-//! - mixcolums
-//! is executed 9 times, after this addroundkey to finish the 9th
-//! round, after that the 10th round without mixcolums
-//! no further subfunctions to save cycles for function calls
-//! no structuring with "for (....)" to save cycles.
-//!
-//!
-//*****************************************************************************
-
-void aes_encr(UINT8 *state, UINT8 *expandedKey)
-{
- UINT8 buf1, buf2, buf3, round;
-
- for (round = 0; round < 9; round ++){
- // addroundkey, sbox and shiftrows
- // row 0
- state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])];
- state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])];
- state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])];
- state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])];
- // row 1
- buf1 = state[1] ^ expandedKey[(round*16) + 1];
- state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])];
- state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])];
- state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])];
- state[13] = sbox[buf1];
- // row 2
- buf1 = state[2] ^ expandedKey[(round*16) + 2];
- buf2 = state[6] ^ expandedKey[(round*16) + 6];
- state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])];
- state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])];
- state[10] = sbox[buf1];
- state[14] = sbox[buf2];
- // row 3
- buf1 = state[15] ^ expandedKey[(round*16) + 15];
- state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])];
- state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])];
- state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])];
- state[ 3] = sbox[buf1];
-
- // mixcolums //////////
- // col1
- buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
- buf2 = state[0];
- buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
- buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
- buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
- buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
- // col2
- buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
- buf2 = state[4];
- buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
- buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
- buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
- buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
- // col3
- buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
- buf2 = state[8];
- buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
- buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
- buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
- buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
- // col4
- buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
- buf2 = state[12];
- buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
- buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
- buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
- buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
-
- }
- // 10th round without mixcols
- state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])];
- state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])];
- state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])];
- state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])];
- // row 1
- buf1 = state[1] ^ expandedKey[(round*16) + 1];
- state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])];
- state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])];
- state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])];
- state[13] = sbox[buf1];
- // row 2
- buf1 = state[2] ^ expandedKey[(round*16) + 2];
- buf2 = state[6] ^ expandedKey[(round*16) + 6];
- state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])];
- state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])];
- state[10] = sbox[buf1];
- state[14] = sbox[buf2];
- // row 3
- buf1 = state[15] ^ expandedKey[(round*16) + 15];
- state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])];
- state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])];
- state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])];
- state[ 3] = sbox[buf1];
- // last addroundkey
- state[ 0]^=expandedKey[160];
- state[ 1]^=expandedKey[161];
- state[ 2]^=expandedKey[162];
- state[ 3]^=expandedKey[163];
- state[ 4]^=expandedKey[164];
- state[ 5]^=expandedKey[165];
- state[ 6]^=expandedKey[166];
- state[ 7]^=expandedKey[167];
- state[ 8]^=expandedKey[168];
- state[ 9]^=expandedKey[169];
- state[10]^=expandedKey[170];
- state[11]^=expandedKey[171];
- state[12]^=expandedKey[172];
- state[13]^=expandedKey[173];
- state[14]^=expandedKey[174];
- state[15]^=expandedKey[175];
-}
-
-//*****************************************************************************
-//
-//! aes_decr
-//!
-//! @param[in] expandedKey expanded AES128 key
-//! @param[in\out] state 16 bytes of cipher text and plain text
-//!
-//! @return none
-//!
-//! @brief internal implementation of AES128 decryption.
-//! straight forward aes decryption implementation
-//! the order of substeps is the exact reverse of decryption
-//! inverse functions:
-//! - addRoundKey is its own inverse
-//! - rsbox is inverse of sbox
-//! - rightshift instead of leftshift
-//! - invMixColumns = barreto + mixColumns
-//! no further subfunctions to save cycles for function calls
-//! no structuring with "for (....)" to save cycles
-//!
-//*****************************************************************************
-
-void aes_decr(UINT8 *state, UINT8 *expandedKey)
-{
- UINT8 buf1, buf2, buf3;
- INT8 round;
- round = 9;
-
- // initial addroundkey
- state[ 0]^=expandedKey[160];
- state[ 1]^=expandedKey[161];
- state[ 2]^=expandedKey[162];
- state[ 3]^=expandedKey[163];
- state[ 4]^=expandedKey[164];
- state[ 5]^=expandedKey[165];
- state[ 6]^=expandedKey[166];
- state[ 7]^=expandedKey[167];
- state[ 8]^=expandedKey[168];
- state[ 9]^=expandedKey[169];
- state[10]^=expandedKey[170];
- state[11]^=expandedKey[171];
- state[12]^=expandedKey[172];
- state[13]^=expandedKey[173];
- state[14]^=expandedKey[174];
- state[15]^=expandedKey[175];
-
- // 10th round without mixcols
- state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ];
- state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4];
- state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8];
- state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12];
- // row 1
- buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1];
- state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13];
- state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9];
- state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5];
- state[ 1] = buf1;
- // row 2
- buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10];
- buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14];
- state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2];
- state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6];
- state[10] = buf1;
- state[14] = buf2;
- // row 3
- buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15];
- state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3];
- state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7];
- state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11];
- state[15] = buf1;
-
- for (round = 8; round >= 0; round--){
- // barreto
- //col1
- buf1 = galois_mul2(galois_mul2(state[0]^state[2]));
- buf2 = galois_mul2(galois_mul2(state[1]^state[3]));
- state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2;
- //col2
- buf1 = galois_mul2(galois_mul2(state[4]^state[6]));
- buf2 = galois_mul2(galois_mul2(state[5]^state[7]));
- state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2;
- //col3
- buf1 = galois_mul2(galois_mul2(state[8]^state[10]));
- buf2 = galois_mul2(galois_mul2(state[9]^state[11]));
- state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2;
- //col4
- buf1 = galois_mul2(galois_mul2(state[12]^state[14]));
- buf2 = galois_mul2(galois_mul2(state[13]^state[15]));
- state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2;
- // mixcolums //////////
- // col1
- buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
- buf2 = state[0];
- buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
- buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
- buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
- buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
- // col2
- buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
- buf2 = state[4];
- buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
- buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
- buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
- buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
- // col3
- buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
- buf2 = state[8];
- buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
- buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
- buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
- buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
- // col4
- buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
- buf2 = state[12];
- buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
- buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
- buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
- buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
-
- // addroundkey, rsbox and shiftrows
- // row 0
- state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ];
- state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4];
- state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8];
- state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12];
- // row 1
- buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1];
- state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13];
- state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9];
- state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5];
- state[ 1] = buf1;
- // row 2
- buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10];
- buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14];
- state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2];
- state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6];
- state[10] = buf1;
- state[14] = buf2;
- // row 3
- buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15];
- state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3];
- state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7];
- state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11];
- state[15] = buf1;
- }
-
-}
-
-//*****************************************************************************
-//
-//! aes_encrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of plain text and cipher text
-//!
-//! @return none
-//!
-//! @brief AES128 encryption:
-//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes
-//! is computed. The AES implementation is in mode ECB (Electronic
-//! Code Book).
-//!
-//!
-//*****************************************************************************
-
-void aes_encrypt(UINT8 *state, UINT8 *key)
-{
- // expand the key into 176 bytes
- expandKey(expandedKey, key);
- aes_encr(state, expandedKey);
-}
-
-//*****************************************************************************
-//
-//! aes_decrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of cipher text and plain text
-//!
-//! @return none
-//!
-//! @brief AES128 decryption:
-//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes
-//! is computed The AES implementation is in mode ECB
-//! (Electronic Code Book).
-//!
-//!
-//*****************************************************************************
-
-void aes_decrypt(UINT8 *state, UINT8 *key)
-{
- expandKey(expandedKey, key); // expand the key into 176 bytes
- aes_decr(state, expandedKey);
-}
-
-//*****************************************************************************
-//
-//! aes_read_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads AES128 key from EEPROM
-//! Reads the AES128 key from fileID #12 in EEPROM
-//! returns an error if the key does not exist.
-//!
-//!
-//*****************************************************************************
-
-INT32 aes_read_key(UINT8 *key)
-{
- INT32 returnValue;
-
- returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key);
-
- return returnValue;
-}
-
-//*****************************************************************************
-//
-//! aes_write_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief writes AES128 key from EEPROM
-//! Writes the AES128 key to fileID #12 in EEPROM
-//!
-//!
-//*****************************************************************************
-
-INT32 aes_write_key(UINT8 *key)
-{
- INT32 returnValue;
-
- returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key);
-
- return returnValue;
-}
-
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/socket.c b/drivers/cc3000/src/socket.c
deleted file mode 100644
index ddd7e56e80759..0000000000000
--- a/drivers/cc3000/src/socket.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/*****************************************************************************
-*
-* socket.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup socket_api
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include
-#include "hci.h"
-#include "socket.h"
-#include "evnt_handler.h"
-#include "netapp.h"
-
-
-
-//Enable this flag if and only if you must comply with BSD socket
-//close() function
-#ifdef _API_USE_BSD_CLOSE
-#define close(sd) closesocket(sd)
-#endif
-
-//Enable this flag if and only if you must comply with BSD socket read() and
-//write() functions
-#ifdef _API_USE_BSD_READ_WRITE
-#define read(sd, buf, len, flags) recv(sd, buf, len, flags)
-#define write(sd, buf, len, flags) send(sd, buf, len, flags)
-#endif
-
-#define SOCKET_OPEN_PARAMS_LEN (12)
-#define SOCKET_CLOSE_PARAMS_LEN (4)
-#define SOCKET_ACCEPT_PARAMS_LEN (4)
-#define SOCKET_BIND_PARAMS_LEN (20)
-#define SOCKET_LISTEN_PARAMS_LEN (8)
-#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9)
-#define SOCKET_CONNECT_PARAMS_LEN (20)
-#define SOCKET_SELECT_PARAMS_LEN (44)
-#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20)
-#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12)
-#define SOCKET_RECV_FROM_PARAMS_LEN (12)
-#define SOCKET_SENDTO_PARAMS_LEN (24)
-#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12)
-#define SOCKET_GET_MSS_VALUE_PARAMS_LEN (4)
-
-// The legnth of arguments for the SEND command: sd + buff_offset + len + flags,
-// while size of each parameter is 32 bit - so the total length is 16 bytes;
-
-#define HCI_CMND_SEND_ARG_LENGTH (16)
-
-
-#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000
-
-#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5)
-
-#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
-
-#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32)
-
-
-//*****************************************************************************
-//
-//! HostFlowControlConsumeBuff
-//!
-//! @param sd socket descriptor
-//!
-//! @return 0 in case there are buffers available,
-//! -1 in case of bad socket
-//! -2 if there are no free buffers present (only when
-//! SEND_NON_BLOCKING is enabled)
-//!
-//! @brief if SEND_NON_BLOCKING not define - block until have free buffer
-//! becomes available, else return immediately with correct status
-//! regarding the buffers available.
-//
-//*****************************************************************************
-static INT16 HostFlowControlConsumeBuff(INT16 sd)
-{
-#ifndef SEND_NON_BLOCKING
- /* wait in busy loop */
- do
- {
- // In case last transmission failed then we will return the last failure
- // reason here.
- // Note that the buffer will not be allocated in this case
- if (tSLInformation.slTransmitDataError != 0)
- {
- CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError;
- tSLInformation.slTransmitDataError = 0;
- return CC3000_EXPORT(errno);
- }
-
- if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
- return -1;
- } while(0 == tSLInformation.usNumberOfFreeBuffers);
-
- tSLInformation.usNumberOfFreeBuffers--;
-
- return 0;
-#else
-
- // In case last transmission failed then we will return the last failure
- // reason here.
- // Note that the buffer will not be allocated in this case
- if (tSLInformation.slTransmitDataError != 0)
- {
- CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError;
- tSLInformation.slTransmitDataError = 0;
- return CC3000_EXPORT(errno);
- }
- if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
- return -1;
-
- //If there are no available buffers, return -2. It is recommended to use
- // select or receive to see if there is any buffer occupied with received data
- // If so, call receive() to release the buffer.
- if(0 == tSLInformation.usNumberOfFreeBuffers)
- {
- return -2;
- }
- else
- {
- tSLInformation.usNumberOfFreeBuffers--;
- return 0;
- }
-#endif
-}
-
-//*****************************************************************************
-//
-//! socket
-//!
-//! @param domain selects the protocol family which will be used for
-//! communication. On this version only AF_INET is supported
-//! @param type specifies the communication semantics. On this version
-//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
-//! @param protocol specifies a particular protocol to be used with the
-//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are
-//! supported.
-//!
-//! @return On success, socket handle that is used for consequent socket
-//! operations. On error, -1 is returned.
-//!
-//! @brief create an endpoint for communication
-//! The socket function creates a socket that is bound to a specific
-//! transport service provider. This function is called by the
-//! application layer to obtain a socket handle.
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, domain);
- args = UINT32_TO_STREAM(args, type);
- args = UINT32_TO_STREAM(args, protocol);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);
-
- // Process the event
- CC3000_EXPORT(errno) = ret;
-
- set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! closesocket
-//!
-//! @param sd socket handle.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief The socket function closes a created socket.
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(closesocket)(INT32 sd)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, sd);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_CLOSE_SOCKET,
- ptr, SOCKET_CLOSE_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
- CC3000_EXPORT(errno) = ret;
-
- // since 'close' call may result in either OK (and then it closed) or error
- // mark this socket as invalid
- set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! accept
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr the argument addr is a pointer to a sockaddr structure
-//! This structure is filled in with the address of the
-//! peer socket, as known to the communications layer.
-//! determined. The exact format of the address returned
-//! addr is by the socket's address sockaddr.
-//! On this version only AF_INET is supported.
-//! This argument returns in network order.
-//! @param[out] addrlen the addrlen argument is a value-result argument:
-//! it should initially contain the size of the structure
-//! pointed to by addr.
-//!
-//! @return For socket in blocking mode:
-//! On success, socket handle. on failure negative
-//! For socket in non-blocking mode:
-//! - On connection establishment, socket handle
-//! - On connection pending, SOC_IN_PROGRESS (-2)
-//! - On failure, SOC_ERROR (-1)
-//!
-//! @brief accept a connection on a socket:
-//! This function is used with connection-based socket types
-//! (SOCK_STREAM). It extracts the first connection request on the
-//! queue of pending connections, creates a new connected socket, and
-//! returns a new file descriptor referring to that socket.
-//! The newly created socket is not in the listening state.
-//! The original socket sd is unaffected by this call.
-//! The argument sd is a socket that has been created with socket(),
-//! bound to a local address with bind(), and is listening for
-//! connections after a listen(). The argument addr is a pointer
-//! to a sockaddr structure. This structure is filled in with the
-//! address of the peer socket, as known to the communications layer.
-//! The exact format of the address returned addr is determined by the
-//! socket's address family. The addrlen argument is a value-result
-//! argument: it should initially contain the size of the structure
-//! pointed to by addr, on return it will contain the actual
-//! length (in bytes) of the address returned.
-//!
-//! @sa socket ; bind ; listen
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
- tBsdReturnParams tAcceptReturnArguments;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_ACCEPT,
- ptr, SOCKET_ACCEPT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);
-
-
- // need specify return parameters!!!
- memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
- *addrlen = ASIC_ADDR_LEN;
- CC3000_EXPORT(errno) = tAcceptReturnArguments.iStatus;
- ret = CC3000_EXPORT(errno);
-
- // if succeeded, iStatus = new socket descriptor. otherwise - error number
- if(M_IS_VALID_SD(ret))
- {
- set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
- }
- else
- {
- set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
- }
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! bind
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr specifies the destination address. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief assign a name to a socket
-//! This function gives the socket the local address addr.
-//! addr is addrlen bytes long. Traditionally, this is called when a
-//! socket is created with socket, it exists in a name space (address
-//! family) but has no name assigned.
-//! It is necessary to assign a local address before a SOCK_STREAM
-//! socket may receive connections.
-//!
-//! @sa socket ; accept ; listen
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- addrlen = ASIC_ADDR_LEN;
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, 0x00000008);
- args = UINT32_TO_STREAM(args, addrlen);
- ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_BIND,
- ptr, SOCKET_BIND_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);
-
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! listen
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] backlog specifies the listen queue depth. On this version
-//! backlog is not supported.
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief listen for connections on a socket
-//! The willingness to accept incoming connections and a queue
-//! limit for incoming connections are specified with listen(),
-//! and then the connections are accepted with accept.
-//! The listen() call applies only to sockets of type SOCK_STREAM
-//! The backlog parameter defines the maximum length the queue of
-//! pending connections may grow to.
-//!
-//! @sa socket ; accept ; bind
-//!
-//! @note On this version, backlog is not supported
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, backlog);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_LISTEN,
- ptr, SOCKET_LISTEN_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! gethostbyname
-//!
-//! @param[in] hostname host name
-//! @param[in] usNameLen name length
-//! @param[out] out_ip_addr This parameter is filled in with host IP address.
-//! In case that host name is not resolved,
-//! out_ip_addr is zero.
-//! @return On success, positive is returned. On error, negative is returned
-//!
-//! @brief Get host IP by name. Obtain the IP Address of machine on network,
-//! by its name.
-//!
-//! @note On this version, only blocking mode is supported. Also note that
-//! the function requires DNS server to be configured prior to its usage.
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen,
- UINT32* out_ip_addr)
-{
- tBsdGethostbynameParams ret;
- UINT8 *ptr, *args;
-
- CC3000_EXPORT(errno) = EFAIL;
-
- if (usNameLen > HOSTNAME_MAX_LENGTH)
- {
- return CC3000_EXPORT(errno);
- }
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, 8);
- args = UINT32_TO_STREAM(args, usNameLen);
- ARRAY_TO_STREAM(args, hostname, usNameLen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
- + usNameLen - 1);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
-
- CC3000_EXPORT(errno) = ret.retVal;
-
- (*((INT32*)out_ip_addr)) = ret.outputAddress;
-
- return CC3000_EXPORT(errno);
-
-}
-#endif
-
-//*****************************************************************************
-//
-//! connect
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] addr specifies the destination addr. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief initiate a connection on a socket
-//! Function connects the socket referred to by the socket descriptor
-//! sd, to the address specified by addr. The addrlen argument
-//! specifies the size of addr. The format of the address in addr is
-//! determined by the address space of the socket. If it is of type
-//! SOCK_DGRAM, this call specifies the peer with which the socket is
-//! to be associated; this address is that to which datagrams are to be
-//! sent, and the only address from which datagrams are to be received.
-//! If the socket is of type SOCK_STREAM, this call attempts to make a
-//! connection to another socket. The other socket is specified by
-//! address, which is an address in the communications space of the
-//! socket. Note that the function implements only blocking behavior
-//! thus the caller will be waiting either for the connection
-//! establishment or for the connection establishment failure.
-//!
-//! @sa socket
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
- addrlen = 8;
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, 0x00000008);
- args = UINT32_TO_STREAM(args, addrlen);
- ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_CONNECT,
- ptr, SOCKET_CONNECT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);
-
- CC3000_EXPORT(errno) = ret;
-
- return((INT32)ret);
-}
-
-
-//*****************************************************************************
-//
-//! select
-//!
-//! @param[in] nfds the highest-numbered file descriptor in any of the
-//! three sets, plus 1.
-//! @param[out] writesds socket descriptors list for write monitoring
-//! @param[out] readsds socket descriptors list for read monitoring
-//! @param[out] exceptsds socket descriptors list for exception monitoring
-//! @param[in] timeout is an upper bound on the amount of time elapsed
-//! before select() returns. Null means infinity
-//! timeout. The minimum timeout is 5 milliseconds,
-//! less than 5 milliseconds will be set
-//! automatically to 5 milliseconds.
-//! @return On success, select() returns the number of file descriptors
-//! contained in the three returned descriptor sets (that is, the
-//! total number of bits that are set in readfds, writefds,
-//! exceptfds) which may be zero if the timeout expires before
-//! anything interesting happens.
-//! On error, -1 is returned.
-//! *readsds - return the sockets on which Read request will
-//! return without delay with valid data.
-//! *writesds - return the sockets on which Write request
-//! will return without delay.
-//! *exceptsds - return the sockets which closed recently.
-//!
-//! @brief Monitor socket activity
-//! Select allow a program to monitor multiple file descriptors,
-//! waiting until one or more of the file descriptors become
-//! "ready" for some class of I/O operation
-//!
-//! @Note If the timeout value set to less than 5ms it will automatically set
-//! to 5ms to prevent overload of the system
-//!
-//! @sa socket
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds,
-struct cc3000_timeval *timeout)
-{
- UINT8 *ptr, *args;
- tBsdSelectRecvParams tParams;
- UINT32 is_blocking;
-
- if( timeout == NULL)
- {
- is_blocking = 1; /* blocking , infinity timeout */
- }
- else
- {
- is_blocking = 0; /* no blocking, timeout */
- }
-
- // Fill in HCI packet structure
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, nfds);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, is_blocking);
- args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0));
- args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0));
- args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0));
-
- if (timeout)
- {
- if ( 0 == timeout->tv_sec && timeout->tv_usec <
- SELECT_TIMEOUT_MIN_MICRO_SECONDS)
- {
- timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
- }
- args = UINT32_TO_STREAM(args, timeout->tv_sec);
- args = UINT32_TO_STREAM(args, timeout->tv_usec);
- }
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);
-
- // Update actually read FD
- if (tParams.iStatus >= 0)
- {
- if (readsds)
- {
- memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
- }
-
- if (writesds)
- {
- memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd));
- }
-
- if (exceptsds)
- {
- memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd));
- }
-
- return(tParams.iStatus);
-
- }
- else
- {
- CC3000_EXPORT(errno) = tParams.iStatus;
- return(-1);
- }
-}
-
-//*****************************************************************************
-//
-//! setsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[in] optval specifies a value for the option
-//! @param[in] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa getsockopt
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval,
- socklen_t optlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, level);
- args = UINT32_TO_STREAM(args, optname);
- args = UINT32_TO_STREAM(args, 0x00000008);
- args = UINT32_TO_STREAM(args, optlen);
- ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_SETSOCKOPT,
- ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);
-
- if (ret >= 0)
- {
- return (0);
- }
- else
- {
- CC3000_EXPORT(errno) = ret;
- return ret;
- }
-}
-#endif
-
-//*****************************************************************************
-//
-//! getsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[out] optval specifies a value for the option
-//! @param[out] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa setsockopt
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(getsockopt) (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen)
-{
- UINT8 *ptr, *args;
- tBsdGetSockOptReturnParams tRetParams;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, level);
- args = UINT32_TO_STREAM(args, optname);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_GETSOCKOPT,
- ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);
-
- if (((INT8)tRetParams.iStatus) >= 0)
- {
- *optlen = 4;
- memcpy(optval, tRetParams.ucOptValue, 4);
- return (0);
- }
- else
- {
- CC3000_EXPORT(errno) = tRetParams.iStatus;
- return CC3000_EXPORT(errno);
- }
-}
-
-//*****************************************************************************
-//
-//! simple_link_recv
-//!
-//! @param sd socket handle
-//! @param buf read buffer
-//! @param len buffer length
-//! @param flags indicates blocking or non-blocking operation
-//! @param from pointer to an address structure indicating source address
-//! @param fromlen source address structure size
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief Read data from socket
-//! Return the length of the message on successful completion.
-//! If a message is too long to fit in the supplied buffer,
-//! excess bytes may be discarded depending on the type of
-//! socket the message is received from
-//
-//*****************************************************************************
-static INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
- socklen_t *fromlen, INT32 opcode)
-{
- UINT8 *ptr, *args;
- tBsdReadReturnParams tSocketReadEvent;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, len);
- args = UINT32_TO_STREAM(args, flags);
-
- // Generate the read command, and wait for the
- hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
-
- // In case the number of bytes is more then zero - read data
- if (tSocketReadEvent.iNumberOfBytes > 0)
- {
- // Wait for the data in a synchronous way. Here we assume that the bug is
- // big enough to store also parameters of receive from too....
- SimpleLinkWaitData(buf, (UINT8 *)from, (UINT8 *)fromlen);
- }
-
- CC3000_EXPORT(errno) = tSocketReadEvent.iNumberOfBytes;
-
- return(tSocketReadEvent.iNumberOfBytes);
-}
-
-//*****************************************************************************
-//
-//! recv
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief function receives a message from a connection-mode socket
-//!
-//! @sa recvfrom
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags)
-{
- return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
-}
-
-//*****************************************************************************
-//
-//! recvfrom
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//! @param[in] from pointer to an address structure indicating the source
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param[in] fromlen source address tructure size
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief read data from socket
-//! function receives a message from a connection-mode or
-//! connectionless-mode socket. Note that raw sockets are not
-//! supported.
-//!
-//! @sa recv
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
- socklen_t *fromlen)
-{
- return(simple_link_recv(sd, buf, len, flags, from, fromlen,
- HCI_CMND_RECVFROM));
-}
-
-//*****************************************************************************
-//
-//! simple_link_send
-//!
-//! @param sd socket handle
-//! @param buf write buffer
-//! @param len buffer length
-//! @param flags On this version, this parameter is not supported
-//! @param to pointer to an address structure indicating destination
-//! address
-//! @param tolen destination address structure size
-//!
-//! @return Return the number of bytes transmitted, or -1 if an error
-//! occurred, or -2 in case there are no free buffers available
-//! (only when SEND_NON_BLOCKING is enabled)
-//!
-//! @brief This function is used to transmit a message to another
-//! socket
-//
-//*****************************************************************************
-static INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags,
- const sockaddr *to, INT32 tolen, INT32 opcode)
-{
- UINT8 uArgSize=0, addrlen;
- UINT8 *ptr, *pDataPtr=0, *args;
- UINT32 addr_offset=0;
- INT16 res;
- tBsdReadReturnParams tSocketSendEvent;
-
- // Check the bsd_arguments
- if (0 != (res = HostFlowControlConsumeBuff(sd)))
- {
- return res;
- }
-
- //Update the number of sent packets
- tSLInformation.NumberOfSentPackets++;
-
- // Allocate a buffer and construct a packet and send it over spi
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_DATA);
-
- // Update the offset of data and parameters according to the command
- switch(opcode)
- {
- case HCI_CMND_SENDTO:
- {
- addr_offset = len + sizeof(len) + sizeof(len);
- addrlen = 8;
- uArgSize = SOCKET_SENDTO_PARAMS_LEN;
- pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
- break;
- }
-
- case HCI_CMND_SEND:
- {
- tolen = 0;
- to = NULL;
- uArgSize = HCI_CMND_SEND_ARG_LENGTH;
- pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
- break;
- }
-
- default:
- {
- break;
- }
- }
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
- args = UINT32_TO_STREAM(args, len);
- args = UINT32_TO_STREAM(args, flags);
-
- if (opcode == HCI_CMND_SENDTO)
- {
- args = UINT32_TO_STREAM(args, addr_offset);
- args = UINT32_TO_STREAM(args, addrlen);
- }
-
- // Copy the data received from user into the TX Buffer
- ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len);
-
- // In case we are using SendTo, copy the to parameters
- if (opcode == HCI_CMND_SENDTO)
- {
- ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen);
- }
-
- // Initiate a HCI command
- hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen);
-
- if (opcode == HCI_CMND_SENDTO)
- SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent);
- else
- SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent);
-
- return (len);
-}
-
-
-//*****************************************************************************
-//
-//! send
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa sendto
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags)
-{
- return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
-}
-
-//*****************************************************************************
-//
-//! sendto
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//! @param to pointer to an address structure indicating the destination
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param tolen destination address structure size
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa send
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to,
- socklen_t tolen)
-{
- return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
-}
-
-//*****************************************************************************
-//
-//! mdnsAdvertiser
-//!
-//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature
-//! @param[in] deviceServiceName Service name as part of the published
-//! canonical domain name
-//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars
-//!
-//!
-//! @return On success, zero is returned, return SOC_ERROR if socket was not
-//! opened successfully, or if an error occurred.
-//!
-//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself.
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength)
-{
- INT8 ret;
- UINT8 *pTxBuffer, *pArgs;
-
- if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH)
- {
- return EFAIL;
- }
-
- pTxBuffer = tSLInformation.pucTxCommandBuffer;
- pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
-
- // Fill in HCI packet structure
- pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled);
- pArgs = UINT32_TO_STREAM(pArgs, 8);
- pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength);
- ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret);
-
- return ret;
-
-}
-
-
-//*****************************************************************************
-//
-//! getmssvalue
-//!
-//! @param[in] sd socket descriptor
-//!
-//! @return On success, returns the MSS value of a TCP connection
-//!
-//! @brief Returns the MSS value of a TCP connection according to the socket descriptor
-//
-//*****************************************************************************
-UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd)
-{
- UINT8 *ptr, *args;
- UINT16 ret;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret);
-
- return ret;
-}
diff --git a/drivers/cc3000/src/wlan.c b/drivers/cc3000/src/wlan.c
deleted file mode 100644
index 6385937778ccc..0000000000000
--- a/drivers/cc3000/src/wlan.c
+++ /dev/null
@@ -1,1252 +0,0 @@
-/*****************************************************************************
-*
-* wlan.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup wlan_api
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include "wlan.h"
-#include "hci.h"
-#include "ccspi.h"
-#include "socket.h"
-#include "nvmem.h"
-#include "security.h"
-#include "evnt_handler.h"
-
-
-volatile sSimplLinkInformation tSLInformation;
-
-#define SMART_CONFIG_PROFILE_SIZE 67 // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length)
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-UINT8 key[AES128_KEY_SIZE];
-UINT8 profileArray[SMART_CONFIG_PROFILE_SIZE];
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-/* patches type */
-#define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01
-#define PATCHES_HOST_TYPE_WLAN_FW 0x02
-#define PATCHES_HOST_TYPE_BOOTLOADER 0x03
-
-#define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16)
-#define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3)
-#define ETH_ALEN (6)
-#define MAXIMAL_SSID_LENGTH (32)
-
-#define SL_PATCHES_REQUEST_DEFAULT (0)
-#define SL_PATCHES_REQUEST_FORCE_HOST (1)
-#define SL_PATCHES_REQUEST_FORCE_NONE (2)
-
-
-#define WLAN_SEC_UNSEC (0)
-#define WLAN_SEC_WEP (1)
-#define WLAN_SEC_WPA (2)
-#define WLAN_SEC_WPA2 (3)
-
-
-#define WLAN_SL_INIT_START_PARAMS_LEN (1)
-#define WLAN_PATCH_PARAMS_LENGTH (8)
-#define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12)
-#define WLAN_DEL_PROFILE_PARAMS_LEN (4)
-#define WLAN_SET_MASK_PARAMS_LEN (4)
-#define WLAN_SET_SCAN_PARAMS_LEN (100)
-#define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4)
-#define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24)
-#define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36)
-#define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44)
-#define WLAN_CONNECT_PARAM_LEN (29)
-#define WLAN_SMART_CONFIG_START_PARAMS_LEN (4)
-
-
-
-
-//*****************************************************************************
-//
-//! SimpleLink_Init_Start
-//!
-//! @param usPatchesAvailableAtHost flag to indicate if patches available
-//! from host or from EEPROM. Due to the
-//! fact the patches are burn to the EEPROM
-//! using the patch programmer utility, the
-//! patches will be available from the EEPROM
-//! and not from the host.
-//!
-//! @return none
-//!
-//! @brief Send HCI_CMND_SIMPLE_LINK_START to CC3000
-//
-//*****************************************************************************
-static void SimpleLink_Init_Start(UINT16 usPatchesAvailableAtHost)
-{
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_NONE : SL_PATCHES_REQUEST_DEFAULT));
-
- // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000
- hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN);
-
- SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0);
-}
-
-
-
-//*****************************************************************************
-//
-//! wlan_init
-//!
-//! @param sWlanCB Asynchronous events callback.
-//! 0 no event call back.
-//! -call back parameters:
-//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event,
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event,
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done,
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report,
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive.
-//! 2) data: pointer to extra data that received by the event
-//! (NULL no data).
-//! 3) length: data length.
-//! -Events with extra data:
-//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask,
-//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes
-//! for DNS server.
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent,
-//! 4 bytes Packets received, 4 bytes Min round time,
-//! 4 bytes Max round time and 4 bytes for Avg round time.
-//!
-//! @param sFWPatches 0 no patch or pointer to FW patches
-//! @param sDriverPatches 0 no patch or pointer to driver patches
-//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches
-//! @param sReadWlanInterruptPin init callback. the callback read wlan
-//! interrupt status.
-//! @param sWlanInterruptEnable init callback. the callback enable wlan
-//! interrupt.
-//! @param sWlanInterruptDisable init callback. the callback disable wlan
-//! interrupt.
-//! @param sWriteWlanPin init callback. the callback write value
-//! to device pin.
-//!
-//! @return none
-//!
-//! @sa wlan_set_event_mask , wlan_start , wlan_stop
-//!
-//! @brief Initialize wlan driver
-//!
-//! @warning This function must be called before ANY other wlan driver function
-//
-//*****************************************************************************
-
-void wlan_init( tWlanCB sWlanCB,
- tFWPatches sFWPatches,
- tDriverPatches sDriverPatches,
- tBootLoaderPatches sBootLoaderPatches,
- tWlanReadInteruptPin sReadWlanInterruptPin,
- tWlanInterruptEnable sWlanInterruptEnable,
- tWlanInterruptDisable sWlanInterruptDisable,
- tWriteWlanPin sWriteWlanPin)
-{
-
- tSLInformation.sFWPatches = sFWPatches;
- tSLInformation.sDriverPatches = sDriverPatches;
- tSLInformation.sBootLoaderPatches = sBootLoaderPatches;
-
- // init io callback
- tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin;
- tSLInformation.WlanInterruptEnable = sWlanInterruptEnable;
- tSLInformation.WlanInterruptDisable = sWlanInterruptDisable;
- tSLInformation.WriteWlanPin = sWriteWlanPin;
-
- //init asynchronous events callback
- tSLInformation.sWlanCB= sWlanCB;
-
- // By default TX Complete events are routed to host too
- tSLInformation.InformHostOnTxComplete = 1;
-}
-
-//*****************************************************************************
-//
-//! SpiReceiveHandler
-//!
-//! @param pvBuffer - pointer to the received data buffer
-//! The function triggers Received event/data processing
-//!
-//! @param Pointer to the received data
-//! @return none
-//!
-//! @brief The function triggers Received event/data processing. It is
-//! called from the SPI library to receive the data
-//
-//*****************************************************************************
-void SpiReceiveHandler(void *pvBuffer)
-{
- tSLInformation.usEventOrDataReceived = 1;
- tSLInformation.pucReceivedData = (UINT8 *)pvBuffer;
-
- hci_unsolicited_event_handler();
-}
-
-
-//*****************************************************************************
-//
-//! wlan_start
-//!
-//! @param usPatchesAvailableAtHost - flag to indicate if patches available
-//! from host or from EEPROM. Due to the
-//! fact the patches are burn to the EEPROM
-//! using the patch programmer utility, the
-//! patches will be available from the EEPROM
-//! and not from the host.
-//!
-//! @return none
-//!
-//! @brief Start WLAN device. This function asserts the enable pin of
-//! the device (WLAN_EN), starting the HW initialization process.
-//! The function blocked until device Initialization is completed.
-//! Function also configure patches (FW, driver or bootloader)
-//! and calls appropriate device callbacks.
-//!
-//! @Note Prior calling the function wlan_init shall be called.
-//! @Warning This function must be called after wlan_init and before any
-//! other wlan API
-//! @sa wlan_init , wlan_stop
-//!
-//
-//*****************************************************************************
-#define TIMEOUT (500000)
-
-int wlan_start(UINT16 usPatchesAvailableAtHost)
-{
-
- UINT32 ulSpiIRQState;
- UINT32 wlan_timeout;
-
- tSLInformation.NumberOfSentPackets = 0;
- tSLInformation.NumberOfReleasedPackets = 0;
- tSLInformation.usRxEventOpcode = 0;
- tSLInformation.usNumberOfFreeBuffers = 0;
- tSLInformation.usSlBufferLength = 0;
- tSLInformation.usBufferSize = 0;
- tSLInformation.usRxDataPending = 0;
- tSLInformation.slTransmitDataError = 0;
- tSLInformation.usEventOrDataReceived = 0;
- tSLInformation.pucReceivedData = 0;
-
- // Allocate the memory for the RX/TX data transactions
- tSLInformation.pucTxCommandBuffer = (UINT8 *)wlan_tx_buffer;
-
- // init spi
- SpiOpen(SpiReceiveHandler);
-
- // Check the IRQ line
- ulSpiIRQState = tSLInformation.ReadWlanInterruptPin();
-
- // Chip enable: toggle WLAN EN line
- tSLInformation.WriteWlanPin( WLAN_ENABLE );
-
- wlan_timeout = TIMEOUT;
- if (ulSpiIRQState) {
- // wait till the IRQ line goes low
- while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout)
- {
- }
- }
- else
- {
- // wait till the IRQ line goes high and than low
- while(tSLInformation.ReadWlanInterruptPin() == 0 && --wlan_timeout)
- {
- }
-
- if (wlan_timeout == 0) {
- return -1;
- }
-
- wlan_timeout = TIMEOUT;
- while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout)
- {
- }
- }
-
- if (wlan_timeout ==0) {
- return -1;
- }
-
- SimpleLink_Init_Start(usPatchesAvailableAtHost);
-
- // Read Buffer's size and finish
- hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0);
- SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0);
-
- return 0;
-}
-
-
-//*****************************************************************************
-//
-//! wlan_stop
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Stop WLAN device by putting it into reset state.
-//!
-//! @sa wlan_start
-//
-//*****************************************************************************
-
-void wlan_stop(void)
-{
- // Chip disable
- tSLInformation.WriteWlanPin( WLAN_DISABLE );
-
- // Wait till IRQ line goes high...
- while(tSLInformation.ReadWlanInterruptPin() == 0)
- {
- }
-
- // Free the used by WLAN Driver memory
- if (tSLInformation.pucTxCommandBuffer)
- {
- tSLInformation.pucTxCommandBuffer = 0;
- }
-
- SpiClose();
-}
-
-
-//*****************************************************************************
-//
-//! wlan_connect
-//!
-//! @param sec_type security options:
-//! WLAN_SEC_UNSEC,
-//! WLAN_SEC_WEP (ASCII support only),
-//! WLAN_SEC_WPA or WLAN_SEC_WPA2
-//! @param ssid up to 32 bytes and is ASCII SSID of the AP
-//! @param ssid_len length of the SSID
-//! @param bssid 6 bytes specified the AP bssid
-//! @param key up to 32 bytes specified the AP security key
-//! @param key_len key length
-//!
-//! @return On success, zero is returned. On error, negative is returned.
-//! Note that even though a zero is returned on success to trigger
-//! connection operation, it does not mean that CCC3000 is already
-//! connected. An asynchronous "Connected" event is generated when
-//! actual association process finishes and CC3000 is connected to
-//! the AP. If DHCP is set, An asynchronous "DHCP" event is
-//! generated when DHCP process is finish.
-//!
-//!
-//! @brief Connect to AP
-//! @warning Please Note that when connection to AP configured with security
-//! type WEP, please confirm that the key is set as ASCII and not
-//! as HEX.
-//! @sa wlan_disconnect
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len,
- UINT8 *bssid, UINT8 *key, INT32 key_len)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
- UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0};
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in command buffer
- args = UINT32_TO_STREAM(args, 0x0000001c);
- args = UINT32_TO_STREAM(args, ssid_len);
- args = UINT32_TO_STREAM(args, ulSecType);
- args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
- args = UINT32_TO_STREAM(args, key_len);
- args = UINT16_TO_STREAM(args, 0);
-
- // padding shall be zeroed
- if(bssid)
- {
- ARRAY_TO_STREAM(args, bssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
-
- ARRAY_TO_STREAM(args, ssid, ssid_len);
-
- if(key_len && key)
- {
- ARRAY_TO_STREAM(args, key, key_len);
- }
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
- ssid_len + key_len - 1);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-#else
-INT32 wlan_connect(CHAR *ssid, INT32 ssid_len)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
- UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0};
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in command buffer
- args = UINT32_TO_STREAM(args, 0x0000001c);
- args = UINT32_TO_STREAM(args, ssid_len);
- args = UINT32_TO_STREAM(args, 0);
- args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
- args = UINT32_TO_STREAM(args, 0);
- args = UINT16_TO_STREAM(args, 0);
-
- // padding shall be zeroed
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- ARRAY_TO_STREAM(args, ssid, ssid_len);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
- ssid_len - 1);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_disconnect
-//!
-//! @return 0 disconnected done, other CC3000 already disconnected
-//!
-//! @brief Disconnect connection from AP.
-//!
-//! @sa wlan_connect
-//
-//*****************************************************************************
-
-INT32 wlan_disconnect()
-{
- INT32 ret;
- UINT8 *ptr;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_connection_policy
-//!
-//! @param should_connect_to_open_ap enable(1), disable(0) connect to any
-//! available AP. This parameter corresponds to the configuration of
-//! item # 3 in the brief description.
-//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries
-//! to connect to the last connected AP. This parameter corresponds
-//! to the configuration of item # 1 in the brief description.
-//! @param auto_start enable(1), disable(0) auto connect
-//! after reset and periodically reconnect if needed. This
-//! configuration configures option 2 in the above description.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief When auto is enabled, the device tries to connect according
-//! the following policy:
-//! 1) If fast connect is enabled and last connection is valid,
-//! the device will try to connect to it without the scanning
-//! procedure (fast). The last connection will be marked as
-//! invalid, due to adding/removing profile.
-//! 2) If profile exists, the device will try to connect it
-//! (Up to seven profiles).
-//! 3) If fast and profiles are not found, and open mode is
-//! enabled, the device will try to connect to any AP.
-//! * Note that the policy settings are stored in the CC3000 NVMEM.
-//!
-//! @sa wlan_add_profile , wlan_ioctl_del_profile
-//
-//*****************************************************************************
-
-INT32 wlan_ioctl_set_connection_policy(UINT32 should_connect_to_open_ap,
- UINT32 ulShouldUseFastConnect,
- UINT32 ulUseProfiles)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, should_connect_to_open_ap);
- args = UINT32_TO_STREAM(args, ulShouldUseFastConnect);
- args = UINT32_TO_STREAM(args, ulUseProfiles);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY,
- ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_add_profile
-//!
-//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2
-//! @param ucSsid ssid SSID up to 32 bytes
-//! @param ulSsidLen ssid length
-//! @param ucBssid bssid 6 bytes
-//! @param ulPriority ulPriority profile priority. Lowest priority:0.
-//! Important Note: Smartconfig process (in unencrypted mode)
-//! stores the profile internally with priority 1, so changing
-//! priorities when adding new profiles should be done with extra care
-//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security
-//! @param ulGroupCipher_TxKeyIndex key index
-//! @param ulKeyMgmt KEY management
-//! @param ucPf_OrKey security key
-//! @param ulPassPhraseLen security key length for WPA\WPA2
-//!
-//! @return On success, index (1-7) of the stored profile is returned.
-//! On error, -1 is returned.
-//!
-//! @brief When auto start is enabled, the device connects to
-//! station from the profiles table. Up to 7 profiles are supported.
-//! If several profiles configured the device choose the highest
-//! priority profile, within each priority group, device will choose
-//! profile based on security policy, signal strength, etc
-//! parameters. All the profiles are stored in CC3000 NVMEM.
-//!
-//! @sa wlan_ioctl_del_profile
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_add_profile(UINT32 ulSecType,
- UINT8* ucSsid,
- UINT32 ulSsidLen,
- UINT8 *ucBssid,
- UINT32 ulPriority,
- UINT32 ulPairwiseCipher_Or_TxKeyLen,
- UINT32 ulGroupCipher_TxKeyIndex,
- UINT32 ulKeyMgmt,
- UINT8* ucPf_OrKey,
- UINT32 ulPassPhraseLen)
-{
- UINT16 arg_len=0;
- INT32 ret;
- UINT8 *ptr;
- INT32 i = 0;
- UINT8 *args;
- UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0};
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- args = UINT32_TO_STREAM(args, ulSecType);
-
- // Setup arguments in accordance with the security type
- switch (ulSecType)
- {
- //OPEN
- case WLAN_SEC_UNSEC:
- {
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, ulSsidLen);
- args = UINT16_TO_STREAM(args, 0);
- if(ucBssid)
- {
- ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
- args = UINT32_TO_STREAM(args, ulPriority);
- ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
-
- arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen;
- }
- break;
-
- //WEP
- case WLAN_SEC_WEP:
- {
- args = UINT32_TO_STREAM(args, 0x00000020);
- args = UINT32_TO_STREAM(args, ulSsidLen);
- args = UINT16_TO_STREAM(args, 0);
- if(ucBssid)
- {
- ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
- args = UINT32_TO_STREAM(args, ulPriority);
- args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen);
- args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
- args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
- ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
-
- for(i = 0; i < 4; i++)
- {
- UINT8 *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen];
-
- ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen);
- }
-
- arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen +
- ulPairwiseCipher_Or_TxKeyLen * 4;
-
- }
- break;
-
- //WPA
- //WPA2
- case WLAN_SEC_WPA:
- case WLAN_SEC_WPA2:
- {
- args = UINT32_TO_STREAM(args, 0x00000028);
- args = UINT32_TO_STREAM(args, ulSsidLen);
- args = UINT16_TO_STREAM(args, 0);
- if(ucBssid)
- {
- ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
- args = UINT32_TO_STREAM(args, ulPriority);
- args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
- args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
- args = UINT32_TO_STREAM(args, ulKeyMgmt);
- args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen);
- args = UINT32_TO_STREAM(args, ulPassPhraseLen);
- ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
- ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen);
-
- arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen;
- }
-
- break;
- }
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE,
- ptr, arg_len);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret);
-
- return(ret);
-}
-#else
-INT32 wlan_add_profile(UINT32 ulSecType,
- UINT8* ucSsid,
- UINT32 ulSsidLen,
- UINT8 *ucBssid,
- UINT32 ulPriority,
- UINT32 ulPairwiseCipher_Or_TxKeyLen,
- UINT32 ulGroupCipher_TxKeyIndex,
- UINT32 ulKeyMgmt,
- UINT8* ucPf_OrKey,
- UINT32 ulPassPhraseLen)
-{
- return -1;
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_ioctl_del_profile
-//!
-//! @param index number of profile to delete
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Delete WLAN profile
-//!
-//! @Note In order to delete all stored profile, set index to 255.
-//!
-//! @sa wlan_add_profile
-//
-//*****************************************************************************
-
-INT32 wlan_ioctl_del_profile(UINT32 ulIndex)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulIndex);
- ret = EFAIL;
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE,
- ptr, WLAN_DEL_PROFILE_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_ioctl_get_scan_results
-//!
-//! @param[in] scan_timeout parameter not supported
-//! @param[out] ucResults scan results (_wlan_full_scan_results_args_t)
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Gets entry from scan result table.
-//! The scan results are returned one by one, and each entry
-//! represents a single AP found in the area. The following is a
-//! format of the scan result:
-//! - 4 Bytes: number of networks found
-//! - 4 Bytes: The status of the scan: 0 - aged results,
-//! 1 - results valid, 2 - no results
-//! - 42 bytes: Result entry, where the bytes are arranged as follows:
-//!
-//! - 1 bit isValid - is result valid or not
-//! - 7 bits rssi - RSSI value;
-//! - 2 bits: securityMode - security mode of the AP:
-//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2
-//! - 6 bits: SSID name length
-//! - 2 bytes: the time at which the entry has entered into
-//! scans result table
-//! - 32 bytes: SSID name
-//! - 6 bytes: BSSID
-//!
-//! @Note scan_timeout, is not supported on this version.
-//!
-//! @sa wlan_ioctl_set_scan_params
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout,
- UINT8 *ucResults)
-{
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, ulScanTimeout);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS,
- ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults);
-
- return(0);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_scan_params
-//!
-//! @param uiEnable - start/stop application scan:
-//! 1 = start scan with default interval value of 10 min.
-//! in order to set a different scan interval value apply the value
-//! in milliseconds. minimum 1 second. 0=stop). Wlan reset
-//! (wlan_stop() wlan_start()) is needed when changing scan interval
-//! value. Saved: No
-//! @param uiMinDwellTime minimum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 20)
-//! @param uiMaxDwellTime maximum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 30)
-//! @param uiNumOfProbeRequests max probe request between dwell time.
-//! Saved: yes. Recommended Value: 5 (Default:2)
-//! @param uiChannelMask bitwise, up to 13 channels (0x1fff).
-//! Saved: yes. Default: 0x7ff
-//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80)
-//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0)
-//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205)
-//! @param aiIntervalList pointer to array with 16 entries (16 channels)
-//! each entry (UINT32) holds timeout between periodic scan
-//! (connection scan) - in millisecond. Saved: yes. Default 2000ms.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief start and stop scan procedure. Set scan parameters.
-//!
-//! @Note uiDefaultTxPower, is not supported on this version.
-//!
-//! @sa wlan_ioctl_get_scan_results
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime,
- UINT32 uiMaxDwellTime,
- UINT32 uiNumOfProbeRequests,
- UINT32 uiChannelMask,INT32 iRSSIThreshold,
- UINT32 uiSNRThreshold,
- UINT32 uiDefaultTxPower,
- UINT32 *aiIntervalList)
-{
- UINT32 uiRes;
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, 36);
- args = UINT32_TO_STREAM(args, uiEnable);
- args = UINT32_TO_STREAM(args, uiMinDwellTime);
- args = UINT32_TO_STREAM(args, uiMaxDwellTime);
- args = UINT32_TO_STREAM(args, uiNumOfProbeRequests);
- args = UINT32_TO_STREAM(args, uiChannelMask);
- args = UINT32_TO_STREAM(args, iRSSIThreshold);
- args = UINT32_TO_STREAM(args, uiSNRThreshold);
- args = UINT32_TO_STREAM(args, uiDefaultTxPower);
- ARRAY_TO_STREAM(args, aiIntervalList, sizeof(UINT32) *
- SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM,
- ptr, WLAN_SET_SCAN_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes);
-
- return(uiRes);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_set_event_mask
-//!
-//! @param mask mask option:
-//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done
-//! HCI_EVNT_WLAN_UNSOL_INIT init done
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive
-//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission
-//! Saved: no.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Mask event according to bit mask. In case that event is
-//! masked (1), the device will not send the masked event to host.
-//
-//*****************************************************************************
-
-INT32 wlan_set_event_mask(UINT32 ulMask)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
-
- if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE)
- {
- tSLInformation.InformHostOnTxComplete = 0;
-
- // Since an event is a virtual event - i.e. it is not coming from CC3000
- // there is no need to send anything to the device if it was an only event
- if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE)
- {
- return 0;
- }
-
- ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE;
- ulMask |= HCI_EVNT_WLAN_UNSOL_BASE;
- }
- else
- {
- tSLInformation.InformHostOnTxComplete = 1;
- }
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulMask);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_EVENT_MASK,
- ptr, WLAN_SET_MASK_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_ioctl_statusget
-//!
-//! @param none
-//!
-//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING,
-//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED
-//!
-//! @brief get wlan status: disconnected, scanning, connecting or connected
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_ioctl_statusget(void)
-{
- INT32 ret;
- UINT8 *ptr;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET,
- ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret);
-
- return(ret);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_smart_config_start
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Start to acquire device profile. The device acquire its own
-//! profile, if profile message is found. The acquired AP information
-//! is stored in CC3000 EEPROM only in case AES128 encryption is used.
-//! In case AES128 encryption is not used, a profile is created by
-//! CC3000 internally.
-//!
-//! @Note An asynchronous event - Smart Config Done will be generated as soon
-//! as the process finishes successfully.
-//!
-//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop
-//
-//*****************************************************************************
-
-INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, algoEncryptedFlag);
- ret = EFAIL;
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr,
- WLAN_SMART_CONFIG_START_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_smart_config_stop
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Stop the acquire profile procedure
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix
-//
-//*****************************************************************************
-
-INT32 wlan_smart_config_stop(void)
-{
- INT32 ret;
- UINT8 *ptr;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_smart_config_set_prefix
-//!
-//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Configure station ssid prefix. The prefix is used internally
-//! in CC3000. It should always be TTT.
-//!
-//! @Note The prefix is stored in CC3000 NVMEM
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_stop
-//
-//*****************************************************************************
-
-INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- if (cNewPrefix == NULL)
- return ret;
- else // with the new Smart Config, prefix must be TTT
- {
- *cNewPrefix = 'T';
- *(cNewPrefix + 1) = 'T';
- *(cNewPrefix + 2) = 'T';
- }
-
- ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH);
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr,
- SL_SIMPLE_CONFIG_PREFIX_LENGTH);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_smart_config_process
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief process the acquired data and store it as a profile. The acquired
-//! AP information is stored in CC3000 EEPROM encrypted.
-//! The encrypted data is decrypted and stored as a profile.
-//! behavior is as defined by connection policy.
-//
-//*****************************************************************************
-
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-INT32 wlan_smart_config_process()
-{
- INT32 returnValue;
- UINT32 ssidLen, keyLen;
- UINT8 *decKeyPtr;
- UINT8 *ssidPtr;
-
- // read the key from EEPROM - fileID 12
- returnValue = aes_read_key(key);
-
- if (returnValue != 0)
- return returnValue;
-
- // read the received data from fileID #13 and parse it according to the followings:
- // 1) SSID LEN - not encrypted
- // 2) SSID - not encrypted
- // 3) KEY LEN - not encrypted. always 32 bytes long
- // 4) Security type - not encrypted
- // 5) KEY - encrypted together with true key length as the first byte in KEY
- // to elaborate, there are two corner cases:
- // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length
- // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31
- returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray);
-
- if (returnValue != 0)
- return returnValue;
-
- ssidPtr = &profileArray[1];
-
- ssidLen = profileArray[0];
-
- decKeyPtr = &profileArray[profileArray[0] + 3];
-
- aes_decrypt(decKeyPtr, key);
- if (profileArray[profileArray[0] + 1] > 16)
- aes_decrypt((UINT8 *)(decKeyPtr + 16), key);
-
- if (*(UINT8 *)(decKeyPtr +31) != 0)
- {
- if (*decKeyPtr == 31)
- {
- keyLen = 31;
- decKeyPtr++;
- }
- else
- {
- keyLen = 32;
- }
- }
- else
- {
- keyLen = *decKeyPtr;
- decKeyPtr++;
- }
-
- // add a profile
- switch (profileArray[profileArray[0] + 2])
- {
- case WLAN_SEC_UNSEC://None
- {
- returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type
- ssidPtr, // SSID
- ssidLen, // SSID length
- NULL, // BSSID
- 1, // Priority
- 0, 0, 0, 0, 0);
-
- break;
- }
-
- case WLAN_SEC_WEP://WEP
- {
- returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type
- ssidPtr, // SSID
- ssidLen, // SSID length
- NULL, // BSSID
- 1, // Priority
- keyLen, // KEY length
- 0, // KEY index
- 0,
- decKeyPtr, // KEY
- 0);
-
- break;
- }
-
- case WLAN_SEC_WPA://WPA
- case WLAN_SEC_WPA2://WPA2
- {
- returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type
- ssidPtr,
- ssidLen,
- NULL, // BSSID
- 1, // Priority
- 0x18, // PairwiseCipher
- 0x1e, // GroupCipher
- 2, // KEY management
- decKeyPtr, // KEY
- keyLen); // KEY length
-
- break;
- }
- }
-
- return returnValue;
-}
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3100/src/wlan.c b/drivers/cc3100/src/wlan.c
index 59adf02f02288..22be4d7ddf55e 100644
--- a/drivers/cc3100/src/wlan.c
+++ b/drivers/cc3100/src/wlan.c
@@ -536,10 +536,7 @@ _i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAd
*pNameLen = Msg.Rsp.Args.Common.SsidLen;
*pPriority = Msg.Rsp.Args.Common.Priority;
- if (NULL != Msg.Rsp.Args.Common.Bssid)
- {
- sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid));
- }
+ sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid));
sl_Memcpy(pName, EAP_PROFILE_SSID_STRING(&Msg), *pNameLen);
diff --git a/drivers/codec/wm8960.py b/drivers/codec/wm8960.py
deleted file mode 100644
index ad1cb1cbf872b..0000000000000
--- a/drivers/codec/wm8960.py
+++ /dev/null
@@ -1,753 +0,0 @@
-#
-# Driver class for the WM8960 Codec to be used e.g. with MIMXRT_1xxx Boards.
-# Derived from the NXP SDK drivers.
-#
-# Copyright (c) 2015, Freescale Semiconductor, Inc., (C-Code)
-# Copyright 2016-2021 NXP, (C-Code)
-# All rights reserved.
-#
-# Translated to MicroPython by Robert Hammelrath, 2022
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import array
-from micropython import const
-
-# Define the register addresses of WM8960.
-_LINVOL = const(0x0)
-_RINVOL = const(0x1)
-_LOUT1 = const(0x2)
-_ROUT1 = const(0x3)
-_CLOCK1 = const(0x4)
-_DACCTL1 = const(0x5)
-_DACCTL2 = const(0x6)
-_IFACE1 = const(0x7)
-_CLOCK2 = const(0x8)
-_IFACE2 = const(0x9)
-_LDAC = const(0xA)
-_RDAC = const(0xB)
-_RESET = const(0xF)
-_3D = const(0x10)
-_ALC1 = const(0x11)
-_ALC2 = const(0x12)
-_ALC3 = const(0x13)
-_NOISEG = const(0x14)
-_LADC = const(0x15)
-_RADC = const(0x16)
-_ADDCTL1 = const(0x17)
-# Register _ADDCTL2 = const(0x18)
-_POWER1 = const(0x19)
-_POWER2 = const(0x1A)
-_ADDCTL3 = const(0x1B)
-# Register _APOP1 = const(0x1C)
-# Register _APOP2 = const(0x1D)
-_LINPATH = const(0x20)
-_RINPATH = const(0x21)
-_LOUTMIX = const(0x22)
-_ROUTMIX = const(0x25)
-_MONOMIX1 = const(0x26)
-_MONOMIX2 = const(0x27)
-_LOUT2 = const(0x28)
-_ROUT2 = const(0x29)
-_MONO = const(0x2A)
-_INBMIX1 = const(0x2B)
-_INBMIX2 = const(0x2C)
-_BYPASS1 = const(0x2D)
-_BYPASS2 = const(0x2E)
-_POWER3 = const(0x2F)
-_ADDCTL4 = const(0x30)
-_CLASSD1 = const(0x31)
-# Register _CLASSD3 = const(0x33)
-_PLL1 = const(0x34)
-_PLL2 = const(0x35)
-_PLL3 = const(0x36)
-_PLL4 = const(0x37)
-
-# WM8960 PLLN range */
-_PLL_N_MIN_VALUE = const(6)
-_PLL_N_MAX_VALUE = const(12)
-
-# WM8960 CLOCK2 bits
-_CLOCK2_BCLK_DIV_MASK = const(0x0F)
-_CLOCK2_DCLK_DIV_MASK = const(0x1C0)
-_CLOCK2_DCLK_DIV_SHIFT = const(0x06)
-
-# Register _IFACE1
-_IFACE1_FORMAT_MASK = const(0x03)
-_IFACE1_WL_MASK = const(0x0C)
-_IFACE1_WL_SHIFT = const(0x02)
-_IFACE1_LRP_MASK = const(0x10)
-_IFACE1_MS_MASK = const(0x40)
-_IFACE1_DLRSWAP_MASK = const(0x20)
-_IFACE1_ALRSWAP_MASK = const(0x100)
-
-# Register _POWER1
-_POWER1_VREF_MASK = const(0x40)
-_POWER1_VREF_SHIFT = const(0x06)
-_POWER1_AINL_MASK = const(0x20)
-_POWER1_AINR_MASK = const(0x10)
-_POWER1_ADCL_MASK = const(0x08)
-_POWER1_ADCR_MASK = const(0x0)
-_POWER1_MICB_MASK = const(0x02)
-_POWER1_MICB_SHIFT = const(0x01)
-
-# Register _POWER2
-_POWER2_DACL_MASK = const(0x100)
-_POWER2_DACR_MASK = const(0x80)
-_POWER2_LOUT1_MASK = const(0x40)
-_POWER2_ROUT1_MASK = const(0x20)
-_POWER2_SPKL_MASK = const(0x10)
-_POWER2_SPKR_MASK = const(0x08)
-_POWER3_LMIC_MASK = const(0x20)
-_POWER3_RMIC_MASK = const(0x10)
-_POWER3_LOMIX_MASK = const(0x08)
-_POWER3_ROMIX_MASK = const(0x04)
-
-# Register _DACCTL1 .. 3
-_DACCTL1_MONOMIX_MASK = const(0x10)
-_DACCTL1_MONOMIX_SHIFT = const(0x4)
-_DACCTL1_DACMU_MASK = const(0x08)
-_DACCTL1_DEEM_MASK = const(0x06)
-_DACCTL1_DEEM_SHIFT = const(0x01)
-_DACCTL2_DACSMM_MASK = const(0x08)
-_DACCTL2_DACMR_MASK = const(0x04)
-_DACCTL3_ALCSR_MASK = const(0x07)
-
-# _WM8060_ALC1 .. 3
-_ALC_CHANNEL_MASK = const(0x180)
-_ALC_CHANNEL_SHIFT = const(0x7)
-_ALC_MODE_MASK = const(0x100)
-_ALC_MODE_SHIFT = const(0x8)
-_ALC_GAIN_MASK = const(0x70)
-_ALC_GAIN_SHIFT = const(0x4)
-_ALC_TARGET_MASK = const(0x0F)
-_ALC_ATTACK_MASK = const(0x0F)
-_ALC_DECAY_MASK = const(0xF0)
-_ALC_DECAY_SHIFT = const(4)
-_ALC_HOLD_MASK = const(0xF)
-
-# Register _NOISEG
-_NOISEG_LEVEL_SHIFT = const(3)
-
-_I2C_ADDR = const(0x1A)
-
-# WM8960 maximum volume values
-_MAX_VOLUME_ADC = const(0xFF)
-_MAX_VOLUME_DAC = const(0xFF)
-_MAX_VOLUME_HEADPHONE = const(0x7F)
-_MAX_VOLUME_LINEIN = const(0x3F)
-_MAX_VOLUME_SPEAKER = const(0x7F)
-
-# Config symbol names
-# Modules
-MODULE_ADC = const(0) # ADC module in WM8960
-MODULE_DAC = const(1) # DAC module in WM8960
-MODULE_VREF = const(2) # VREF module
-MODULE_HEADPHONE = const(3) # Headphone
-MODULE_MIC_BIAS = const(4) # Mic bias
-MODULE_MIC = const(5) # Input Mic
-MODULE_LINE_IN = const(6) # Analog in PGA
-MODULE_LINE_OUT = const(7) # Line out module
-MODULE_SPEAKER = const(8) # Speaker module
-MODULE_OMIX = const(9) # Output mixer
-MODULE_MONO_OUT = const(10) # Mono mix
-
-# Route
-ROUTE_BYPASS = const(0) # LINEIN->Headphone.
-ROUTE_PLAYBACK = const(1) # I2SIN->DAC->Headphone.
-ROUTE_PLAYBACK_RECORD = const(2) # I2SIN->DAC->Headphone, LINEIN->ADC->I2SOUT.
-ROUTE_RECORD = const(5) # LINEIN->ADC->I2SOUT.
-
-# Input
-INPUT_CLOSED = const(0) # Input device is closed
-INPUT_MIC1 = const(1) # Input as single ended mic, only use L/RINPUT1
-INPUT_MIC2 = const(2) # Input as diff. mic, use L/RINPUT1 and L/RINPUT2
-INPUT_MIC3 = const(3) # Input as diff. mic, use L/RINPUT1 and L/RINPUT3
-INPUT_LINE2 = const(4) # Input as line input, only use L/RINPUT2
-INPUT_LINE3 = const(5) # Input as line input, only use L/RINPUT3
-
-# ADC sync input
-SYNC_ADC = const(0) # Use ADCLRC pin for ADC sync
-SYNC_DAC = const(1) # used DACLRC pin for ADC sync
-
-# Protocol type
-BUS_I2S = const(2) # I2S type
-BUS_LEFT_JUSTIFIED = const(1) # Left justified mode
-BUS_RIGHT_JUSTIFIED = const(0) # Right justified mode
-BUS_PCMA = const(3) # PCM A mode
-BUS_PCMB = const(3 | (1 << 4)) # PCM B mode
-
-# Channel swap
-SWAP_NONE = const(0)
-SWAP_INPUT = const(1)
-SWAP_OUTPUT = const(2)
-
-# Mute settings
-MUTE_FAST = const(0)
-MUTE_SLOW = const(1)
-
-# ALC settings
-ALC_OFF = const(0)
-ALC_RIGHT = const(1)
-ALC_LEFT = const(2)
-ALC_STEREO = const(3)
-ALC_MODE = const(0) # ALC mode
-ALC_LIMITER = const(1) # Limiter mode
-
-# Clock Source
-SYSCLK_MCLK = const(0) # sysclk source from external MCLK
-SYSCLK_PLL = const(1) # sysclk source from internal PLL
-
-
-class Regs:
- # register cache of 56 register. Since registers cannot be read back, they are
- # kept in the table for modification
- # fmt: off
- cache = array.array("H", (
- 0x0097, 0x0097, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000,
- 0x000a, 0x01c0, 0x0000, 0x00ff, 0x00ff, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x007b, 0x0100, 0x0032, 0x0000,
- 0x00c3, 0x00c3, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0050,
- 0x0050, 0x0050, 0x0050, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0040, 0x0000, 0x0000, 0x0050, 0x0050, 0x0000, 0x0002,
- 0x0037, 0x004d, 0x0080, 0x0008, 0x0031, 0x0026, 0x00e9
- ))
- # fmt: on
-
- def __init__(self, i2c, i2c_address=_I2C_ADDR):
- self.value_buffer = bytearray(2)
- self.i2c = i2c
- self.i2c_address = i2c_address
-
- def __getitem__(self, reg):
- return self.cache[reg]
-
- def __setitem__(self, reg, value):
- if type(reg) is tuple:
- if type(value) is tuple:
- self[reg[0]] = value[0]
- self[reg[1]] = value[1]
- else:
- self[reg[0]] = value
- self[reg[1]] = value
- else:
- if type(value) is tuple:
- val = (self.cache[reg] & (~value[0] & 0xFFFF)) | value[1]
- else:
- val = value
- self.cache[reg] = val
- self.value_buffer[0] = (reg << 1) | ((val >> 8) & 0x01)
- self.value_buffer[1] = val & 0xFF
- self.i2c.writeto(self.i2c_address, self.value_buffer)
-
-
-class WM8960:
-
- _bit_clock_divider_table = {
- 2: 0,
- 3: 1,
- 4: 2,
- 6: 3,
- 8: 4,
- 11: 5,
- 12: 6,
- 16: 7,
- 22: 8,
- 24: 9,
- 32: 10,
- 44: 11,
- 48: 12,
- }
-
- _dac_divider_table = {
- 1.0 * 256: 0b000,
- 1.5 * 256: 0b001,
- 2 * 256: 0b010,
- 3 * 256: 0b011,
- 4 * 256: 0b100,
- 5.5 * 256: 0b101,
- 6 * 256: 0b110,
- }
-
- _audio_word_length_table = {
- 16: 0b00,
- 20: 0b01,
- 24: 0b10,
- 32: 0b11,
- }
-
- _alc_sample_rate_table = {
- 48000: 0,
- 44100: 0,
- 32000: 1,
- 24000: 2,
- 22050: 2,
- 16000: 3,
- 12000: 4,
- 11025: 4,
- 8000: 5,
- }
-
- _volume_config_table = {
- MODULE_ADC: (_MAX_VOLUME_ADC, _LADC, 0x100),
- MODULE_DAC: (_MAX_VOLUME_DAC, _LDAC, 0x100),
- MODULE_HEADPHONE: (_MAX_VOLUME_HEADPHONE, _LOUT1, 0x180),
- MODULE_LINE_IN: (_MAX_VOLUME_LINEIN, _LINVOL, 0x140),
- MODULE_SPEAKER: (_MAX_VOLUME_SPEAKER, _LOUT2, 0x180),
- }
-
- _input_config_table = {
- INPUT_CLOSED: None,
- INPUT_MIC1: (0x138, 0x117),
- INPUT_MIC2: (0x178, 0x117),
- INPUT_MIC3: (0x1B8, 0x117),
- INPUT_LINE2: (0, 0xE),
- INPUT_LINE3: (0, 0x70),
- }
-
- def __init__(
- self,
- i2c,
- sample_rate=16000,
- bits=16,
- swap=SWAP_NONE,
- route=ROUTE_PLAYBACK_RECORD,
- left_input=INPUT_MIC3,
- right_input=INPUT_MIC2,
- sysclk_source=SYSCLK_MCLK,
- mclk_freq=None,
- primary=False,
- adc_sync=SYNC_DAC,
- protocol=BUS_I2S,
- i2c_address=_I2C_ADDR,
- ):
- self.regs = regs = Regs(i2c, i2c_address)
- self.sample_rate = sample_rate
-
- # check parameter consistency and set the sysclk value
- if sysclk_source == SYSCLK_PLL:
- if sample_rate in (11025, 22050, 44100):
- sysclk = 11289600
- else:
- sysclk = 12288000
- if sysclk < sample_rate * 256:
- sysclk = sample_rate * 256
- if mclk_freq is None:
- mclk_freq = sysclk
- else: # sysclk_source == SYSCLK_MCLK
- if mclk_freq is None:
- mclk_freq = sample_rate * 256
- sysclk = mclk_freq
-
- regs[_RESET] = 0x00
- # VMID=50K, Enable VREF, AINL, AINR, ADCL and ADCR
- # I2S_IN (bit 0), I2S_OUT (bit 1), DAP (bit 4), DAC (bit 5), ADC (bit 6) are powered on
- regs[_POWER1] = 0xFE
- # Enable DACL, DACR, LOUT1, ROUT1, PLL down, SPKL, SPKR
- regs[_POWER2] = 0x1F8
- # Enable left and right channel input PGA, left and right output mixer
- regs[_POWER3] = 0x3C
-
- if adc_sync == SYNC_ADC:
- # ADC and DAC use different Frame Clock Pins
- regs[_IFACE2] = 0x00 # ADCLRC 0x00:Input 0x40:output.
- else:
- # ADC and DAC use the same Frame Clock Pin
- regs[_IFACE2] = 0x40 # ADCLRC 0x00:Input 0x40:output.
- self.set_data_route(route)
- self.set_protocol(protocol)
-
- if sysclk_source == SYSCLK_PLL:
- self.set_internal_pll_config(mclk_freq, sysclk)
- if primary:
- self.set_master_clock(sysclk, sample_rate, bits)
- # set master bit.
- self.regs[_IFACE1] = (0, _IFACE1_MS_MASK)
-
- self.set_speaker_clock(sysclk)
-
- # swap channels
- if swap & SWAP_INPUT:
- regs[_IFACE1] = (0, _IFACE1_ALRSWAP_MASK)
- if swap & SWAP_OUTPUT:
- regs[_IFACE1] = (0, _IFACE1_DLRSWAP_MASK)
-
- self.set_left_input(left_input)
- self.set_right_input(right_input)
-
- regs[_ADDCTL1] = 0x0C0
- regs[_ADDCTL4] = 0x60 # Set GPIO1 to 0.
-
- regs[_BYPASS1] = regs[_BYPASS2] = 0x0
- # ADC volume, 0dB
- regs[_LADC, _RADC] = 0x1C3
- # Digital DAC volume, 0dB
- regs[_LDAC, _RDAC] = 0x1FF
- # Headphone volume, LOUT1 and ROUT1, 0dB
- regs[_LOUT1, _ROUT1] = 0x16F
- # speaker volume 6dB
- regs[_LOUT2, _ROUT2] = 0x1FF
- # enable class D output
- regs[_CLASSD1] = 0xF7
- # Unmute DAC.
- regs[_DACCTL1] = 0x0000
- # Input PGA volume 0 dB
- regs[_LINVOL, _RINVOL] = 0x117
-
- self.config_data_format(sysclk, sample_rate, bits)
-
- def deinit(self):
-
- self.set_module(MODULE_ADC, False)
- self.set_module(MODULE_DAC, False)
- self.set_module(MODULE_VREF, False)
- self.set_module(MODULE_LINE_IN, False)
- self.set_module(MODULE_LINE_OUT, False)
- self.set_module(MODULE_SPEAKER, False)
-
- def set_internal_pll_config(self, input_mclk, output_clk):
- regs = self.regs
- pllF2 = output_clk * 4
- pll_prescale = 0
- sysclk_div = 1
- frac_mode = 0
-
- # disable PLL power
- regs[_POWER2] = (1, 0)
- regs[_CLOCK1] = (7, 0)
-
- pllN = pllF2 // input_mclk
- if pllN < _PLL_N_MIN_VALUE:
- input_mclk //= 2
- pll_prescale = 1
- pllN = pllF2 // input_mclk
- if pllN < _PLL_N_MIN_VALUE:
- sysclk_div = 2
- pllF2 *= 2
- pllN = pllF2 // input_mclk
-
- if (pllN < _PLL_N_MIN_VALUE) or (pllN > _PLL_N_MAX_VALUE):
- raise ValueError("Invalid MCLK vs. sysclk ratio")
-
- pllK = ((pllF2 % input_mclk) * (1 << 24)) // input_mclk
- if pllK != 0:
- frac_mode = 1
-
- regs[_PLL1] = (frac_mode << 5) | (pll_prescale << 4) | (pllN & 0x0F)
- regs[_PLL2] = (pllK >> 16) & 0xFF
- regs[_PLL3] = (pllK >> 8) & 0xFF
- regs[_PLL4] = pllK & 0xFF
- # enable PLL power
- regs[_POWER2] = (1, 1)
- regs[_CLOCK1] = (7, ((0 if sysclk_div == 1 else sysclk_div) << 1) | 1)
-
- def set_master_clock(self, sysclk, sample_rate, bit_width):
- bit_clock_divider = (sysclk * 2) // (sample_rate * bit_width * 2)
- try:
- reg_divider = self._bit_clock_divider_table[bit_clock_divider]
- except:
- raise ValueError("Invalid ratio of sysclk sample rate and bits")
- # configure the master bit clock divider
- self.regs[_CLOCK2] = (_CLOCK2_BCLK_DIV_MASK, reg_divider)
-
- def set_speaker_clock(self, sysclk):
- speaker_divider_table = (1.5, 2, 3, 4, 6, 8, 12, 16)
- for val in range(8):
- divider = speaker_divider_table[val]
- f = sysclk / divider
- if 500_000 < f < 1_000_000:
- break
- else:
- val = 7
- self.regs[_CLOCK2] = (
- _CLOCK2_DCLK_DIV_MASK,
- val << _CLOCK2_DCLK_DIV_SHIFT,
- )
-
- def set_module(self, module, is_enabled):
-
- is_enabled = 1 if is_enabled else 0
- regs = self.regs
-
- if module == MODULE_ADC:
-
- regs[_POWER1] = (
- _POWER1_ADCL_MASK | _POWER1_ADCR_MASK,
- (_POWER1_ADCL_MASK | _POWER1_ADCR_MASK) * is_enabled,
- )
-
- elif module == MODULE_DAC:
-
- regs[_POWER2] = (
- _POWER2_DACL_MASK | _POWER2_DACR_MASK,
- (_POWER2_DACL_MASK | _POWER2_DACR_MASK) * is_enabled,
- )
-
- elif module == MODULE_VREF:
-
- regs[_POWER1] = (
- _POWER1_VREF_MASK,
- (is_enabled << _POWER1_VREF_SHIFT),
- )
-
- elif module == MODULE_LINE_IN:
-
- regs[_POWER1] = (
- _POWER1_AINL_MASK | _POWER1_AINR_MASK,
- (_POWER1_AINL_MASK | _POWER1_AINR_MASK) * is_enabled,
- )
- regs[_POWER3] = (
- _POWER3_LMIC_MASK | _POWER3_RMIC_MASK,
- (_POWER3_LMIC_MASK | _POWER3_RMIC_MASK) * is_enabled,
- )
-
- elif module == MODULE_LINE_OUT:
-
- regs[_POWER2] = (
- _POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK,
- (_POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK) * is_enabled,
- )
-
- elif module == MODULE_MIC_BIAS:
-
- regs[_POWER1] = (
- _POWER1_MICB_MASK,
- (is_enabled << _POWER1_MICB_SHIFT),
- )
-
- elif module == MODULE_SPEAKER:
-
- regs[_POWER2] = (
- _POWER2_SPKL_MASK | _POWER2_SPKR_MASK,
- (_POWER2_SPKL_MASK | _POWER2_SPKR_MASK) * is_enabled,
- )
- regs[_CLASSD1] = 0xF7
-
- elif module == MODULE_OMIX:
-
- regs[_POWER3] = (
- _POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK,
- (_POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK) * is_enabled,
- )
-
- elif module == MODULE_MONO_OUT:
-
- regs[_MONOMIX1] = regs[_MONOMIX2] = is_enabled << 7
- regs[_MONO] = is_enabled << 6
-
- else:
- raise ValueError("Invalid module")
-
- def enable_module(self, module):
- self.set_module(module, True)
-
- def disable_module(self, module):
- self.set_module(module, False)
-
- def set_data_route(self, route):
- regs = self.regs
- if route == ROUTE_BYPASS:
- # Bypass means from line-in to HP
- # Left LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
- # Right RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
- regs[_LOUTMIX, _ROUTMIX] = 0x80
-
- elif route == ROUTE_PLAYBACK:
- # Data route I2S_IN-> DAC-> HP
- #
- # Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
- # Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
- regs[_LOUTMIX, _ROUTMIX] = 0x100
- regs[_POWER3] = 0x0C
- # Set power for DAC
- self.set_module(MODULE_DAC, True)
- self.set_module(MODULE_OMIX, True)
- self.set_module(MODULE_LINE_OUT, True)
-
- elif route == ROUTE_PLAYBACK_RECORD:
- #
- # Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
- # Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
- regs[_LOUTMIX, _ROUTMIX] = 0x100
- regs[_POWER3] = 0x3C
- self.set_module(MODULE_DAC, True)
- self.set_module(MODULE_ADC, True)
- self.set_module(MODULE_LINE_IN, True)
- self.set_module(MODULE_OMIX, True)
- self.set_module(MODULE_LINE_OUT, True)
-
- elif route == ROUTE_RECORD:
- # LINE_IN->ADC->I2S_OUT
- # Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
- regs[_POWER3] = 0x30
- # Power up ADC and AIN
- self.set_module(MODULE_LINE_IN, True)
- self.set_module(MODULE_ADC, True)
-
- else:
- raise ValueError("Invalid route")
-
- def set_left_input(self, input):
- if not input in self._input_config_table.keys():
- raise ValueError("Invalid input")
-
- input = self._input_config_table[input]
-
- regs = self.regs
- if input is None:
- regs[_POWER1] = (_POWER1_AINL_MASK | _POWER1_ADCL_MASK, 0)
- elif input[0] == 0:
- regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK)
- regs[_INBMIX1] = input
- else:
- regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK | _POWER1_MICB_MASK)
- regs[_LINPATH] = input[0]
- regs[_LINVOL] = input[1]
-
- def set_right_input(self, input):
- if not input in self._input_config_table.keys():
- raise ValueError("Invalid input name")
-
- input = self._input_config_table[input]
-
- regs = self.regs
- if input is None:
- regs[_POWER1] = (_POWER1_AINR_MASK | _POWER1_ADCR_MASK, 0)
- elif input[0] == 0:
- regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCR_MASK)
- regs[_INBMIX2] = input
- else:
- regs[_POWER1] = (0, _POWER1_AINR_MASK | _POWER1_ADCR_MASK | _POWER1_MICB_MASK)
- regs[_RINPATH] = input[0]
- regs[_RINVOL] = input[1]
-
- def set_protocol(self, protocol):
- self.regs[_IFACE1] = (
- _IFACE1_FORMAT_MASK | _IFACE1_LRP_MASK,
- protocol,
- )
-
- def config_data_format(self, sysclk, sample_rate, bits):
- # Compute sample rate divider, dac and adc are the same sample rate
- try:
- divider = self._dac_divider_table[sysclk // sample_rate]
- wl = self._audio_word_length_table[bits]
- except:
- raise ValueError("Invalid ratio sysclk/sample_rate or invalid bit length")
-
- self.regs[_CLOCK1] = (0x1F8, divider << 6 | divider << 3)
- self.regs[_IFACE1] = (_IFACE1_WL_MASK, wl << _IFACE1_WL_SHIFT)
-
- def volume(self, module, volume_l=None, volume_r=None):
- if not module in self._volume_config_table.keys():
- raise ValueError("Invalid module")
-
- if volume_l is None: # get volume
- vol_max, regnum, _ = self._volume_config_table[module]
- return (
- int((self.regs[regnum] & vol_max) * 100 / vol_max + 0.5),
- int((self.regs[regnum + 1] & vol_max) * 100 / vol_max + 0.5),
- )
- else: # set volume
- if volume_r is None:
- volume_r = volume_l
-
- if not ((0 <= volume_l <= 100) and (0 <= volume_r <= 100)):
- raise ValueError("Invalid value for volume")
- elif not module in self._volume_config_table.keys():
- raise ValueError("Invalid module")
-
- vol_max, regnum, flags = self._volume_config_table[module]
- self.regs[regnum] = int(volume_l * vol_max / 100 + 0.5) | flags
- self.regs[regnum + 1] = int(volume_r * vol_max / 100 + 0.5) | flags
-
- def mute(self, enable, soft=True, ramp=MUTE_FAST):
- enable = _DACCTL1_DACMU_MASK if enable else 0
- soft = _DACCTL2_DACSMM_MASK if soft else 0
- ramp = _DACCTL2_DACMR_MASK if ramp == MUTE_SLOW else 0
- self.regs[_DACCTL1] = (_DACCTL1_DACMU_MASK, enable)
- self.regs[_DACCTL2] = (
- _DACCTL2_DACSMM_MASK | _DACCTL2_DACMR_MASK,
- soft | ramp,
- )
-
- def expand_3d(self, depth=0):
- depth &= 0x0F
- cutoff = 0 if self.sample_rate >= 32000 else 0b1100000
- self.regs[_3D] = cutoff | depth << 1 | (1 if depth > 0 else 0)
-
- def mono(self, enable):
- enable = 1 if enable else 0
- self.regs[_DACCTL1] = (
- _DACCTL1_MONOMIX_MASK,
- enable << _DACCTL1_MONOMIX_SHIFT,
- )
-
- def alc_mode(self, channel, mode=ALC_MODE):
- if mode != ALC_MODE:
- mode = ALC_LIMITER
- channel &= 3
- self.regs[_ALC1] = (
- _ALC_CHANNEL_MASK,
- channel << _ALC_CHANNEL_SHIFT,
- )
- self.regs[_ALC3] = (_ALC_MODE_MASK, mode << _ALC_MODE_SHIFT)
- try:
- rate = _alc_sample_rate_table[self.sample_rate]
- except:
- rate = 0
- self.regs[_ADDCTL3] = (_DACCTL3_ALCSR_MASK, rate)
-
- def alc_gain(self, target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78):
- def limit(value, minval, maxval):
- value = int(value)
- if value < minval:
- value = minval
- if value > maxval:
- value = maxval
- return value
-
- target = limit((16 + (target * 2) // 3), 0, 15)
- max_gain = limit((max_gain + 12) // 6, 0, 7)
- min_gain = limit((min_gain * 4 + 69) // 24, 0, 7)
- noise_gate = limit((noise_gate * 2 + 153) // 3, -1, 31)
- self.regs[_ALC1] = (
- _ALC_GAIN_MASK | _ALC_TARGET_MASK,
- (max_gain << _ALC_GAIN_SHIFT) | target,
- )
- self.regs[_ALC2] = (_ALC_GAIN_MASK, (min_gain << _ALC_GAIN_SHIFT))
- if noise_gate >= 0:
- self.regs[_NOISEG] = noise_gate << _NOISEG_LEVEL_SHIFT | 1
- else:
- self.regs[_NOISEG] = 0
-
- def alc_time(self, attack=24, decay=192, hold=0):
- def logb(value, limit):
- value = int(value)
- lb = 0
- while value > 1:
- value >>= 1
- lb += 1
- if lb > limit:
- lb = limit
- return lb
-
- attack = logb(attack / 6, 7)
- decay = logb(decay / 24, 7)
- hold = logb((hold * 3) / 8, 15)
- self.regs[_ALC2] = (_ALC_HOLD_MASK, hold)
- self.regs[_ALC3] = (
- _ALC_DECAY_MASK | _ALC_ATTACK_MASK,
- (decay << _ALC_DECAY_SHIFT) | attack,
- )
-
- def deemphasis(self, enable):
- deem_table = (32000, 44100, 48000)
- enable = not not enable
- if enable and self.sample_rate in deem_table:
- val = deem_table.index(self.sample_rate) + 1
- else:
- val = 0
- self.regs[_DACCTL1] = (_DACCTL1_DEEM_MASK, val << _DACCTL1_DEEM_SHIFT)
diff --git a/drivers/cyw43/cyw43.h b/drivers/cyw43/cyw43.h
deleted file mode 100644
index 7d3e30f5d4eda..0000000000000
--- a/drivers/cyw43/cyw43.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018-2019 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef MICROPY_INCLUDED_STM32_CYW43_H
-#define MICROPY_INCLUDED_STM32_CYW43_H
-
-#include "lwip/netif.h"
-#include "lwip/dhcp.h"
-#include "shared/netutils/dhcpserver.h"
-#include "drivers/cyw43/cyw43_ll.h"
-
-// For trace_flags
-#define CYW43_TRACE_ASYNC_EV (0x0001)
-#define CYW43_TRACE_ETH_TX (0x0002)
-#define CYW43_TRACE_ETH_RX (0x0004)
-#define CYW43_TRACE_ETH_FULL (0x0008)
-#define CYW43_TRACE_MAC (0x0010)
-
-// Return value of cyw43_wifi_link_status
-#define CYW43_LINK_DOWN (0)
-#define CYW43_LINK_JOIN (1)
-#define CYW43_LINK_NOIP (2)
-#define CYW43_LINK_UP (3)
-#define CYW43_LINK_FAIL (-1)
-#define CYW43_LINK_NONET (-2)
-#define CYW43_LINK_BADAUTH (-3)
-
-typedef struct _cyw43_t {
- cyw43_ll_t cyw43_ll;
-
- uint8_t itf_state;
- uint32_t trace_flags;
-
- // State for async events
- volatile uint32_t wifi_scan_state;
- uint32_t wifi_join_state;
- void *wifi_scan_env;
- int (*wifi_scan_cb)(void*, const cyw43_ev_scan_result_t*);
-
- // Pending things to do
- bool pend_disassoc;
- bool pend_rejoin;
- bool pend_rejoin_wpa;
-
- // AP settings
- uint8_t ap_channel;
- uint8_t ap_auth;
- uint8_t ap_ssid_len;
- uint8_t ap_key_len;
- uint8_t ap_ssid[32];
- uint8_t ap_key[64];
-
- // lwIP data
- struct netif netif[2];
- struct dhcp dhcp_client;
- dhcp_server_t dhcp_server;
-} cyw43_t;
-
-extern cyw43_t cyw43_state;
-extern void (*cyw43_poll)(void);
-extern uint32_t cyw43_sleep;
-
-void cyw43_init(cyw43_t *self);
-void cyw43_deinit(cyw43_t *self);
-
-int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface);
-int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf);
-
-int cyw43_wifi_pm(cyw43_t *self, uint32_t pm);
-int cyw43_wifi_link_status(cyw43_t *self, int itf);
-void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up);
-int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]);
-int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*));
-
-static inline bool cyw43_wifi_scan_active(cyw43_t *self) {
- return self->wifi_scan_state == 1;
-}
-
-int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel);
-int cyw43_wifi_leave(cyw43_t *self, int itf);
-
-static inline void cyw43_wifi_ap_get_ssid(cyw43_t *self, size_t *len, const uint8_t **buf) {
- *len = self->ap_ssid_len;
- *buf = self->ap_ssid;
-}
-
-static inline void cyw43_wifi_ap_set_channel(cyw43_t *self, uint32_t channel) {
- self->ap_channel = channel;
-}
-
-static inline void cyw43_wifi_ap_set_ssid(cyw43_t *self, size_t len, const uint8_t *buf) {
- self->ap_ssid_len = MIN(len, sizeof(self->ap_ssid));
- memcpy(self->ap_ssid, buf, self->ap_ssid_len);
-}
-
-static inline void cyw43_wifi_ap_set_password(cyw43_t *self, size_t len, const uint8_t *buf) {
- self->ap_key_len = MIN(len, sizeof(self->ap_key));
- memcpy(self->ap_key, buf, self->ap_key_len);
-}
-
-static inline void cyw43_wifi_ap_set_auth(cyw43_t *self, uint32_t auth) {
- self->ap_auth = auth;
-}
-
-void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs);
-
-void cyw43_tcpip_init(cyw43_t *self, int itf);
-void cyw43_tcpip_deinit(cyw43_t *self, int itf);
-void cyw43_tcpip_set_link_up(cyw43_t *self, int itf);
-void cyw43_tcpip_set_link_down(cyw43_t *self, int itf);
-int cyw43_tcpip_link_status(cyw43_t *self, int itf);
-
-#endif // MICROPY_INCLUDED_STM32_CYW43_H
diff --git a/drivers/cyw43/cyw43_ctrl.c b/drivers/cyw43/cyw43_ctrl.c
deleted file mode 100644
index 203bc812ac13f..0000000000000
--- a/drivers/cyw43/cyw43_ctrl.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018-2019 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-#include "py/mperrno.h"
-#include "py/mphal.h"
-#include "drivers/cyw43/cyw43.h"
-#include "pendsv.h"
-#include "sdio.h"
-
-#define CYW_ENTER MICROPY_PY_LWIP_ENTER
-#define CYW_EXIT MICROPY_PY_LWIP_EXIT
-
-#ifdef pyb_pin_WL_HOST_WAKE
-#define USE_SDIOIT (0)
-#else
-#define USE_SDIOIT (1)
-#endif
-
-#define CYW43_SLEEP_MAX (50)
-
-#define WIFI_JOIN_STATE_ACTIVE (0x0001)
-#define WIFI_JOIN_STATE_FAIL (0x0002)
-#define WIFI_JOIN_STATE_NONET (0x0003)
-#define WIFI_JOIN_STATE_BADAUTH (0x0004)
-#define WIFI_JOIN_STATE_AUTH (0x0200)
-#define WIFI_JOIN_STATE_LINK (0x0400)
-#define WIFI_JOIN_STATE_KEYED (0x0800)
-#define WIFI_JOIN_STATE_ALL (0x0e01)
-
-#define CYW43_STA_IS_ACTIVE(self) (((self)->itf_state >> CYW43_ITF_STA) & 1)
-#define CYW43_AP_IS_ACTIVE(self) (((self)->itf_state >> CYW43_ITF_AP) & 1)
-
-cyw43_t cyw43_state;
-void (*cyw43_poll)(void);
-uint32_t cyw43_sleep;
-
-STATIC void cyw43_poll_func(void);
-STATIC void cyw43_wifi_ap_init(cyw43_t *self);
-STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up);
-
-static inline uint32_t cyw43_get_be16(const uint8_t *buf) {
- return buf[0] << 8 | buf[1];
-}
-
-static inline uint32_t cyw43_get_be32(const uint8_t *buf) {
- return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
-}
-
-static inline void cyw43_delay_ms(uint32_t ms) {
- mp_hal_delay_ms(ms);
-}
-
-/*******************************************************************************/
-// Initialisation and polling
-
-void cyw43_init(cyw43_t *self) {
- #ifdef pyb_pin_WL_HOST_WAKE
- mp_hal_pin_config(pyb_pin_WL_HOST_WAKE, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0);
- #endif
- mp_hal_pin_config(pyb_pin_WL_REG_ON, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0);
- mp_hal_pin_low(pyb_pin_WL_REG_ON);
- #ifdef pyb_pin_WL_RFSW_VDD
- mp_hal_pin_config(pyb_pin_WL_RFSW_VDD, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power
- mp_hal_pin_low(pyb_pin_WL_RFSW_VDD);
- #endif
-
- cyw43_ll_init(&self->cyw43_ll, self);
-
- self->itf_state = 0;
- self->wifi_scan_state = 0;
- self->wifi_join_state = 0;
- self->pend_disassoc = false;
- self->pend_rejoin= false;
- self->pend_rejoin_wpa = false;
- self->ap_channel = 3;
- self->ap_ssid_len = 0;
- self->ap_key_len = 0;
-
- cyw43_poll = NULL;
-}
-
-void cyw43_deinit(cyw43_t *self) {
- if (cyw43_poll == NULL) {
- return;
- }
-
- CYW_ENTER
-
- // Stop the TCP/IP network interfaces.
- cyw43_tcpip_deinit(self, 0);
- cyw43_tcpip_deinit(self, 1);
-
- // Turn off the SDIO bus.
- #if USE_SDIOIT
- sdio_enable_irq(false);
- #endif
- sdio_deinit();
-
- // Power off the WLAN chip and make sure all state is reset.
- cyw43_init(self);
-
- CYW_EXIT
-}
-
-STATIC int cyw43_ensure_up(cyw43_t *self) {
- if (cyw43_poll != NULL) {
- cyw43_ll_bus_sleep(&self->cyw43_ll, false);
- return 0;
- }
-
- CYW_ENTER
-
- // Disable the netif if it was previously up
- cyw43_tcpip_deinit(self, CYW43_ITF_STA);
- cyw43_tcpip_deinit(self, CYW43_ITF_AP);
- self->itf_state = 0;
-
- // Reset and power up the WL chip
- mp_hal_pin_low(pyb_pin_WL_REG_ON);
- cyw43_delay_ms(20);
- mp_hal_pin_high(pyb_pin_WL_REG_ON);
- cyw43_delay_ms(50);
-
- // Initialise SDIO bus
- // IRQ priority only needs to be higher than CYW_ENTER/EXIT protection (PENDSV)
- sdio_init(NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0));
-
- // Initialise the low-level driver
- uint8_t mac[6];
- mp_hal_get_mac(MP_HAL_MAC_WLAN0, mac);
- int ret = cyw43_ll_bus_init(&self->cyw43_ll, mac);
-
- if (ret != 0) {
- CYW_EXIT
- return ret;
- }
-
- // Enable async events from low-level driver
- cyw43_sleep = CYW43_SLEEP_MAX;
- cyw43_poll = cyw43_poll_func;
- #if USE_SDIOIT
- sdio_enable_irq(true);
- #else
- extern void extint_set(const pin_obj_t *pin, uint32_t mode);
- extint_set(pyb_pin_WL_HOST_WAKE, GPIO_MODE_IT_FALLING);
- #endif
-
- CYW_EXIT
-
- return ret;
-}
-
-// This function must always be executed at the level where CYW_ENTER is effectively active
-STATIC void cyw43_poll_func(void) {
- if (cyw43_poll == NULL) {
- // Poll scheduled during deinit, just ignore it
- return;
- }
-
- cyw43_t *self = &cyw43_state;
- cyw43_ll_process_packets(&self->cyw43_ll);
-
- if (self->pend_disassoc) {
- self->pend_disassoc = false;
- cyw43_ll_ioctl(&self->cyw43_ll, CYW43_IOCTL_SET_DISASSOC, 0, NULL, CYW43_ITF_STA);
- }
-
- if (self->pend_rejoin_wpa) {
- self->pend_rejoin_wpa = false;
- cyw43_ll_wifi_set_wpa_auth(&self->cyw43_ll);
- }
-
- if (self->pend_rejoin) {
- self->pend_rejoin = false;
- cyw43_ll_wifi_rejoin(&self->cyw43_ll);
- self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE;
- }
-
- if (cyw43_sleep == 0) {
- cyw43_ll_bus_sleep(&self->cyw43_ll, true);
- #if !USE_SDIOIT
- sdio_deinit(); // save power while WLAN bus sleeps
- #endif
- }
-
- #if USE_SDIOIT
- sdio_enable_irq(true);
- #endif
-}
-
-/*******************************************************************************/
-// Callback interface to low-level driver
-
-int cyw43_cb_read_host_interrupt_pin(void *cb_data) {
- #ifdef pyb_pin_WL_HOST_WAKE
- return mp_hal_pin_read(pyb_pin_WL_HOST_WAKE);
- #else
- return mp_hal_pin_read(pyb_pin_WL_SDIO_1);
- #endif
-}
-
-void cyw43_cb_ensure_awake(void *cb_data) {
- cyw43_sleep = CYW43_SLEEP_MAX;
- #if !USE_SDIOIT
- sdio_reenable();
- #endif
-}
-
-STATIC const char *cyw43_async_event_name_table[89] = {
- [0 ... 88] = NULL,
- [CYW43_EV_SET_SSID] = "SET_SSID",
- [CYW43_EV_JOIN] = "JOIN",
- [CYW43_EV_AUTH] = "AUTH",
- [CYW43_EV_DEAUTH_IND] = "DEAUTH_IND",
- [CYW43_EV_ASSOC] = "ASSOC",
- [CYW43_EV_DISASSOC] = "DISASSOC",
- [CYW43_EV_DISASSOC_IND] = "DISASSOC_IND",
- [CYW43_EV_LINK] = "LINK",
- [CYW43_EV_PSK_SUP] = "PSK_SUP",
- [CYW43_EV_ESCAN_RESULT] = "ESCAN_RESULT",
- [CYW43_EV_CSA_COMPLETE_IND] = "CSA_COMPLETE_IND",
- [CYW43_EV_ASSOC_REQ_IE] = "ASSOC_REQ_IE",
- [CYW43_EV_ASSOC_RESP_IE] = "ASSOC_RESP_IE",
-};
-
-STATIC void cyw43_dump_async_event(const cyw43_async_event_t *ev) {
- printf("[% 8d] ASYNC(%04x,",
- (int)mp_hal_ticks_ms(),
- (unsigned int)ev->flags
- );
- if (ev->event_type < MP_ARRAY_SIZE(cyw43_async_event_name_table)
- && cyw43_async_event_name_table[ev->event_type] != NULL) {
- printf("%s", cyw43_async_event_name_table[ev->event_type]);
- } else {
- printf("%u", (unsigned int)ev->event_type);
- }
- printf(",%u,%u,%u)\n",
- (unsigned int)ev->status,
- (unsigned int)ev->reason,
- (unsigned int)ev->interface
- );
-}
-
-void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev) {
- cyw43_t *self = cb_data;
-
- if (self->trace_flags & CYW43_TRACE_ASYNC_EV) {
- cyw43_dump_async_event(ev);
- }
-
- if (ev->event_type == CYW43_EV_ESCAN_RESULT && self->wifi_scan_state == 1) {
- // Escan result event
- if (ev->status == 8) {
- // Partial result
- int ret = self->wifi_scan_cb(self->wifi_scan_env, &ev->u.scan_result);
- if (ret != 0) {
- // TODO need to abort scan, or just ignore any more results
- }
- } else if (ev->status == 0) {
- // Scan complete
- self->wifi_scan_state = 2;
- }
-
- } else if (ev->event_type == CYW43_EV_DISASSOC) {
- cyw43_tcpip_set_link_down(self, CYW43_ITF_STA);
- self->wifi_join_state = 0x0000;
-
- /*
- } else if (ev->event_type == CYW43_EV_DISASSOC_IND) {
- if (ev->interface == CYW43_ITF_AP) {
- // Station disassociated with our AP, let DHCP server know so it can free the IP address
- dhcp_server_disassoc(&self->dhcp_server, buf + 24);
- }
- */
-
- // WiFi join events
- } else if (ev->event_type == CYW43_EV_PRUNE) {
- if (ev->status == 0 && ev->reason == 8) {
- // RSN mismatch, retry join with WPA auth
- self->pend_rejoin = true;
- self->pend_rejoin_wpa = true;
- pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func);
- }
- } else if (ev->event_type == CYW43_EV_SET_SSID) {
- if (ev->status == 0) {
- // Success setting SSID
- } else if (ev->status == 3 && ev->reason == 0) {
- self->wifi_join_state = WIFI_JOIN_STATE_NONET;
- // No matching SSID found (could be out of range, or down)
- } else {
- // Other failure setting SSID
- self->wifi_join_state = WIFI_JOIN_STATE_FAIL;
- }
- } else if (ev->event_type == CYW43_EV_AUTH) {
- if (ev->status == 0) {
- self->wifi_join_state |= WIFI_JOIN_STATE_AUTH;
- } else if (ev->status == 6) {
- // Unsolicited auth packet, ignore it
- } else {
- // Cannot authenticate
- self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
- }
- } else if (ev->event_type == CYW43_EV_DEAUTH_IND) {
- if (ev->status == 0 && ev->reason == 2) {
- // Deauth, probably because password was wrong; disassociate
- self->pend_disassoc = true;
- pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func);
- }
- } else if (ev->event_type == CYW43_EV_LINK) {
- if (ev->status == 0) {
- if (ev->flags & 1) {
- // Link is up
- if (ev->interface == CYW43_ITF_STA) {
- self->wifi_join_state |= WIFI_JOIN_STATE_LINK;
- } else {
- cyw43_tcpip_set_link_up(self, ev->interface);
- }
- } else {
- // Link is down
- cyw43_tcpip_set_link_down(self, ev->interface);
- }
- }
- } else if (ev->event_type == CYW43_EV_PSK_SUP) {
- if (ev->status == 6) { // WLC_SUP_KEYED
- self->wifi_join_state |= WIFI_JOIN_STATE_KEYED;
- } else if ((ev->status == 4 || ev->status == 8 || ev->status == 11) && ev->reason == 15) {
- // Timeout waiting for key exchange M1/M3/G1
- // Probably at edge of the cell, retry
- self->pend_rejoin = true;
- pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func);
- } else {
- // PSK_SUP failure
- self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
- }
- }
-
- if (self->wifi_join_state == WIFI_JOIN_STATE_ALL) {
- // STA connected
- self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE;
- cyw43_tcpip_set_link_up(self, CYW43_ITF_STA);
- }
-}
-
-/*******************************************************************************/
-// Ioctl and Ethernet interface
-
-int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) {
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return ret;
- }
-
- CYW_ENTER
- ret = cyw43_ll_ioctl(&self->cyw43_ll, cmd, len, buf, iface);
- CYW_EXIT
-
- return ret;
-}
-
-int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf) {
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return ret;
- }
-
- CYW_ENTER
- ret = cyw43_ll_send_ethernet(&self->cyw43_ll, itf, len, buf, is_pbuf);
- CYW_EXIT
-
- return ret;
-}
-
-/*******************************************************************************/
-// WiFi control
-
-STATIC int cyw43_wifi_on(cyw43_t *self, uint32_t country) {
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return ret;
- }
-
- #ifdef pyb_pin_WL_RFSW_VDD
- // Turn the RF-switch on
- mp_hal_pin_high(pyb_pin_WL_RFSW_VDD);
- #endif
-
- CYW_ENTER
- ret = cyw43_ll_wifi_on(&self->cyw43_ll, country);
- CYW_EXIT
-
- return ret;
-}
-
-int cyw43_wifi_pm(cyw43_t *self, uint32_t pm_in) {
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return ret;
- }
-
- // pm_in: 0x00adbrrm
- uint32_t pm = pm_in & 0xf;
- uint32_t pm_sleep_ret = (pm_in >> 4) & 0xff;
- uint32_t li_bcn = (pm_in >> 12) & 0xf;
- uint32_t li_dtim = (pm_in >> 16) & 0xf;
- uint32_t li_assoc = (pm_in >> 20) & 0xf;
-
- CYW_ENTER
- ret = cyw43_ll_wifi_pm(&self->cyw43_ll, pm, pm_sleep_ret, li_bcn, li_dtim, li_assoc);
- CYW_EXIT
-
- return ret;
-}
-
-int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]) {
- mp_hal_get_mac(MP_HAL_MAC_WLAN0, &mac[0]);
- return 0;
-}
-
-#define MAKE_COUNTRY(a, b, rev) ((a) | (b) << 8 | (rev) << 16)
-
-void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up) {
- if (up) {
- if (self->itf_state == 0) {
- uint32_t country;
- extern char pyb_country_code[2];
- if (pyb_country_code[0] == '\0' || pyb_country_code[1] == '\0') {
- country = MAKE_COUNTRY('X', 'X', 17); // default to world-wide (passive ch 12-14)
- } else {
- country = MAKE_COUNTRY(pyb_country_code[0], pyb_country_code[1], 0);
- }
- if (cyw43_wifi_on(self, country) != 0) {
- return;
- }
- cyw43_wifi_pm(self, 10 << 20 | 1 << 16 | 1 << 12 | 20 << 4 | 2);
- }
- if (itf == CYW43_ITF_AP) {
- cyw43_wifi_ap_init(self);
- cyw43_wifi_ap_set_up(self, true);
- }
- if ((self->itf_state & (1 << itf)) == 0) {
- CYW_ENTER
- cyw43_tcpip_deinit(self, itf);
- cyw43_tcpip_init(self, itf);
- self->itf_state |= 1 << itf;
- CYW_EXIT
- }
- } else {
- if (itf == CYW43_ITF_AP) {
- cyw43_wifi_ap_set_up(self, false);
- }
- }
-}
-
-int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)) {
- if (self->itf_state == 0) {
- return -MP_EPERM;
- }
-
- cyw43_ensure_up(self);
-
- CYW_ENTER
-
- // Set state and callback data
- self->wifi_scan_state = 1;
- self->wifi_scan_env = env;
- self->wifi_scan_cb = result_cb;
-
- // Start the scan
- int ret = cyw43_ll_wifi_scan(&self->cyw43_ll, opts);
-
- CYW_EXIT
-
- return ret;
-}
-
-int cyw43_wifi_link_status(cyw43_t *self, int itf) {
- if (itf == CYW43_ITF_STA) {
- int s = self->wifi_join_state & 0xf;
- if (s == WIFI_JOIN_STATE_ACTIVE) {
- return CYW43_LINK_JOIN;
- } else if (s == WIFI_JOIN_STATE_FAIL) {
- return CYW43_LINK_FAIL;
- } else if (s == WIFI_JOIN_STATE_NONET) {
- return CYW43_LINK_NONET;
- } else if (s == WIFI_JOIN_STATE_BADAUTH) {
- return CYW43_LINK_BADAUTH;
- } else {
- return CYW43_LINK_DOWN;
- }
- } else {
- return CYW43_LINK_DOWN;
- }
-}
-
-/*******************************************************************************/
-// WiFi STA
-
-int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel) {
- if (!CYW43_STA_IS_ACTIVE(self)) {
- return -MP_EPERM;
- }
-
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return ret;
- }
-
- CYW_ENTER
-
- ret = cyw43_ll_wifi_join(&self->cyw43_ll, ssid_len, ssid, key_len, key, auth_type, bssid, channel);
-
- if (ret == 0) {
- // Wait for responses: EV_AUTH, EV_LINK, EV_SET_SSID, EV_PSK_SUP
- // Will get EV_DEAUTH_IND if password is invalid
- self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE;
-
- if (auth_type == 0) {
- // For open security we don't need EV_PSK_SUP, so set that flag indicator now
- self->wifi_join_state |= WIFI_JOIN_STATE_KEYED;
- }
- }
-
- CYW_EXIT
-
- return ret;
-}
-
-int cyw43_wifi_leave(cyw43_t *self, int itf) {
- // Disassociate with SSID
- return cyw43_ioctl(self, CYW43_IOCTL_SET_DISASSOC, 0, NULL, itf);
-}
-
-/*******************************************************************************/
-// WiFi AP
-
-STATIC void cyw43_wifi_ap_init(cyw43_t *self) {
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return;
- }
-
- CYW_ENTER
- cyw43_ll_wifi_ap_init(&self->cyw43_ll, self->ap_ssid_len, self->ap_ssid, self->ap_auth, self->ap_key_len, self->ap_key, self->ap_channel);
- CYW_EXIT
-}
-
-STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up) {
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return;
- }
-
- CYW_ENTER
- cyw43_ll_wifi_ap_set_up(&self->cyw43_ll, up);
- CYW_EXIT
-}
-
-void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs) {
- int ret = cyw43_ensure_up(self);
- if (ret) {
- return;
- }
-
- CYW_ENTER
- cyw43_ll_wifi_ap_get_stas(&self->cyw43_ll, num_stas, macs);
- CYW_EXIT
-}
diff --git a/drivers/cyw43/cyw43_ll.h b/drivers/cyw43/cyw43_ll.h
deleted file mode 100644
index 879367a2edd9e..0000000000000
--- a/drivers/cyw43/cyw43_ll.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018-2019 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef MICROPY_INCLUDED_STM32_CYW43_LL_H
-#define MICROPY_INCLUDED_STM32_CYW43_LL_H
-
-// IOCTL commands
-#define CYW43_IOCTL_GET_SSID (0x32)
-#define CYW43_IOCTL_GET_CHANNEL (0x3a)
-#define CYW43_IOCTL_SET_DISASSOC (0x69)
-#define CYW43_IOCTL_GET_ANTDIV (0x7e)
-#define CYW43_IOCTL_SET_ANTDIV (0x81)
-#define CYW43_IOCTL_SET_MONITOR (0xd9)
-#define CYW43_IOCTL_GET_VAR (0x20c)
-#define CYW43_IOCTL_SET_VAR (0x20f)
-
-// Async events, event_type field
-#define CYW43_EV_SET_SSID (0)
-#define CYW43_EV_JOIN (1)
-#define CYW43_EV_AUTH (3)
-#define CYW43_EV_DEAUTH_IND (6)
-#define CYW43_EV_ASSOC (7)
-#define CYW43_EV_DISASSOC (11)
-#define CYW43_EV_DISASSOC_IND (12)
-#define CYW43_EV_LINK (16)
-#define CYW43_EV_PRUNE (23)
-#define CYW43_EV_PSK_SUP (46)
-#define CYW43_EV_ESCAN_RESULT (69)
-#define CYW43_EV_CSA_COMPLETE_IND (80)
-#define CYW43_EV_ASSOC_REQ_IE (87)
-#define CYW43_EV_ASSOC_RESP_IE (88)
-
-enum {
- CYW43_ITF_STA,
- CYW43_ITF_AP,
-};
-
-typedef struct _cyw43_ev_scan_result_t {
- uint32_t _0[5];
- uint8_t bssid[6];
- uint16_t _1[2];
- uint8_t ssid_len;
- uint8_t ssid[32];
- uint32_t _2[5];
- uint16_t channel;
- uint16_t _3;
- uint8_t auth_mode;
- int16_t rssi;
-} cyw43_ev_scan_result_t;
-
-typedef struct _cyw43_async_event_t {
- uint16_t _0;
- uint16_t flags;
- uint32_t event_type;
- uint32_t status;
- uint32_t reason;
- uint8_t _1[30];
- uint8_t interface;
- uint8_t _2;
- union {
- cyw43_ev_scan_result_t scan_result;
- } u;
-} cyw43_async_event_t;
-
-typedef struct _cyw43_wifi_scan_options_t {
- uint32_t version;
- uint16_t action;
- uint16_t _;
- uint32_t ssid_len; // 0 to select all
- uint8_t ssid[32];
- uint8_t bssid[6];
- int8_t bss_type; // fill with 0xff to select all
- int8_t scan_type; // 0=active, 1=passive
- int32_t nprobes;
- int32_t active_time;
- int32_t passive_time;
- int32_t home_time;
- int32_t channel_num;
- uint16_t channel_list[1];
-} cyw43_wifi_scan_options_t;
-
-typedef struct _cyw43_ll_t {
- uint32_t opaque[528];
-} cyw43_ll_t;
-
-void cyw43_ll_init(cyw43_ll_t *self, void *cb_data);
-void cyw43_ll_deinit(cyw43_ll_t *self);
-
-int cyw43_ll_bus_init(cyw43_ll_t *self, const uint8_t *mac);
-void cyw43_ll_bus_sleep(cyw43_ll_t *self, bool can_sleep);
-void cyw43_ll_process_packets(cyw43_ll_t *self);
-int cyw43_ll_ioctl(cyw43_ll_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface);
-int cyw43_ll_send_ethernet(cyw43_ll_t *self, int itf, size_t len, const void *buf, bool is_pbuf);
-
-int cyw43_ll_wifi_on(cyw43_ll_t *self, uint32_t country);
-int cyw43_ll_wifi_pm(cyw43_ll_t *self, uint32_t pm, uint32_t pm_sleep_ret, uint32_t li_bcn, uint32_t li_dtim, uint32_t li_assoc);
-int cyw43_ll_wifi_scan(cyw43_ll_t *self, cyw43_wifi_scan_options_t *opts);
-
-int cyw43_ll_wifi_join(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel);
-void cyw43_ll_wifi_set_wpa_auth(cyw43_ll_t *self);
-void cyw43_ll_wifi_rejoin(cyw43_ll_t *self);
-
-int cyw43_ll_wifi_ap_init(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, uint32_t auth, size_t key_len, const uint8_t *key, uint32_t channel);
-int cyw43_ll_wifi_ap_set_up(cyw43_ll_t *self, bool up);
-int cyw43_ll_wifi_ap_get_stas(cyw43_ll_t *self, int *num_stas, uint8_t *macs);
-
-// Callbacks to be provided by mid-level interface
-int cyw43_cb_read_host_interrupt_pin(void *cb_data);
-void cyw43_cb_ensure_awake(void *cb_data);
-void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev);
-void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf);
-
-#endif // MICROPY_INCLUDED_STM32_CYW43_LL_H
diff --git a/drivers/cyw43/cyw43_lwip.c b/drivers/cyw43/cyw43_lwip.c
deleted file mode 100644
index 16ae6023755a1..0000000000000
--- a/drivers/cyw43/cyw43_lwip.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018-2019 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-#include "py/mphal.h"
-#include "shared/netutils/netutils.h"
-#include "lwip/etharp.h"
-#include "lwip/dns.h"
-#include "lwip/apps/mdns.h"
-#include "drivers/cyw43/cyw43.h"
-
-STATIC void cyw43_ethernet_trace(cyw43_t *self, struct netif *netif, size_t len, const void *data, unsigned int flags) {
- bool is_tx = flags & NETUTILS_TRACE_IS_TX;
- if ((is_tx && (self->trace_flags & CYW43_TRACE_ETH_TX))
- || (!is_tx && (self->trace_flags & CYW43_TRACE_ETH_RX))) {
- const uint8_t *buf;
- if (len == (size_t)-1) {
- // data is a pbuf
- const struct pbuf *pbuf = data;
- buf = pbuf->payload;
- len = pbuf->len; // restricted to print only the first chunk of the pbuf
- } else {
- // data is actual data buffer
- buf = data;
- }
-
- if (self->trace_flags & CYW43_TRACE_MAC) {
- printf("[% 8d] ETH%cX itf=%c%c len=%u", (int)mp_hal_ticks_ms(), is_tx ? 'T' : 'R', netif->name[0], netif->name[1], len);
- printf(" MAC type=%d subtype=%d data=", buf[0] >> 2 & 3, buf[0] >> 4);
- for (size_t i = 0; i < len; ++i) {
- printf(" %02x", buf[i]);
- }
- printf("\n");
- return;
- }
-
- if (self->trace_flags & CYW43_TRACE_ETH_FULL) {
- flags |= NETUTILS_TRACE_PAYLOAD;
- }
- netutils_ethernet_trace(MP_PYTHON_PRINTER, len, buf, flags);
- }
-}
-
-STATIC err_t cyw43_netif_output(struct netif *netif, struct pbuf *p) {
- cyw43_t *self = netif->state;
- if (self->trace_flags != 0) {
- cyw43_ethernet_trace(self, netif, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE);
- }
- int itf = netif->name[1] - '0';
- int ret = cyw43_send_ethernet(self, itf, p->tot_len, (void*)p, true);
- if (ret) {
- printf("[CYW43] send_ethernet failed: %d\n", ret);
- return ERR_IF;
- }
- return ERR_OK;
-}
-
-STATIC err_t cyw43_netif_init(struct netif *netif) {
- netif->linkoutput = cyw43_netif_output;
- netif->output = etharp_output;
- netif->mtu = 1500;
- netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
- cyw43_wifi_get_mac(netif->state, netif->name[1] - '0', netif->hwaddr);
- netif->hwaddr_len = sizeof(netif->hwaddr);
- return ERR_OK;
-}
-
-void cyw43_tcpip_init(cyw43_t *self, int itf) {
- ip_addr_t ipconfig[4];
- #if LWIP_IPV6
- #define IP(x) ((x).u_addr.ip4)
- #else
- #define IP(x) (x)
- #endif
- if (itf == 0) {
- // need to zero out to get isconnected() working
- IP4_ADDR(&IP(ipconfig[0]), 0, 0, 0, 0);
- IP4_ADDR(&IP(ipconfig[2]), 192, 168, 0, 1);
- } else {
- IP4_ADDR(&IP(ipconfig[0]), 192, 168, 4, 1);
- IP4_ADDR(&IP(ipconfig[2]), 192, 168, 4, 1);
- }
- IP4_ADDR(&IP(ipconfig[1]), 255, 255, 255, 0);
- IP4_ADDR(&IP(ipconfig[3]), 8, 8, 8, 8);
- #undef IP
-
- struct netif *n = &self->netif[itf];
- n->name[0] = 'w';
- n->name[1] = '0' + itf;
- #if LWIP_IPV6
- netif_add(n, &ipconfig[0].u_addr.ip4, &ipconfig[1].u_addr.ip4, &ipconfig[2].u_addr.ip4, self, cyw43_netif_init, ethernet_input);
- #else
- netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, cyw43_netif_init, netif_input);
- #endif
- netif_set_hostname(n, "PYBD");
- netif_set_default(n);
- netif_set_up(n);
-
- if (itf == CYW43_ITF_STA) {
- dns_setserver(0, &ipconfig[3]);
- dhcp_set_struct(n, &self->dhcp_client);
- dhcp_start(n);
- } else {
- dhcp_server_init(&self->dhcp_server, &ipconfig[0], &ipconfig[1]);
- }
-
- #if LWIP_MDNS_RESPONDER
- // TODO better to call after IP address is set
- char mdns_hostname[9];
- memcpy(&mdns_hostname[0], "PYBD", 4);
- mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, &mdns_hostname[4]);
- mdns_hostname[8] = '\0';
- mdns_resp_add_netif(n, mdns_hostname, 60);
- #endif
-}
-
-void cyw43_tcpip_deinit(cyw43_t *self, int itf) {
- struct netif *n = &self->netif[itf];
- if (itf == CYW43_ITF_STA) {
- dhcp_stop(n);
- } else {
- dhcp_server_deinit(&self->dhcp_server);
- }
- #if LWIP_MDNS_RESPONDER
- mdns_resp_remove_netif(n);
- #endif
- for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
- if (netif == n) {
- netif_remove(netif);
- netif->ip_addr.addr = 0;
- netif->flags = 0;
- }
- }
-}
-
-void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
- cyw43_t *self = cb_data;
- struct netif *netif = &self->netif[itf];
- if (self->trace_flags) {
- cyw43_ethernet_trace(self, netif, len, buf, NETUTILS_TRACE_NEWLINE);
- }
- if (netif->flags & NETIF_FLAG_LINK_UP) {
- struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- if (p != NULL) {
- pbuf_take(p, buf, len);
- if (netif->input(p, netif) != ERR_OK) {
- pbuf_free(p);
- }
- }
- }
-}
-
-void cyw43_tcpip_set_link_up(cyw43_t *self, int itf) {
- netif_set_link_up(&self->netif[itf]);
-}
-
-void cyw43_tcpip_set_link_down(cyw43_t *self, int itf) {
- netif_set_link_down(&self->netif[itf]);
-}
-
-int cyw43_tcpip_link_status(cyw43_t *self, int itf) {
- struct netif *netif = &self->netif[itf];
- if ((netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP))
- == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) {
- if (netif->ip_addr.addr != 0) {
- return CYW43_LINK_UP;
- } else {
- return CYW43_LINK_NOIP;
- }
- } else {
- return cyw43_wifi_link_status(self, itf);
- }
-}
diff --git a/drivers/cyw43/cywbt.c b/drivers/cyw43/cywbt.c
index 64aeb871c38bb..006fd28e901d7 100644
--- a/drivers/cyw43/cywbt.c
+++ b/drivers/cyw43/cywbt.c
@@ -35,8 +35,8 @@
#if MICROPY_PY_NETWORK_CYW43
-extern const char fw_4343WA1_7_45_98_50_start;
-#define CYWBT_FW_ADDR (&fw_4343WA1_7_45_98_50_start + 749 * 512 + 29 * 256)
+#include "lib/cyw43-driver/src/cyw43_config.h"
+#include "lib/cyw43-driver/firmware/cyw43_btfw_4343A1.h"
// Provided by the port.
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
@@ -67,7 +67,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj);
}
- // expect a comand complete event (event 0x0e)
+ // expect a command complete event (event 0x0e)
if (buf[0] != 0x04 || buf[1] != 0x0e) {
printf("unknown response: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
return -1;
@@ -159,8 +159,8 @@ STATIC int cywbt_download_firmware(const uint8_t *firmware) {
#endif
mp_bluetooth_hci_uart_set_baudrate(115200);
- cywbt_set_baudrate(3000000);
- mp_bluetooth_hci_uart_set_baudrate(3000000);
+ cywbt_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY);
+ mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY);
return 0;
}
@@ -191,11 +191,13 @@ int mp_bluetooth_hci_controller_init(void) {
// Reset
cywbt_hci_cmd(0x03, 0x0003, 0, NULL);
+ #ifdef MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE
// Change baudrate
- cywbt_set_baudrate(3000000);
- mp_bluetooth_hci_uart_set_baudrate(3000000);
+ cywbt_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE);
+ mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE);
+ #endif
- cywbt_download_firmware((const uint8_t*)CYWBT_FW_ADDR);
+ cywbt_download_firmware((const uint8_t*)&cyw43_btfw_4343A1[0]);
// Reset
cywbt_hci_cmd(0x03, 0x0003, 0, NULL);
diff --git a/drivers/cyw43/libcyw43.a b/drivers/cyw43/libcyw43.a
deleted file mode 100644
index 7d0ff93dcbe68..0000000000000
Binary files a/drivers/cyw43/libcyw43.a and /dev/null differ
diff --git a/drivers/dht/dht.py b/drivers/dht/dht.py
deleted file mode 100644
index 411e9a8d28a6b..0000000000000
--- a/drivers/dht/dht.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# DHT11/DHT22 driver for MicroPython on ESP8266
-# MIT license; Copyright (c) 2016 Damien P. George
-
-import sys
-
-if sys.platform.startswith("esp"):
- from esp import dht_readinto
-elif sys.platform == "mimxrt":
- from mimxrt import dht_readinto
-elif sys.platform == "rp2":
- from rp2 import dht_readinto
-elif sys.platform == "pyboard":
- from pyb import dht_readinto
-else:
- from machine import dht_readinto
-
-
-class DHTBase:
- def __init__(self, pin):
- self.pin = pin
- self.buf = bytearray(5)
-
- def measure(self):
- buf = self.buf
- dht_readinto(self.pin, buf)
- if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]:
- raise Exception("checksum error")
-
-
-class DHT11(DHTBase):
- def humidity(self):
- return self.buf[0]
-
- def temperature(self):
- return self.buf[2]
-
-
-class DHT22(DHTBase):
- def humidity(self):
- return (self.buf[0] << 8 | self.buf[1]) * 0.1
-
- def temperature(self):
- t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1
- if self.buf[2] & 0x80:
- t = -t
- return t
diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py
deleted file mode 100644
index f792418aa2b55..0000000000000
--- a/drivers/display/lcd160cr.py
+++ /dev/null
@@ -1,482 +0,0 @@
-# Driver for official MicroPython LCD160CR display
-# MIT license; Copyright (c) 2017 Damien P. George
-
-from micropython import const
-from utime import sleep_ms
-from ustruct import calcsize, pack_into
-import uerrno, machine
-
-# for set_orient
-PORTRAIT = const(0)
-LANDSCAPE = const(1)
-PORTRAIT_UPSIDEDOWN = const(2)
-LANDSCAPE_UPSIDEDOWN = const(3)
-
-# for set_startup_deco; can be or'd
-STARTUP_DECO_NONE = const(0)
-STARTUP_DECO_MLOGO = const(1)
-STARTUP_DECO_INFO = const(2)
-
-_uart_baud_table = {
- 2400: 0,
- 4800: 1,
- 9600: 2,
- 19200: 3,
- 38400: 4,
- 57600: 5,
- 115200: 6,
- 230400: 7,
- 460800: 8,
-}
-
-
-class LCD160CR:
- def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98):
- if connect in ("X", "Y", "XY", "YX"):
- i = connect[-1]
- j = connect[0]
- y = j + "4"
- elif connect == "C":
- i = 2
- j = 2
- y = "A7"
- else:
- if pwr is None or i2c is None or spi is None:
- raise ValueError('must specify valid "connect" or all of "pwr", "i2c" and "spi"')
-
- if pwr is None:
- pwr = machine.Pin(y, machine.Pin.OUT)
- if i2c is None:
- i2c = machine.I2C(i, freq=1000000)
- if spi is None:
- spi = machine.SPI(j, baudrate=13500000, polarity=0, phase=0)
-
- if not pwr.value():
- pwr(1)
- sleep_ms(10)
- # else:
- # alread have power
- # lets be optimistic...
-
- # set connections
- self.pwr = pwr
- self.i2c = i2c
- self.spi = spi
- self.i2c_addr = i2c_addr
-
- # create temp buffers and memoryviews
- self.buf16 = bytearray(16)
- self.buf19 = bytearray(19)
- self.buf = [None] * 10
- for i in range(1, 10):
- self.buf[i] = memoryview(self.buf16)[0:i]
- self.buf1 = self.buf[1]
- self.array4 = [0, 0, 0, 0]
-
- # set default orientation and window
- self.set_orient(PORTRAIT)
- self._fcmd2b("= n:
- self.i2c.readfrom_into(self.i2c_addr, buf)
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def oflush(self, n=255):
- t = 5000
- while t:
- self.i2c.readfrom_into(self.i2c_addr + 1, self.buf1)
- r = self.buf1[0]
- if r >= n:
- return
- t -= 1
- machine.idle()
- raise OSError(uerrno.ETIMEDOUT)
-
- def iflush(self):
- t = 5000
- while t:
- self.i2c.readfrom_into(self.i2c_addr, self.buf16)
- if self.buf16[0] == 0:
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- #### MISC METHODS ####
-
- @staticmethod
- def rgb(r, g, b):
- return ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3)
-
- @staticmethod
- def clip_line(c, w, h):
- while True:
- ca = ce = 0
- if c[1] < 0:
- ca |= 8
- elif c[1] > h:
- ca |= 4
- if c[0] < 0:
- ca |= 1
- elif c[0] > w:
- ca |= 2
- if c[3] < 0:
- ce |= 8
- elif c[3] > h:
- ce |= 4
- if c[2] < 0:
- ce |= 1
- elif c[2] > w:
- ce |= 2
- if ca & ce:
- return False
- elif ca | ce:
- ca |= ce
- if ca & 1:
- if c[2] < c[0]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[1] += ((-c[0]) * (c[3] - c[1])) // (c[2] - c[0])
- c[0] = 0
- elif ca & 2:
- if c[2] < c[0]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[3] += ((w - 1 - c[2]) * (c[3] - c[1])) // (c[2] - c[0])
- c[2] = w - 1
- elif ca & 4:
- if c[0] == c[2]:
- if c[1] >= h:
- c[1] = h - 1
- if c[3] >= h:
- c[3] = h - 1
- else:
- if c[3] < c[1]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[2] += ((h - 1 - c[3]) * (c[2] - c[0])) // (c[3] - c[1])
- c[3] = h - 1
- else:
- if c[0] == c[2]:
- if c[1] < 0:
- c[1] = 0
- if c[3] < 0:
- c[3] = 0
- else:
- if c[3] < c[1]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[0] += ((-c[1]) * (c[2] - c[0])) // (c[3] - c[1])
- c[1] = 0
- else:
- return True
-
- #### SETUP COMMANDS ####
-
- def set_power(self, on):
- self.pwr(on)
- sleep_ms(15)
-
- def set_orient(self, orient):
- self._fcmd2("= 2:
- self.i2c.readfrom_into(self.i2c_addr, self.buf[3])
- return self.buf[3][1] | self.buf[3][2] << 8
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def get_line(self, x, y, buf):
- l = len(buf) // 2
- self._fcmd2b("= l:
- self.i2c.readfrom_into(self.i2c_addr, buf)
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def screen_dump(self, buf, x=0, y=0, w=None, h=None):
- if w is None:
- w = self.w - x
- if h is None:
- h = self.h - y
- if w <= 127:
- line = bytearray(2 * w + 1)
- line2 = None
- else:
- # split line if more than 254 bytes needed
- buflen = (w + 1) // 2
- line = bytearray(2 * buflen + 1)
- line2 = memoryview(line)[: 2 * (w - buflen) + 1]
- for i in range(min(len(buf) // (2 * w), h)):
- ix = i * w * 2
- self.get_line(x, y + i, line)
- buf[ix : ix + len(line) - 1] = memoryview(line)[1:]
- ix += len(line) - 1
- if line2:
- self.get_line(x + buflen, y + i, line2)
- buf[ix : ix + len(line2) - 1] = memoryview(line2)[1:]
- ix += len(line2) - 1
-
- def screen_load(self, buf):
- l = self.w * self.h * 2 + 2
- self._fcmd2b("= 0x200:
- self._send(ar[n : n + 0x200])
- n += 0x200
- else:
- self._send(ar[n:])
- while n < self.w * self.h * 2:
- self._send(b"\x00")
- n += 1
-
- #### TEXT COMMANDS ####
-
- def set_pos(self, x, y):
- self._fcmd2("= self.w or y >= self.h:
- return
- elif x < 0 or y < 0:
- left = top = True
- if x < 0:
- left = False
- w += x
- x = 0
- if y < 0:
- top = False
- h += y
- y = 0
- if cmd == 0x51 or cmd == 0x72:
- # draw interior
- self._fcmd2b("> 7 != 0
-
- def get_touch(self):
- self._send(b"\x02T") # implicit LCD output flush
- b = self.buf[4]
- self._waitfor(3, b)
- return b[1] >> 7, b[2], b[3]
-
- #### ADVANCED COMMANDS ####
-
- def set_spi_win(self, x, y, w, h):
- pack_into(
- " 32:
- raise ValueError("length must be 32 or less")
- self._fcmd2(" 0xFFFF:
- raise ValueError("length must be 65535 or less")
- self.oflush()
- self._fcmd2(" 0:
- s = "%6.3fV" % data[i]
- else:
- s = "%5.1f°C" % data[i]
- if lcd.h == 160:
- lcd.set_font(1, bold=0, scale=1)
- else:
- lcd.set_font(1, bold=0, scale=1, trans=1)
- lcd.set_pos(45, lcd.h - 60 + i * 16)
- lcd.write(s)
-
-
-def test_features(lcd, orient=lcd160cr.PORTRAIT):
- # if we run on pyboard then use ADC and RTC features
- try:
- import pyb
-
- adc = pyb.ADCAll(12, 0xF0000)
- rtc = pyb.RTC()
- except:
- adc = None
- rtc = None
-
- # set orientation and clear screen
- lcd = get_lcd(lcd)
- lcd.set_orient(orient)
- lcd.set_pen(0, 0)
- lcd.erase()
-
- # create M-logo
- mlogo = framebuf.FrameBuffer(bytearray(17 * 17 * 2), 17, 17, framebuf.RGB565)
- mlogo.fill(0)
- mlogo.fill_rect(1, 1, 15, 15, 0xFFFFFF)
- mlogo.vline(4, 4, 12, 0)
- mlogo.vline(8, 1, 12, 0)
- mlogo.vline(12, 4, 12, 0)
- mlogo.vline(14, 13, 2, 0)
-
- # create inline framebuf
- offx = 14
- offy = 19
- w = 100
- h = 75
- fbuf = framebuf.FrameBuffer(bytearray(w * h * 2), w, h, framebuf.RGB565)
- lcd.set_spi_win(offx, offy, w, h)
-
- # initialise loop parameters
- tx = ty = 0
- t0 = time.ticks_us()
-
- for i in range(300):
- # update position of cross-hair
- t, tx2, ty2 = lcd.get_touch()
- if t:
- tx2 -= offx
- ty2 -= offy
- if tx2 >= 0 and ty2 >= 0 and tx2 < w and ty2 < h:
- tx, ty = tx2, ty2
- else:
- tx = (tx + 1) % w
- ty = (ty + 1) % h
-
- # create and show the inline framebuf
- fbuf.fill(lcd.rgb(128 + int(64 * math.cos(0.1 * i)), 128, 192))
- fbuf.line(
- w // 2,
- h // 2,
- w // 2 + int(40 * math.cos(0.2 * i)),
- h // 2 + int(40 * math.sin(0.2 * i)),
- lcd.rgb(128, 255, 64),
- )
- fbuf.hline(0, ty, w, lcd.rgb(64, 64, 64))
- fbuf.vline(tx, 0, h, lcd.rgb(64, 64, 64))
- fbuf.rect(tx - 3, ty - 3, 7, 7, lcd.rgb(64, 64, 64))
- for phase in (-0.2, 0, 0.2):
- x = w // 2 - 8 + int(50 * math.cos(0.05 * i + phase))
- y = h // 2 - 8 + int(32 * math.sin(0.05 * i + phase))
- fbuf.blit(mlogo, x, y)
- for j in range(-3, 3):
- fbuf.text(
- "MicroPython",
- 5,
- h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))),
- lcd.rgb(128 + 10 * j, 0, 128 - 10 * j),
- )
- lcd.show_framebuf(fbuf)
-
- # show results from the ADC
- if adc:
- show_adc(lcd, adc)
-
- # show the time
- if rtc:
- lcd.set_pos(2, 0)
- lcd.set_font(1)
- t = rtc.datetime()
- lcd.write(
- "%4d-%02d-%02d %2d:%02d:%02d.%01d"
- % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000)
- )
-
- # compute the frame rate
- t1 = time.ticks_us()
- dt = time.ticks_diff(t1, t0)
- t0 = t1
-
- # show the frame rate
- lcd.set_pos(2, 9)
- lcd.write("%.2f fps" % (1000000 / dt))
-
-
-def test_mandel(lcd, orient=lcd160cr.PORTRAIT):
- # set orientation and clear screen
- lcd = get_lcd(lcd)
- lcd.set_orient(orient)
- lcd.set_pen(0, 0xFFFF)
- lcd.erase()
-
- # function to compute Mandelbrot pixels
- def in_set(c):
- z = 0
- for i in range(32):
- z = z * z + c
- if abs(z) > 100:
- return i
- return 0
-
- # cache width and height of LCD
- w = lcd.w
- h = lcd.h
-
- # create the buffer for each line and set SPI parameters
- line = bytearray(w * 2)
- lcd.set_spi_win(0, 0, w, h)
- spi = lcd.fast_spi()
-
- # draw the Mandelbrot set line-by-line
- hh = (h - 1) / 3.2
- ww = (w - 1) / 2.4
- for v in range(h):
- for u in range(w):
- c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j)
- if c < 16:
- rgb = c << 12 | c << 6
- else:
- rgb = 0xF800 | c << 6
- line[2 * u] = rgb
- line[2 * u + 1] = rgb >> 8
- spi.write(line)
-
-
-def test_all(lcd, orient=lcd160cr.PORTRAIT):
- lcd = get_lcd(lcd)
- test_features(lcd, orient)
- test_mandel(lcd, orient)
-
-
-print("To run all tests: test_all()")
-print("Individual tests are: test_features, test_mandel")
-print(' argument should be a connection, eg "X", or an LCD160CR object')
diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py
deleted file mode 100644
index a504cdadcc94e..0000000000000
--- a/drivers/display/ssd1306.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
-
-from micropython import const
-import framebuf
-
-
-# register definitions
-SET_CONTRAST = const(0x81)
-SET_ENTIRE_ON = const(0xA4)
-SET_NORM_INV = const(0xA6)
-SET_DISP = const(0xAE)
-SET_MEM_ADDR = const(0x20)
-SET_COL_ADDR = const(0x21)
-SET_PAGE_ADDR = const(0x22)
-SET_DISP_START_LINE = const(0x40)
-SET_SEG_REMAP = const(0xA0)
-SET_MUX_RATIO = const(0xA8)
-SET_IREF_SELECT = const(0xAD)
-SET_COM_OUT_DIR = const(0xC0)
-SET_DISP_OFFSET = const(0xD3)
-SET_COM_PIN_CFG = const(0xDA)
-SET_DISP_CLK_DIV = const(0xD5)
-SET_PRECHARGE = const(0xD9)
-SET_VCOM_DESEL = const(0xDB)
-SET_CHARGE_PUMP = const(0x8D)
-
-# Subclassing FrameBuffer provides support for graphics primitives
-# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
-class SSD1306(framebuf.FrameBuffer):
- def __init__(self, width, height, external_vcc):
- self.width = width
- self.height = height
- self.external_vcc = external_vcc
- self.pages = self.height // 8
- self.buffer = bytearray(self.pages * self.width)
- super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
- self.init_display()
-
- def init_display(self):
- for cmd in (
- SET_DISP, # display off
- # address setting
- SET_MEM_ADDR,
- 0x00, # horizontal
- # resolution and layout
- SET_DISP_START_LINE, # start at line 0
- SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
- SET_MUX_RATIO,
- self.height - 1,
- SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
- SET_DISP_OFFSET,
- 0x00,
- SET_COM_PIN_CFG,
- 0x02 if self.width > 2 * self.height else 0x12,
- # timing and driving scheme
- SET_DISP_CLK_DIV,
- 0x80,
- SET_PRECHARGE,
- 0x22 if self.external_vcc else 0xF1,
- SET_VCOM_DESEL,
- 0x30, # 0.83*Vcc
- # display
- SET_CONTRAST,
- 0xFF, # maximum
- SET_ENTIRE_ON, # output follows RAM contents
- SET_NORM_INV, # not inverted
- SET_IREF_SELECT,
- 0x30, # enable internal IREF during display on
- # charge pump
- SET_CHARGE_PUMP,
- 0x10 if self.external_vcc else 0x14,
- SET_DISP | 0x01, # display on
- ): # on
- self.write_cmd(cmd)
- self.fill(0)
- self.show()
-
- def poweroff(self):
- self.write_cmd(SET_DISP)
-
- def poweron(self):
- self.write_cmd(SET_DISP | 0x01)
-
- def contrast(self, contrast):
- self.write_cmd(SET_CONTRAST)
- self.write_cmd(contrast)
-
- def invert(self, invert):
- self.write_cmd(SET_NORM_INV | (invert & 1))
-
- def rotate(self, rotate):
- self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3))
- self.write_cmd(SET_SEG_REMAP | (rotate & 1))
-
- def show(self):
- x0 = 0
- x1 = self.width - 1
- if self.width != 128:
- # narrow displays use centred columns
- col_offset = (128 - self.width) // 2
- x0 += col_offset
- x1 += col_offset
- self.write_cmd(SET_COL_ADDR)
- self.write_cmd(x0)
- self.write_cmd(x1)
- self.write_cmd(SET_PAGE_ADDR)
- self.write_cmd(0)
- self.write_cmd(self.pages - 1)
- self.write_data(self.buffer)
-
-
-class SSD1306_I2C(SSD1306):
- def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
- self.i2c = i2c
- self.addr = addr
- self.temp = bytearray(2)
- self.write_list = [b"\x40", None] # Co=0, D/C#=1
- super().__init__(width, height, external_vcc)
-
- def write_cmd(self, cmd):
- self.temp[0] = 0x80 # Co=1, D/C#=0
- self.temp[1] = cmd
- self.i2c.writeto(self.addr, self.temp)
-
- def write_data(self, buf):
- self.write_list[1] = buf
- self.i2c.writevto(self.addr, self.write_list)
-
-
-class SSD1306_SPI(SSD1306):
- def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
- self.rate = 10 * 1024 * 1024
- dc.init(dc.OUT, value=0)
- res.init(res.OUT, value=0)
- cs.init(cs.OUT, value=1)
- self.spi = spi
- self.dc = dc
- self.res = res
- self.cs = cs
- import time
-
- self.res(1)
- time.sleep_ms(1)
- self.res(0)
- time.sleep_ms(10)
- self.res(1)
- super().__init__(width, height, external_vcc)
-
- def write_cmd(self, cmd):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(0)
- self.cs(0)
- self.spi.write(bytearray([cmd]))
- self.cs(1)
-
- def write_data(self, buf):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(1)
- self.cs(0)
- self.spi.write(buf)
- self.cs(1)
diff --git a/drivers/lsm6dsox/lsm6dsox.py b/drivers/lsm6dsox/lsm6dsox.py
deleted file mode 100644
index 98e19fa4ca7b3..0000000000000
--- a/drivers/lsm6dsox/lsm6dsox.py
+++ /dev/null
@@ -1,271 +0,0 @@
-"""
-LSM6DSOX STMicro driver for MicroPython based on LSM9DS1:
-Source repo: https://github.com/hoihu/projects/tree/master/raspi-hat
-
-The MIT License (MIT)
-
-Copyright (c) 2021 Damien P. George
-Copyright (c) 2021-2022 Ibrahim Abdelkader
-
-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.
-
-Basic example usage:
-
-import time
-from lsm6dsox import LSM6DSOX
-
-from machine import Pin, SPI, I2C
-# Init in I2C mode.
-lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
-
-# Or init in SPI mode.
-#lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10))
-
-while (True):
- print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_accel()))
- print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_gyro()))
- print("")
- time.sleep_ms(100)
-"""
-
-import array
-from micropython import const
-
-
-class LSM6DSOX:
- _CTRL3_C = const(0x12)
- _CTRL1_XL = const(0x10)
- _CTRL8_XL = const(0x17)
- _CTRL9_XL = const(0x18)
-
- _CTRL2_G = const(0x11)
- _CTRL7_G = const(0x16)
-
- _OUTX_L_G = const(0x22)
- _OUTX_L_XL = const(0x28)
- _MLC_STATUS = const(0x38)
-
- _DEFAULT_ADDR = const(0x6A)
- _WHO_AM_I_REG = const(0x0F)
-
- _FUNC_CFG_ACCESS = const(0x01)
- _FUNC_CFG_BANK_USER = const(0)
- _FUNC_CFG_BANK_HUB = const(1)
- _FUNC_CFG_BANK_EMBED = const(2)
-
- _MLC0_SRC = const(0x70)
- _MLC_INT1 = const(0x0D)
- _TAP_CFG0 = const(0x56)
-
- _EMB_FUNC_EN_A = const(0x04)
- _EMB_FUNC_EN_B = const(0x05)
-
- def __init__(
- self,
- bus,
- cs_pin=None,
- address=_DEFAULT_ADDR,
- gyro_odr=104,
- accel_odr=104,
- gyro_scale=2000,
- accel_scale=4,
- ucf=None,
- ):
- """Initalizes Gyro and Accelerator.
- accel_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz)
- gyro_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz)
- gyro_scale: (245dps, 500dps, 1000dps, 2000dps)
- accel_scale: (+/-2g, +/-4g, +/-8g, +-16g)
- ucf: MLC program to load.
- """
- self.bus = bus
- self.cs_pin = cs_pin
- self.address = address
- self._use_i2c = hasattr(self.bus, "readfrom_mem")
-
- if not self._use_i2c and cs_pin is None:
- raise ValueError("A CS pin must be provided in SPI mode")
-
- # check the id of the Accelerometer/Gyro
- if self.__read_reg(_WHO_AM_I_REG) != 108:
- raise OSError("No LSM6DS device was found at address 0x%x" % (self.address))
-
- # allocate scratch buffer for efficient conversions and memread op's
- self.scratch_int = array.array("h", [0, 0, 0])
-
- SCALE_GYRO = {250: 0, 500: 1, 1000: 2, 2000: 3}
- SCALE_ACCEL = {2: 0, 4: 2, 8: 3, 16: 1}
- # XL_HM_MODE = 0 by default. G_HM_MODE = 0 by default.
- ODR = {
- 0: 0x00,
- 1.6: 0x08,
- 3.33: 0x09,
- 6.66: 0x0A,
- 12.5: 0x01,
- 26: 0x02,
- 52: 0x03,
- 104: 0x04,
- 208: 0x05,
- 416: 0x06,
- 888: 0x07,
- }
-
- gyro_odr = round(gyro_odr, 2)
- accel_odr = round(accel_odr, 2)
-
- # Sanity checks
- if not gyro_odr in ODR:
- raise ValueError("Invalid sampling rate: %d" % accel_odr)
- if not gyro_scale in SCALE_GYRO:
- raise ValueError("invalid gyro scaling: %d" % gyro_scale)
- if not accel_odr in ODR:
- raise ValueError("Invalid sampling rate: %d" % accel_odr)
- if not accel_scale in SCALE_ACCEL:
- raise ValueError("invalid accelerometer scaling: %d" % accel_scale)
-
- # Soft-reset the device.
- self.reset()
-
- # Load and configure MLC if UCF file is provided
- if ucf != None:
- self.load_mlc(ucf)
-
- # Set Gyroscope datarate and scale.
- # Note output from LPF2 second filtering stage is selected. See Figure 18.
- self.__write_reg(_CTRL1_XL, (ODR[accel_odr] << 4) | (SCALE_ACCEL[accel_scale] << 2) | 2)
-
- # Enable LPF2 and HPF fast-settling mode, ODR/4
- self.__write_reg(_CTRL8_XL, 0x09)
-
- # Set Gyroscope datarate and scale.
- self.__write_reg(_CTRL2_G, (ODR[gyro_odr] << 4) | (SCALE_GYRO[gyro_scale] << 2) | 0)
-
- self.gyro_scale = 32768 / gyro_scale
- self.accel_scale = 32768 / accel_scale
-
- def __read_reg(self, reg, size=1):
- if self._use_i2c:
- buf = self.bus.readfrom_mem(self.address, reg, size)
- else:
- try:
- self.cs_pin(0)
- self.bus.write(bytes([reg | 0x80]))
- buf = self.bus.read(size)
- finally:
- self.cs_pin(1)
- if size == 1:
- return int(buf[0])
- return [int(x) for x in buf]
-
- def __write_reg(self, reg, val):
- if self._use_i2c:
- self.bus.writeto_mem(self.address, reg, bytes([val]))
- else:
- try:
- self.cs_pin(0)
- self.bus.write(bytes([reg, val]))
- finally:
- self.cs_pin(1)
-
- def __read_reg_into(self, reg, buf):
- if self._use_i2c:
- self.bus.readfrom_mem_into(self.address, reg, buf)
- else:
- try:
- self.cs_pin(0)
- self.bus.write(bytes([reg | 0x80]))
- self.bus.readinto(buf)
- finally:
- self.cs_pin(1)
-
- def reset(self):
- self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x1)
- for i in range(0, 10):
- if (self.__read_reg(_CTRL3_C) & 0x01) == 0:
- return
- time.sleep_ms(10)
- raise OSError("Failed to reset LSM6DS device.")
-
- def set_mem_bank(self, bank):
- cfg = self.__read_reg(_FUNC_CFG_ACCESS) & 0x3F
- self.__write_reg(_FUNC_CFG_ACCESS, cfg | (bank << 6))
-
- def set_embedded_functions(self, enable, emb_ab=None):
- self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
- if enable:
- self.__write_reg(_EMB_FUNC_EN_A, emb_ab[0])
- self.__write_reg(_EMB_FUNC_EN_B, emb_ab[1])
- else:
- emb_a = self.__read_reg(_EMB_FUNC_EN_A)
- emb_b = self.__read_reg(_EMB_FUNC_EN_B)
- self.__write_reg(_EMB_FUNC_EN_A, (emb_a & 0xC7))
- self.__write_reg(_EMB_FUNC_EN_B, (emb_b & 0xE6))
- emb_ab = (emb_a, emb_b)
-
- self.set_mem_bank(_FUNC_CFG_BANK_USER)
- return emb_ab
-
- def load_mlc(self, ucf):
- # Load MLC config from file
- with open(ucf, "r") as ucf_file:
- for l in ucf_file:
- if l.startswith("Ac"):
- v = [int(v, 16) for v in l.strip().split(" ")[1:3]]
- self.__write_reg(v[0], v[1])
-
- emb_ab = self.set_embedded_functions(False)
-
- # Disable I3C interface
- self.__write_reg(_CTRL9_XL, self.__read_reg(_CTRL9_XL) | 0x01)
-
- # Enable Block Data Update
- self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x40)
-
- # Route signals on interrupt pin 1
- self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
- self.__write_reg(_MLC_INT1, self.__read_reg(_MLC_INT1) & 0x01)
- self.set_mem_bank(_FUNC_CFG_BANK_USER)
-
- # Configure interrupt pin mode
- self.__write_reg(_TAP_CFG0, self.__read_reg(_TAP_CFG0) | 0x41)
-
- self.set_embedded_functions(True, emb_ab)
-
- def read_mlc_output(self):
- buf = None
- if self.__read_reg(_MLC_STATUS) & 0x1:
- self.__read_reg(0x1A, size=12)
- self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
- buf = self.__read_reg(_MLC0_SRC, 8)
- self.set_mem_bank(_FUNC_CFG_BANK_USER)
- return buf
-
- def read_gyro(self):
- """Returns gyroscope vector in degrees/sec."""
- mv = memoryview(self.scratch_int)
- f = self.gyro_scale
- self.__read_reg_into(_OUTX_L_G, mv)
- return (mv[0] / f, mv[1] / f, mv[2] / f)
-
- def read_accel(self):
- """Returns acceleration vector in gravity units (9.81m/s^2)."""
- mv = memoryview(self.scratch_int)
- f = self.accel_scale
- self.__read_reg_into(_OUTX_L_XL, mv)
- return (mv[0] / f, mv[1] / f, mv[2] / f)
diff --git a/drivers/lsm6dsox/lsm6dsox_basic.py b/drivers/lsm6dsox/lsm6dsox_basic.py
deleted file mode 100644
index 0ffe9e92b7689..0000000000000
--- a/drivers/lsm6dsox/lsm6dsox_basic.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# LSM6DSOX Basic Example.
-import time
-from lsm6dsox import LSM6DSOX
-
-from machine import Pin, I2C
-
-lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
-# Or init in SPI mode.
-# lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10))
-
-while True:
- print("Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_accel()))
- print("Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_gyro()))
- print("")
- time.sleep_ms(100)
diff --git a/drivers/lsm6dsox/lsm6dsox_mlc.py b/drivers/lsm6dsox/lsm6dsox_mlc.py
deleted file mode 100644
index 866498d0ce13e..0000000000000
--- a/drivers/lsm6dsox/lsm6dsox_mlc.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# LSM6DSOX IMU MLC (Machine Learning Core) Example.
-# Download the raw UCF file, copy to storage and reset.
-
-# NOTE: The pre-trained models (UCF files) for the examples can be found here:
-# https://github.com/STMicroelectronics/STMems_Machine_Learning_Core/tree/master/application_examples/lsm6dsox
-
-import time
-from lsm6dsox import LSM6DSOX
-from machine import Pin, I2C
-
-INT_MODE = True # Run in interrupt mode.
-INT_FLAG = False # Set True on interrupt.
-
-
-def imu_int_handler(pin):
- global INT_FLAG
- INT_FLAG = True
-
-
-if INT_MODE == True:
- int_pin = Pin(24)
- int_pin.irq(handler=imu_int_handler, trigger=Pin.IRQ_RISING)
-
-i2c = I2C(0, scl=Pin(13), sda=Pin(12))
-
-# Vibration detection example
-UCF_FILE = "lsm6dsox_vibration_monitoring.ucf"
-UCF_LABELS = {0: "no vibration", 1: "low vibration", 2: "high vibration"}
-# NOTE: Selected data rate and scale must match the MLC data rate and scale.
-lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=2000, accel_scale=4, ucf=UCF_FILE)
-
-# Head gestures example
-# UCF_FILE = "lsm6dsox_head_gestures.ucf"
-# UCF_LABELS = {0:"Nod", 1:"Shake", 2:"Stationary", 3:"Swing", 4:"Walk"}
-# NOTE: Selected data rate and scale must match the MLC data rate and scale.
-# lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=250, accel_scale=2, ucf=UCF_FILE)
-
-print("MLC configured...")
-
-while True:
- if INT_MODE:
- if INT_FLAG:
- INT_FLAG = False
- print(UCF_LABELS[lsm.read_mlc_output()[0]])
- else:
- buf = lsm.read_mlc_output()
- if buf != None:
- print(UCF_LABELS[buf[0]])
diff --git a/drivers/memory/external_flash_device.h b/drivers/memory/external_flash_device.h
new file mode 100644
index 0000000000000..03798446036aa
--- /dev/null
+++ b/drivers/memory/external_flash_device.h
@@ -0,0 +1,461 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC
+ *
+ * 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_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H
+
+#include
+#include
+
+typedef struct {
+ uint32_t total_size;
+ uint16_t start_up_time_us;
+
+ // Three response bytes to 0x9f JEDEC ID command.
+ uint8_t manufacturer_id;
+ uint8_t memory_type;
+ uint8_t capacity;
+
+ // Max clock speed for all operations and the fastest read mode.
+ uint8_t max_clock_speed_mhz;
+
+ // Bitmask for Quad Enable bit if present. 0x00 otherwise. This is for the highest byte in the
+ // status register.
+ uint8_t quad_enable_bit_mask;
+
+ bool has_sector_protection : 1;
+
+ // Supports the 0x0b fast read command with 8 dummy cycles.
+ bool supports_fast_read : 1;
+
+ // Supports the fast read, quad output command 0x6b with 8 dummy cycles.
+ bool supports_qspi : 1;
+
+ // Supports the quad input page program command 0x32. This is known as 1-1-4 because it only
+ // uses all four lines for data.
+ bool supports_qspi_writes : 1;
+
+ // Requires a separate command 0x31 to write to the second byte of the status register.
+ // Otherwise two byte are written via 0x01.
+ bool write_status_register_split : 1;
+
+ // True when the status register is a single byte. This implies the Quad Enable bit is in the
+ // first byte and the Read Status Register 2 command (0x35) is unsupported.
+ bool single_status_byte : 1;
+} external_flash_device;
+
+// Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21
+// Xplained board.
+// Datasheet: https://www.adestotech.com/wp-content/uploads/doc8715.pdf
+#define AT25DF081A { \
+ .total_size = (1 << 20), /* 1 MiB */ \
+ .start_up_time_us = 10000, \
+ .manufacturer_id = 0x1f, \
+ .memory_type = 0x45, \
+ .capacity = 0x01, \
+ .max_clock_speed_mhz = 85, \
+ .quad_enable_bit_mask = 0x00, \
+ .has_sector_protection = true, \
+ .supports_fast_read = true, \
+ .supports_qspi = false, \
+ .supports_qspi_writes = false, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Gigadevice GD25Q16C 2MiB SPI flash.
+// Datasheet: http://www.gigadevice.com/datasheet/gd25q16c/
+#define GD25Q16C { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xc8, \
+ .memory_type = 0x40, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Gigadevice GD25Q64C 8MiB SPI flash.
+// Datasheet: http://www.elm-tech.com/en/products/spi-flash-memory/gd25q64/gd25q64.pdf
+#define GD25Q64C { \
+ .total_size = (1 << 23), /* 8 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xc8, \
+ .memory_type = 0x40, \
+ .capacity = 0x17, \
+ .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = true, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash.
+// Datasheet: http://www.cypress.com/file/316661/download
+#define S25FL064L { \
+ .total_size = (1 << 23), /* 8 MiB */ \
+ .start_up_time_us = 300, \
+ .manufacturer_id = 0x01, \
+ .memory_type = 0x60, \
+ .capacity = 0x17, \
+ .max_clock_speed_mhz = 108, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Cypress (was Spansion) S25FL116K 2MiB SPI flash.
+// Datasheet: http://www.cypress.com/file/196886/download
+#define S25FL116K { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 10000, \
+ .manufacturer_id = 0x01, \
+ .memory_type = 0x40, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 108, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = false, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Cypress (was Spansion) S25FL216K 2MiB SPI flash.
+// Datasheet: http://www.cypress.com/file/197346/download
+#define S25FL216K { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 10000, \
+ .manufacturer_id = 0x01, \
+ .memory_type = 0x40, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 65, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = false, \
+ .supports_qspi_writes = false, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Winbond W25Q16FW 2MiB SPI flash.
+// Datasheet: https://www.winbond.com/resource-files/w25q16fw%20revj%2005182017%20sfdp.pdf
+#define W25Q16FW { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x60, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Winbond W25Q16JV-IQ 2MiB SPI flash. Note that JV-IM has a different .memory_type (0x70)
+// Datasheet: https://www.winbond.com/resource-files/w25q16jv%20spi%20revf%2005092017.pdf
+#define W25Q16JV_IQ { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x40, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Winbond W25Q16JV-IM 2MiB SPI flash. Note that JV-IQ has a different .memory_type (0x40)
+// Datasheet: https://www.winbond.com/resource-files/w25q16jv%20spi%20revf%2005092017.pdf
+#define W25Q16JV_IM { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x70, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+}
+
+// Settings for the Winbond W25Q32BV 4MiB SPI flash.
+// Datasheet: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf
+#define W25Q32BV { \
+ .total_size = (1 << 22), /* 4 MiB */ \
+ .start_up_time_us = 10000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x60, \
+ .capacity = 0x16, \
+ .max_clock_speed_mhz = 104, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = false, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+// Settings for the Winbond W25Q32JV-IM 4MiB SPI flash.
+// Datasheet: https://www.winbond.com/resource-files/w25q32jv%20revg%2003272018%20plus.pdf
+#define W25Q32JV_IM { \
+ .total_size = (1 << 22), /* 4 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x70, \
+ .capacity = 0x16, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+}
+
+// Settings for the Winbond W25Q32JV-IM 4MiB SPI flash.
+// Datasheet: https://www.winbond.com/resource-files/w25q32jv%20revg%2003272018%20plus.pdf
+#define W25Q32JV_IQ { \
+ .total_size = (1 << 22), /* 4 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x40, \
+ .capacity = 0x16, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+}
+
+// Settings for the Winbond W25Q64JV-IM 8MiB SPI flash. Note that JV-IQ has a different .memory_type (0x40)
+// Datasheet: http://www.winbond.com/resource-files/w25q64jv%20revj%2003272018%20plus.pdf
+#define W25Q64JV_IM { \
+ .total_size = (1 << 23), /* 8 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x70, \
+ .capacity = 0x17, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Winbond W25Q64JV-IQ 8MiB SPI flash. Note that JV-IM has a different .memory_type (0x70)
+// Datasheet: http://www.winbond.com/resource-files/w25q64jv%20revj%2003272018%20plus.pdf
+#define W25Q64JV_IQ { \
+ .total_size = (1 << 23), /* 8 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x40, \
+ .capacity = 0x17, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Winbond W25Q80DL 1MiB SPI flash.
+// Datasheet: https://www.winbond.com/resource-files/w25q80dv%20dl_revh_10022015.pdf
+#define W25Q80DL { \
+ .total_size = (1 << 20), /* 1 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x60, \
+ .capacity = 0x14, \
+ .max_clock_speed_mhz = 104, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = false, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+
+// Settings for the Winbond W25Q128JV-SQ 16MiB SPI flash. Note that JV-IM has a different .memory_type (0x70)
+// Datasheet: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf
+#define W25Q128JV_SQ { \
+ .total_size = (1 << 24), /* 16 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x40, \
+ .capacity = 0x18, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for the Macronix MX25L1606 2MiB SPI flash.
+// Datasheet:
+#define MX25L1606 { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xc2, \
+ .memory_type = 0x20, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 8, \
+ .quad_enable_bit_mask = 0x40, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = true, \
+}
+
+// Settings for the Macronix MX25L3233F 4MiB SPI flash.
+// Datasheet: http://www.macronix.com/Lists/Datasheet/Attachments/7426/MX25L3233F,%203V,%2032Mb,%20v1.6.pdf
+#define MX25L3233F { \
+ .total_size = (1 << 22), /* 4 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xc2, \
+ .memory_type = 0x20, \
+ .capacity = 0x16, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x40, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = true, \
+}
+
+// Settings for the Macronix MX25R6435F 8MiB SPI flash.
+// Datasheet: http://www.macronix.com/Lists/Datasheet/Attachments/7428/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.4.pdf
+// By default its in lower power mode which can only do 8mhz. In high power mode it can do 80mhz.
+#define MX25R6435F { \
+ .total_size = (1 << 23), /* 8 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xc2, \
+ .memory_type = 0x28, \
+ .capacity = 0x17, \
+ .max_clock_speed_mhz = 8, \
+ .quad_enable_bit_mask = 0x40, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = true, \
+}
+
+// Settings for the Winbond W25Q128JV-PM 16MiB SPI flash. Note that JV-IM has a different .memory_type (0x70)
+// Datasheet: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf
+#define W25Q128JV_PM { \
+ .total_size = (1 << 24), /* 16 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x70, \
+ .capacity = 0x18, \
+ .max_clock_speed_mhz = 133, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+}
+
+// Settings for the Winbond W25Q32FV 4MiB SPI flash.
+// Datasheet:http://www.winbond.com/resource-files/w25q32fv%20revj%2006032016.pdf?__locale=en
+#define W25Q32FV { \
+ .total_size = (1 << 22), /* 4 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0xef, \
+ .memory_type = 0x40, \
+ .capacity = 0x16, \
+ .max_clock_speed_mhz = 104, \
+ .quad_enable_bit_mask = 0x00, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = false, \
+ .supports_qspi_writes = false, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+
+// Settings for a GENERIC device with the most common setting
+#define GENERIC { \
+ .total_size = (1 << 21), /* 2 MiB */ \
+ .start_up_time_us = 5000, \
+ .manufacturer_id = 0x00, \
+ .memory_type = 0x40, \
+ .capacity = 0x15, \
+ .max_clock_speed_mhz = 48, \
+ .quad_enable_bit_mask = 0x02, \
+ .has_sector_protection = false, \
+ .supports_fast_read = true, \
+ .supports_qspi = true, \
+ .supports_qspi_writes = true, \
+ .write_status_register_split = false, \
+ .single_status_byte = false, \
+}
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H
diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c
index 9f8dc29a734de..52739b1d8bdf7 100644
--- a/drivers/memory/spiflash.c
+++ b/drivers/memory/spiflash.c
@@ -70,7 +70,8 @@ STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) {
}
}
-STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) {
+STATIC int mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) {
+ int ret = 0;
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
// Note: len/data are unused for standard SPI
@@ -78,11 +79,13 @@ STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 1, &cmd, NULL);
mp_hal_pin_write(c->bus.u_spi.cs, 1);
} else {
- c->bus.u_qspi.proto->write_cmd_data(c->bus.u_qspi.data, cmd, len, data);
+ ret = c->bus.u_qspi.proto->write_cmd_data(c->bus.u_qspi.data, cmd, len, data);
}
+ return ret;
}
-STATIC void mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) {
+STATIC int mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) {
+ int ret = 0;
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
uint8_t buf[5] = {cmd, 0};
@@ -98,28 +101,28 @@ STATIC void mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd,
mp_hal_pin_write(c->bus.u_spi.cs, 1);
} else {
if (dest != NULL) {
- c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest);
+ ret = c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest);
} else {
- c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
+ ret = c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
}
}
+ return ret;
}
-STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len) {
+STATIC int mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t *dest) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
- uint32_t buf;
mp_hal_pin_write(c->bus.u_spi.cs, 0);
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 1, &cmd, NULL);
- c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, (void*)&buf, (void*)&buf);
+ c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, (void*)dest, (void*)dest);
mp_hal_pin_write(c->bus.u_spi.cs, 1);
- return buf;
+ return 0;
} else {
- return c->bus.u_qspi.proto->read_cmd(c->bus.u_qspi.data, cmd, len);
+ return c->bus.u_qspi.proto->read_cmd(c->bus.u_qspi.data, cmd, len, dest);
}
}
-STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+STATIC int mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
const mp_spiflash_config_t *c = self->config;
uint8_t cmd;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
@@ -127,17 +130,20 @@ STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len
} else {
cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_C4READ_32 : CMD_C4READ;
}
- mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest);
+ return mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest);
}
-STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
- mp_spiflash_write_cmd_data(self, cmd, 0, 0);
+STATIC int mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
+ return mp_spiflash_write_cmd_data(self, cmd, 0, 0);
}
STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
- uint8_t sr;
do {
- sr = mp_spiflash_read_cmd(self, CMD_RDSR, 1);
+ uint32_t sr;
+ int ret = mp_spiflash_read_cmd(self, CMD_RDSR, 1, &sr);
+ if (ret != 0) {
+ return ret;
+ }
if ((sr & mask) == val) {
return 0; // success
}
@@ -176,17 +182,23 @@ void mp_spiflash_init(mp_spiflash_t *self) {
#if defined(CHECK_DEVID)
// Validate device id
- uint32_t devid = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3);
- if (devid != CHECK_DEVID) {
- return 0;
+ uint32_t devid;
+ int ret = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3, &devid);
+ if (ret != 0 || devid != CHECK_DEVID) {
+ mp_spiflash_release_bus(self);
+ return;
}
#endif
if (self->config->bus_kind == MP_SPIFLASH_BUS_QSPI) {
// Set QE bit
- uint32_t data = (mp_spiflash_read_cmd(self, CMD_RDSR, 1) & 0xff)
- | (mp_spiflash_read_cmd(self, CMD_RDCR, 1) & 0xff) << 8;
- if (!(data & (QSPI_QE_MASK << 8))) {
+ uint32_t sr = 0, cr = 0;
+ int ret = mp_spiflash_read_cmd(self, CMD_RDSR, 1, &sr);
+ if (ret == 0) {
+ ret = mp_spiflash_read_cmd(self, CMD_RDCR, 1, &cr);
+ }
+ uint32_t data = (sr & 0xff) | (cr & 0xff) << 8;
+ if (ret == 0 && !(data & (QSPI_QE_MASK << 8))) {
data |= QSPI_QE_MASK << 8;
mp_spiflash_write_cmd(self, CMD_WREN);
mp_spiflash_write_cmd_data(self, CMD_WRSR, 2, data);
@@ -208,36 +220,50 @@ void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) {
}
STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) {
+ int ret = 0;
// enable writes
- mp_spiflash_write_cmd(self, CMD_WREN);
+ ret = mp_spiflash_write_cmd(self, CMD_WREN);
+ if (ret != 0) {
+ return ret;
+ }
// wait WEL=1
- int ret = mp_spiflash_wait_wel1(self);
+ ret = mp_spiflash_wait_wel1(self);
if (ret != 0) {
return ret;
}
// erase the sector
uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_SEC_ERASE_32 : CMD_SEC_ERASE;
- mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL);
+ ret = mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL);
+ if (ret != 0) {
+ return ret;
+ }
// wait WIP=0
return mp_spiflash_wait_wip0(self);
}
STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
+ int ret = 0;
// enable writes
- mp_spiflash_write_cmd(self, CMD_WREN);
+ ret = mp_spiflash_write_cmd(self, CMD_WREN);
+ if (ret != 0) {
+ return ret;
+ }
// wait WEL=1
- int ret = mp_spiflash_wait_wel1(self);
+ ret = mp_spiflash_wait_wel1(self);
if (ret != 0) {
return ret;
}
// write the page
uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_WRITE_32 : CMD_WRITE;
- mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL);
+ ret = mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL);
+ if (ret != 0) {
+ return ret;
+ }
// wait WIP=0
return mp_spiflash_wait_wip0(self);
@@ -253,13 +279,14 @@ int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr) {
return ret;
}
-void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+int mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
if (len == 0) {
- return;
+ return 0;
}
mp_spiflash_acquire_bus(self);
- mp_spiflash_read_data(self, addr, len, dest);
+ int ret = mp_spiflash_read_data(self, addr, len, dest);
mp_spiflash_release_bus(self);
+ return ret;
}
int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
@@ -289,9 +316,9 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
-void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+int mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
if (len == 0) {
- return;
+ return 0;
}
mp_spiflash_acquire_bus(self);
mp_spiflash_cache_t *cache = self->config->cache;
@@ -304,7 +331,11 @@ void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uin
if (bis < cache->block) {
// Read direct from flash for first part
rest = cache->block * SECTOR_SIZE - addr;
- mp_spiflash_read_data(self, addr, rest, dest);
+ int ret = mp_spiflash_read_data(self, addr, rest, dest);
+ if (ret != 0) {
+ mp_spiflash_release_bus(self);
+ return ret;
+ }
len -= rest;
dest += rest;
addr += rest;
@@ -318,21 +349,22 @@ void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uin
len -= rest;
if (len == 0) {
mp_spiflash_release_bus(self);
- return;
+ return 0;
}
dest += rest;
addr += rest;
}
}
// Read rest direct from flash
- mp_spiflash_read_data(self, addr, len, dest);
+ int ret = mp_spiflash_read_data(self, addr, len, dest);
mp_spiflash_release_bus(self);
+ return ret;
}
-STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
+STATIC int mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
#if USE_WR_DELAY
if (!(self->flags & 1)) {
- return;
+ return 0;
}
self->flags &= ~1;
@@ -342,7 +374,7 @@ STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
// Erase sector
int ret = mp_spiflash_erase_block_internal(self, cache->block * SECTOR_SIZE);
if (ret != 0) {
- return;
+ return ret;
}
// Write
@@ -350,16 +382,18 @@ STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
uint32_t addr = cache->block * SECTOR_SIZE + i * PAGE_SIZE;
int ret = mp_spiflash_write_page(self, addr, PAGE_SIZE, cache->buf + i * PAGE_SIZE);
if (ret != 0) {
- return;
+ return ret;
}
}
#endif
+ return 0;
}
-void mp_spiflash_cache_flush(mp_spiflash_t *self) {
+int mp_spiflash_cache_flush(mp_spiflash_t *self) {
mp_spiflash_acquire_bus(self);
- mp_spiflash_cache_flush_internal(self);
+ int ret = mp_spiflash_cache_flush_internal(self);
mp_spiflash_release_bus(self);
+ return ret;
}
STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
@@ -389,10 +423,16 @@ STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, siz
// Read sector
#if USE_WR_DELAY
if (cache->block != 0xffffffff) {
- mp_spiflash_cache_flush_internal(self);
+ int ret = mp_spiflash_cache_flush_internal(self);
+ if (ret != 0) {
+ return ret;
+ }
}
#endif
- mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf);
+ int ret = mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf);
+ if (ret != 0) {
+ return ret;
+ }
}
#if USE_WR_DELAY
diff --git a/drivers/memory/spiflash.h b/drivers/memory/spiflash.h
index c4162ff21cdc6..5ccf7d44c97de 100644
--- a/drivers/memory/spiflash.h
+++ b/drivers/memory/spiflash.h
@@ -76,13 +76,13 @@ void mp_spiflash_deepsleep(mp_spiflash_t *self, int value);
// These functions go direct to the SPI flash device
int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr);
-void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
+int mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src);
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
// These functions use the cache (which must already be configured)
-void mp_spiflash_cache_flush(mp_spiflash_t *self);
-void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
+int mp_spiflash_cache_flush(mp_spiflash_t *self);
+int mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src);
#endif
diff --git a/drivers/neopixel/manifest.py b/drivers/neopixel/manifest.py
deleted file mode 100644
index 27f610adc0ad7..0000000000000
--- a/drivers/neopixel/manifest.py
+++ /dev/null
@@ -1,5 +0,0 @@
-freeze(
- ".",
- "neopixel.py",
- opt=3,
-)
diff --git a/drivers/neopixel/neopixel.py b/drivers/neopixel/neopixel.py
deleted file mode 100644
index caa12dc845361..0000000000000
--- a/drivers/neopixel/neopixel.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# NeoPixel driver for MicroPython
-# MIT license; Copyright (c) 2016 Damien P. George, 2021 Jim Mussared
-
-from machine import bitstream
-
-
-class NeoPixel:
- # G R B W
- ORDER = (1, 0, 2, 3)
-
- def __init__(self, pin, n, bpp=3, timing=1):
- self.pin = pin
- self.n = n
- self.bpp = bpp
- self.buf = bytearray(n * bpp)
- self.pin.init(pin.OUT)
- # Timing arg can either be 1 for 800kHz or 0 for 400kHz,
- # or a user-specified timing ns tuple (high_0, low_0, high_1, low_1).
- self.timing = (
- ((400, 850, 800, 450) if timing else (800, 1700, 1600, 900))
- if isinstance(timing, int)
- else timing
- )
-
- def __len__(self):
- return self.n
-
- def __setitem__(self, i, v):
- offset = i * self.bpp
- for i in range(self.bpp):
- self.buf[offset + self.ORDER[i]] = v[i]
-
- def __getitem__(self, i):
- offset = i * self.bpp
- return tuple(self.buf[offset + self.ORDER[i]] for i in range(self.bpp))
-
- def fill(self, v):
- b = self.buf
- l = len(self.buf)
- bpp = self.bpp
- for i in range(bpp):
- c = v[i]
- j = self.ORDER[i]
- while j < l:
- b[j] = c
- j += bpp
-
- def write(self):
- # BITSTREAM_TYPE_HIGH_LOW = 0
- bitstream(self.pin, 0, self.timing, self.buf)
diff --git a/drivers/ninaw10/machine_pin_nina.c b/drivers/ninaw10/machine_pin_nina.c
new file mode 100644
index 0000000000000..025ecb66af0d2
--- /dev/null
+++ b/drivers/ninaw10/machine_pin_nina.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Ibrahim Abdelkader
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+
+#if defined(MICROPY_PY_NETWORK_NINAW10) && defined(MICROPY_HW_PIN_EXT_COUNT)
+
+#include "modmachine.h"
+#include "machine_pin.h"
+#include "nina_wifi_drv.h"
+
+#define NINA_GPIO_INPUT (0x00)
+#define NINA_GPIO_OUTPUT (0x01)
+#define NINA_GPIO_INPUT_PULLUP (0x02)
+
+#define NINA_GPIO_MODE (0x50)
+#define NINA_GPIO_READ (0x53)
+#define NINA_GPIO_WRITE (0x51)
+#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 34 && p <= 36) || (p == 39))
+
+static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
+ 27, // LEDR
+ 25, // LEDG
+ 26, // LEDB
+ 34, // A4
+ 39, // A5
+ 36, // A6
+ 35, // A7
+};
+
+void machine_pin_ext_init(void) {
+ nina_init();
+}
+
+void machine_pin_ext_set(machine_pin_obj_t *self, bool value) {
+ if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
+ uint8_t buf[] = {pin_map[self->id], value};
+ nina_ioctl(NINA_GPIO_WRITE, sizeof(buf), buf, 0);
+ }
+}
+
+bool machine_pin_ext_get(machine_pin_obj_t *self) {
+ bool value = false;
+ if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
+ uint8_t buf[] = {pin_map[self->id]};
+ nina_ioctl(NINA_GPIO_READ, sizeof(buf), buf, 0);
+ value = buf[0];
+ }
+ return value;
+}
+
+void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
+ if (mode == MACHINE_PIN_MODE_IN) {
+ mode = NINA_GPIO_INPUT;
+ self->is_output = false;
+ } else if (mode == MACHINE_PIN_MODE_OUT) {
+ mode = NINA_GPIO_OUTPUT;
+ self->is_output = true;
+ } else {
+ mp_raise_ValueError("only Pin.OUT and Pin.IN are supported for this pin");
+ }
+ if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
+ uint8_t buf[] = {pin_map[self->id], mode};
+ if (mode == NINA_GPIO_OUTPUT) {
+ if (NINA_GPIO_IS_INPUT_ONLY(buf[0])) {
+ mp_raise_ValueError("only Pin.IN is supported for this pin");
+ }
+ machine_pin_ext_set(self, value);
+ }
+ nina_ioctl(NINA_GPIO_MODE, sizeof(buf), buf, 0);
+ }
+}
+
+#endif // defined(MICROPY_PY_NETWORK_NINAW10) && defined(MICROPY_HW_PIN_EXT_COUNT)
diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c
index a65ef7fd86448..c65fb111fb101 100644
--- a/drivers/ninaw10/nina_wifi_bsp.c
+++ b/drivers/ninaw10/nina_wifi_bsp.c
@@ -73,7 +73,7 @@ int nina_bsp_init(void) {
MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE),
};
- MP_STATE_PORT(mp_wifi_spi) = machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 0, args);
+ MP_STATE_PORT(mp_wifi_spi) = MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 0, args);
return 0;
}
@@ -137,7 +137,7 @@ int nina_bsp_spi_slave_deselect(void) {
int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) {
mp_obj_t mp_wifi_spi = MP_STATE_PORT(mp_wifi_spi);
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer(mp_wifi_spi, size, tx_buf, rx_buf);
+ ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, protocol))->transfer(mp_wifi_spi, size, tx_buf, rx_buf);
#if NINA_DEBUG
for (int i = 0; i < size; i++) {
if (tx_buf) {
diff --git a/drivers/ninaw10/nina_wifi_drv.c b/drivers/ninaw10/nina_wifi_drv.c
index 7a1167b2c94c0..111ead003dee5 100644
--- a/drivers/ninaw10/nina_wifi_drv.c
+++ b/drivers/ninaw10/nina_wifi_drv.c
@@ -105,9 +105,10 @@ typedef enum {
NINA_CMD_AP_GET_BSSID = 0x3C,
NINA_CMD_AP_GET_CHANNEL = 0x3D,
- // Disonnect/status commands.
+ // Disconnect/status commands.
NINA_CMD_DISCONNECT = 0x30,
NINA_CMD_CONN_STATUS = 0x20,
+ NINA_CMD_CONN_REASON = 0x1F,
// Interface config commands.
NINA_CMD_SET_IF_CONFIG = 0x14,
@@ -173,19 +174,6 @@ typedef enum {
NINA_CMD_CMD_DOWNLOAD_OTA = 0x67,
} nina_cmd_t;
-typedef enum {
- NINA_STATUS_IDLE = 0,
- NINA_STATUS_NO_SSID_AVAIL,
- NINA_STATUS_SCAN_COMPLETED,
- NINA_STATUS_CONNECTED,
- NINA_STATUS_CONNECT_FAILED,
- NINA_STATUS_CONNECTION_LOST,
- NINA_STATUS_DISCONNECTED,
- NINA_STATUS_AP_LISTENING,
- NINA_STATUS_AP_CONNECTED,
- NINA_STATUS_AP_FAILED
-} nina_status_t;
-
typedef enum {
SOCKET_STATE_CLOSED = 0,
SOCKET_STATE_LISTEN,
@@ -364,13 +352,15 @@ int nina_deinit(void) {
return nina_bsp_deinit();
}
-static int nina_connection_status() {
+int nina_connection_status(void) {
return nina_send_command_read_ack(NINA_CMD_CONN_STATUS, 0, ARG_8BITS, NULL);
}
-int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
- uint8_t status = NINA_STATUS_CONNECT_FAILED;
+int nina_connection_reason(void) {
+ return nina_send_command_read_ack(NINA_CMD_CONN_REASON, 0, ARG_8BITS, NULL);
+}
+int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
if (key == NULL && security != NINA_SEC_OPEN) {
return -1;
}
@@ -398,18 +388,7 @@ int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t c
return -1;
}
- for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
- status = nina_connection_status();
- if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
- break;
- }
-
- if ((mp_hal_ticks_ms() - start) >= NINA_CONNECT_TIMEOUT) {
- break;
- }
- }
-
- return (status == NINA_STATUS_CONNECTED) ? 0 : -1;
+ return 0;
}
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
@@ -439,7 +418,7 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
status = nina_connection_status();
- if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
+ if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL)) {
break;
}
diff --git a/drivers/ninaw10/nina_wifi_drv.h b/drivers/ninaw10/nina_wifi_drv.h
index 22163c7286e9e..4b09ac8bd24ab 100644
--- a/drivers/ninaw10/nina_wifi_drv.h
+++ b/drivers/ninaw10/nina_wifi_drv.h
@@ -46,6 +46,17 @@
#define NINA_FW_VER_MINOR_OFFS (2)
#define NINA_FW_VER_PATCH_OFFS (4)
+#define NINA_ESP_REASON_AUTH_EXPIRE (2)
+#define NINA_ESP_REASON_ASSOC_EXPIRE (4)
+#define NINA_ESP_REASON_NOT_AUTHED (6)
+#define NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT (15)
+#define NINA_ESP_REASON_BEACON_TIMEOUT (200)
+#define NINA_ESP_REASON_NO_AP_FOUND (201)
+#define NINA_ESP_REASON_AUTH_FAIL (202)
+#define NINA_ESP_REASON_ASSOC_FAIL (203)
+#define NINA_ESP_REASON_HANDSHAKE_TIMEOUT (204)
+#define NINA_ESP_REASON_CONNECTION_FAIL (205)
+
typedef enum {
NINA_SEC_INVALID = 0,
NINA_SEC_OPEN,
@@ -59,6 +70,19 @@ typedef enum {
NINA_SOCKET_TYPE_RAW = 3,
} nina_socket_type_t;
+typedef enum {
+ NINA_STATUS_IDLE = 0,
+ NINA_STATUS_NO_SSID_AVAIL = 1,
+ NINA_STATUS_SCAN_COMPLETED = 2,
+ NINA_STATUS_CONNECTED = 3,
+ NINA_STATUS_CONNECT_FAILED = 4,
+ NINA_STATUS_CONNECTION_LOST = 5,
+ NINA_STATUS_DISCONNECTED = 6,
+ NINA_STATUS_AP_LISTENING = 7,
+ NINA_STATUS_AP_CONNECTED = 8,
+ NINA_STATUS_AP_FAILED = 9
+} nina_status_t;
+
typedef struct {
uint8_t ip_addr[NINA_IPV4_ADDR_LEN];
uint8_t subnet_addr[NINA_IPV4_ADDR_LEN];
@@ -85,6 +109,8 @@ typedef int (*nina_scan_callback_t)(nina_scan_result_t *, void *);
int nina_init(void);
int nina_deinit(void);
+int nina_connection_status(void);
+int nina_connection_reason(void);
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel);
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel);
int nina_disconnect(void);
diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py
deleted file mode 100644
index 76d55312f8568..0000000000000
--- a/drivers/nrf24l01/nrf24l01.py
+++ /dev/null
@@ -1,252 +0,0 @@
-"""NRF24L01 driver for MicroPython
-"""
-
-from micropython import const
-import utime
-
-# nRF24L01+ registers
-CONFIG = const(0x00)
-EN_RXADDR = const(0x02)
-SETUP_AW = const(0x03)
-SETUP_RETR = const(0x04)
-RF_CH = const(0x05)
-RF_SETUP = const(0x06)
-STATUS = const(0x07)
-RX_ADDR_P0 = const(0x0A)
-TX_ADDR = const(0x10)
-RX_PW_P0 = const(0x11)
-FIFO_STATUS = const(0x17)
-DYNPD = const(0x1C)
-
-# CONFIG register
-EN_CRC = const(0x08) # enable CRC
-CRCO = const(0x04) # CRC encoding scheme; 0=1 byte, 1=2 bytes
-PWR_UP = const(0x02) # 1=power up, 0=power down
-PRIM_RX = const(0x01) # RX/TX control; 0=PTX, 1=PRX
-
-# RF_SETUP register
-POWER_0 = const(0x00) # -18 dBm
-POWER_1 = const(0x02) # -12 dBm
-POWER_2 = const(0x04) # -6 dBm
-POWER_3 = const(0x06) # 0 dBm
-SPEED_1M = const(0x00)
-SPEED_2M = const(0x08)
-SPEED_250K = const(0x20)
-
-# STATUS register
-RX_DR = const(0x40) # RX data ready; write 1 to clear
-TX_DS = const(0x20) # TX data sent; write 1 to clear
-MAX_RT = const(0x10) # max retransmits reached; write 1 to clear
-
-# FIFO_STATUS register
-RX_EMPTY = const(0x01) # 1 if RX FIFO is empty
-
-# constants for instructions
-R_RX_PL_WID = const(0x60) # read RX payload width
-R_RX_PAYLOAD = const(0x61) # read RX payload
-W_TX_PAYLOAD = const(0xA0) # write TX payload
-FLUSH_TX = const(0xE1) # flush TX FIFO
-FLUSH_RX = const(0xE2) # flush RX FIFO
-NOP = const(0xFF) # use to read STATUS register
-
-
-class NRF24L01:
- def __init__(self, spi, cs, ce, channel=46, payload_size=16):
- assert payload_size <= 32
-
- self.buf = bytearray(1)
-
- # store the pins
- self.spi = spi
- self.cs = cs
- self.ce = ce
-
- # init the SPI bus and pins
- self.init_spi(4000000)
-
- # reset everything
- ce.init(ce.OUT, value=0)
- cs.init(cs.OUT, value=1)
-
- self.payload_size = payload_size
- self.pipe0_read_addr = None
- utime.sleep_ms(5)
-
- # set address width to 5 bytes and check for device present
- self.reg_write(SETUP_AW, 0b11)
- if self.reg_read(SETUP_AW) != 0b11:
- raise OSError("nRF24L01+ Hardware not responding")
-
- # disable dynamic payloads
- self.reg_write(DYNPD, 0)
-
- # auto retransmit delay: 1750us
- # auto retransmit count: 8
- self.reg_write(SETUP_RETR, (6 << 4) | 8)
-
- # set rf power and speed
- self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links
-
- # init CRC
- self.set_crc(2)
-
- # clear status flags
- self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
-
- # set channel
- self.set_channel(channel)
-
- # flush buffers
- self.flush_rx()
- self.flush_tx()
-
- def init_spi(self, baudrate):
- try:
- master = self.spi.MASTER
- except AttributeError:
- self.spi.init(baudrate=baudrate, polarity=0, phase=0)
- else:
- self.spi.init(master, baudrate=baudrate, polarity=0, phase=0)
-
- def reg_read(self, reg):
- self.cs(0)
- self.spi.readinto(self.buf, reg)
- self.spi.readinto(self.buf)
- self.cs(1)
- return self.buf[0]
-
- def reg_write_bytes(self, reg, buf):
- self.cs(0)
- self.spi.readinto(self.buf, 0x20 | reg)
- self.spi.write(buf)
- self.cs(1)
- return self.buf[0]
-
- def reg_write(self, reg, value):
- self.cs(0)
- self.spi.readinto(self.buf, 0x20 | reg)
- ret = self.buf[0]
- self.spi.readinto(self.buf, value)
- self.cs(1)
- return ret
-
- def flush_rx(self):
- self.cs(0)
- self.spi.readinto(self.buf, FLUSH_RX)
- self.cs(1)
-
- def flush_tx(self):
- self.cs(0)
- self.spi.readinto(self.buf, FLUSH_TX)
- self.cs(1)
-
- # power is one of POWER_x defines; speed is one of SPEED_x defines
- def set_power_speed(self, power, speed):
- setup = self.reg_read(RF_SETUP) & 0b11010001
- self.reg_write(RF_SETUP, setup | power | speed)
-
- # length in bytes: 0, 1 or 2
- def set_crc(self, length):
- config = self.reg_read(CONFIG) & ~(CRCO | EN_CRC)
- if length == 0:
- pass
- elif length == 1:
- config |= EN_CRC
- else:
- config |= EN_CRC | CRCO
- self.reg_write(CONFIG, config)
-
- def set_channel(self, channel):
- self.reg_write(RF_CH, min(channel, 125))
-
- # address should be a bytes object 5 bytes long
- def open_tx_pipe(self, address):
- assert len(address) == 5
- self.reg_write_bytes(RX_ADDR_P0, address)
- self.reg_write_bytes(TX_ADDR, address)
- self.reg_write(RX_PW_P0, self.payload_size)
-
- # address should be a bytes object 5 bytes long
- # pipe 0 and 1 have 5 byte address
- # pipes 2-5 use same 4 most-significant bytes as pipe 1, plus 1 extra byte
- def open_rx_pipe(self, pipe_id, address):
- assert len(address) == 5
- assert 0 <= pipe_id <= 5
- if pipe_id == 0:
- self.pipe0_read_addr = address
- if pipe_id < 2:
- self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address)
- else:
- self.reg_write(RX_ADDR_P0 + pipe_id, address[0])
- self.reg_write(RX_PW_P0 + pipe_id, self.payload_size)
- self.reg_write(EN_RXADDR, self.reg_read(EN_RXADDR) | (1 << pipe_id))
-
- def start_listening(self):
- self.reg_write(CONFIG, self.reg_read(CONFIG) | PWR_UP | PRIM_RX)
- self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
-
- if self.pipe0_read_addr is not None:
- self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr)
-
- self.flush_rx()
- self.flush_tx()
- self.ce(1)
- utime.sleep_us(130)
-
- def stop_listening(self):
- self.ce(0)
- self.flush_tx()
- self.flush_rx()
-
- # returns True if any data available to recv
- def any(self):
- return not bool(self.reg_read(FIFO_STATUS) & RX_EMPTY)
-
- def recv(self):
- # get the data
- self.cs(0)
- self.spi.readinto(self.buf, R_RX_PAYLOAD)
- buf = self.spi.read(self.payload_size)
- self.cs(1)
- # clear RX ready flag
- self.reg_write(STATUS, RX_DR)
-
- return buf
-
- # blocking wait for tx complete
- def send(self, buf, timeout=500):
- self.send_start(buf)
- start = utime.ticks_ms()
- result = None
- while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
- result = self.send_done() # 1 == success, 2 == fail
- if result == 2:
- raise OSError("send failed")
-
- # non-blocking tx
- def send_start(self, buf):
- # power up
- self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
- utime.sleep_us(150)
- # send the data
- self.cs(0)
- self.spi.readinto(self.buf, W_TX_PAYLOAD)
- self.spi.write(buf)
- if len(buf) < self.payload_size:
- self.spi.write(b"\x00" * (self.payload_size - len(buf))) # pad out data
- self.cs(1)
-
- # enable the chip so it can send the data
- self.ce(1)
- utime.sleep_us(15) # needs to be >10us
- self.ce(0)
-
- # returns None if send still in progress, 1 for success, 2 for fail
- def send_done(self):
- if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)):
- return None # tx not finished
-
- # either finished or failed: get and clear status flags, power down
- status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
- self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP)
- return 1 if status & TX_DS else 2
diff --git a/drivers/nrf24l01/nrf24l01test.py b/drivers/nrf24l01/nrf24l01test.py
deleted file mode 100644
index 56bdb6e26eb9c..0000000000000
--- a/drivers/nrf24l01/nrf24l01test.py
+++ /dev/null
@@ -1,150 +0,0 @@
-"""Test for nrf24l01 module. Portable between MicroPython targets."""
-
-import usys
-import ustruct as struct
-import utime
-from machine import Pin, SPI
-from nrf24l01 import NRF24L01
-from micropython import const
-
-# Slave pause between receiving data and checking for further packets.
-_RX_POLL_DELAY = const(15)
-# Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before
-# transmitting to allow the (remote) master time to get into receive mode. The
-# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266.
-_SLAVE_SEND_DELAY = const(10)
-
-if usys.platform == "pyboard":
- cfg = {"spi": 2, "miso": "Y7", "mosi": "Y8", "sck": "Y6", "csn": "Y5", "ce": "Y4"}
-elif usys.platform == "esp8266": # Hardware SPI
- cfg = {"spi": 1, "miso": 12, "mosi": 13, "sck": 14, "csn": 4, "ce": 5}
-elif usys.platform == "esp32": # Software SPI
- cfg = {"spi": -1, "miso": 32, "mosi": 33, "sck": 25, "csn": 26, "ce": 27}
-else:
- raise ValueError("Unsupported platform {}".format(usys.platform))
-
-# Addresses are in little-endian format. They correspond to big-endian
-# 0xf0f0f0f0e1, 0xf0f0f0f0d2
-pipes = (b"\xe1\xf0\xf0\xf0\xf0", b"\xd2\xf0\xf0\xf0\xf0")
-
-
-def master():
- csn = Pin(cfg["csn"], mode=Pin.OUT, value=1)
- ce = Pin(cfg["ce"], mode=Pin.OUT, value=0)
- if cfg["spi"] == -1:
- spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
- nrf = NRF24L01(spi, csn, ce, payload_size=8)
- else:
- nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8)
-
- nrf.open_tx_pipe(pipes[0])
- nrf.open_rx_pipe(1, pipes[1])
- nrf.start_listening()
-
- num_needed = 16
- num_successes = 0
- num_failures = 0
- led_state = 0
-
- print("NRF24L01 master mode, sending %d packets..." % num_needed)
-
- while num_successes < num_needed and num_failures < num_needed:
- # stop listening and send packet
- nrf.stop_listening()
- millis = utime.ticks_ms()
- led_state = max(1, (led_state << 1) & 0x0F)
- print("sending:", millis, led_state)
- try:
- nrf.send(struct.pack("ii", millis, led_state))
- except OSError:
- pass
-
- # start listening again
- nrf.start_listening()
-
- # wait for response, with 250ms timeout
- start_time = utime.ticks_ms()
- timeout = False
- while not nrf.any() and not timeout:
- if utime.ticks_diff(utime.ticks_ms(), start_time) > 250:
- timeout = True
-
- if timeout:
- print("failed, response timed out")
- num_failures += 1
-
- else:
- # recv packet
- (got_millis,) = struct.unpack("i", nrf.recv())
-
- # print response and round-trip delay
- print(
- "got response:",
- got_millis,
- "(delay",
- utime.ticks_diff(utime.ticks_ms(), got_millis),
- "ms)",
- )
- num_successes += 1
-
- # delay then loop
- utime.sleep_ms(250)
-
- print("master finished sending; successes=%d, failures=%d" % (num_successes, num_failures))
-
-
-def slave():
- csn = Pin(cfg["csn"], mode=Pin.OUT, value=1)
- ce = Pin(cfg["ce"], mode=Pin.OUT, value=0)
- if cfg["spi"] == -1:
- spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
- nrf = NRF24L01(spi, csn, ce, payload_size=8)
- else:
- nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8)
-
- nrf.open_tx_pipe(pipes[1])
- nrf.open_rx_pipe(1, pipes[0])
- nrf.start_listening()
-
- print("NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)")
-
- while True:
- if nrf.any():
- while nrf.any():
- buf = nrf.recv()
- millis, led_state = struct.unpack("ii", buf)
- print("received:", millis, led_state)
- for led in leds:
- if led_state & 1:
- led.on()
- else:
- led.off()
- led_state >>= 1
- utime.sleep_ms(_RX_POLL_DELAY)
-
- # Give master time to get into receive mode.
- utime.sleep_ms(_SLAVE_SEND_DELAY)
- nrf.stop_listening()
- try:
- nrf.send(struct.pack("i", millis))
- except OSError:
- pass
- print("sent response")
- nrf.start_listening()
-
-
-try:
- import pyb
-
- leds = [pyb.LED(i + 1) for i in range(4)]
-except:
- leds = []
-
-print("NRF24L01 test module loaded")
-print("NRF24L01 pinout for test:")
-print(" CE on", cfg["ce"])
-print(" CSN on", cfg["csn"])
-print(" SCK on", cfg["sck"])
-print(" MISO on", cfg["miso"])
-print(" MOSI on", cfg["mosi"])
-print("run nrf24l01test.slave() on slave, then nrf24l01test.master() on master")
diff --git a/drivers/onewire/ds18x20.py b/drivers/onewire/ds18x20.py
deleted file mode 100644
index ad2d9f52cdd00..0000000000000
--- a/drivers/onewire/ds18x20.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# DS18x20 temperature sensor driver for MicroPython.
-# MIT license; Copyright (c) 2016 Damien P. George
-
-from micropython import const
-
-_CONVERT = const(0x44)
-_RD_SCRATCH = const(0xBE)
-_WR_SCRATCH = const(0x4E)
-
-
-class DS18X20:
- def __init__(self, onewire):
- self.ow = onewire
- self.buf = bytearray(9)
-
- def scan(self):
- return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)]
-
- def convert_temp(self):
- self.ow.reset(True)
- self.ow.writebyte(self.ow.SKIP_ROM)
- self.ow.writebyte(_CONVERT)
-
- def read_scratch(self, rom):
- self.ow.reset(True)
- self.ow.select_rom(rom)
- self.ow.writebyte(_RD_SCRATCH)
- self.ow.readinto(self.buf)
- if self.ow.crc8(self.buf):
- raise Exception("CRC error")
- return self.buf
-
- def write_scratch(self, rom, buf):
- self.ow.reset(True)
- self.ow.select_rom(rom)
- self.ow.writebyte(_WR_SCRATCH)
- self.ow.write(buf)
-
- def read_temp(self, rom):
- buf = self.read_scratch(rom)
- if rom[0] == 0x10:
- if buf[1]:
- t = buf[0] >> 1 | 0x80
- t = -((~t + 1) & 0xFF)
- else:
- t = buf[0] >> 1
- return t - 0.25 + (buf[7] - buf[6]) / buf[7]
- else:
- t = buf[1] << 8 | buf[0]
- if t & 0x8000: # sign bit set
- t = -((t ^ 0xFFFF) + 1)
- return t / 16
diff --git a/drivers/onewire/onewire.py b/drivers/onewire/onewire.py
deleted file mode 100644
index 4c6da741c74ce..0000000000000
--- a/drivers/onewire/onewire.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# 1-Wire driver for MicroPython
-# MIT license; Copyright (c) 2016 Damien P. George
-
-import _onewire as _ow
-
-
-class OneWireError(Exception):
- pass
-
-
-class OneWire:
- SEARCH_ROM = 0xF0
- MATCH_ROM = 0x55
- SKIP_ROM = 0xCC
-
- def __init__(self, pin):
- self.pin = pin
- self.pin.init(pin.OPEN_DRAIN, pin.PULL_UP)
-
- def reset(self, required=False):
- reset = _ow.reset(self.pin)
- if required and not reset:
- raise OneWireError
- return reset
-
- def readbit(self):
- return _ow.readbit(self.pin)
-
- def readbyte(self):
- return _ow.readbyte(self.pin)
-
- def readinto(self, buf):
- for i in range(len(buf)):
- buf[i] = _ow.readbyte(self.pin)
-
- def writebit(self, value):
- return _ow.writebit(self.pin, value)
-
- def writebyte(self, value):
- return _ow.writebyte(self.pin, value)
-
- def write(self, buf):
- for b in buf:
- _ow.writebyte(self.pin, b)
-
- def select_rom(self, rom):
- self.reset()
- self.writebyte(self.MATCH_ROM)
- self.write(rom)
-
- def scan(self):
- devices = []
- diff = 65
- rom = False
- for i in range(0xFF):
- rom, diff = self._search_rom(rom, diff)
- if rom:
- devices += [rom]
- if diff == 0:
- break
- return devices
-
- def _search_rom(self, l_rom, diff):
- if not self.reset():
- return None, 0
- self.writebyte(self.SEARCH_ROM)
- if not l_rom:
- l_rom = bytearray(8)
- rom = bytearray(8)
- next_diff = 0
- i = 64
- for byte in range(8):
- r_b = 0
- for bit in range(8):
- b = self.readbit()
- if self.readbit():
- if b: # there are no devices or there is an error on the bus
- return None, 0
- else:
- if not b: # collision, two devices with different bit meaning
- if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i):
- b = 1
- next_diff = i
- self.writebit(b)
- if b:
- r_b |= 1 << bit
- i -= 1
- rom[byte] = r_b
- return rom, next_diff
-
- def crc8(self, data):
- return _ow.crc8(data)
diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py
deleted file mode 100644
index f4520acbb5379..0000000000000
--- a/drivers/sdcard/sdcard.py
+++ /dev/null
@@ -1,298 +0,0 @@
-"""
-MicroPython driver for SD cards using SPI bus.
-
-Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
-methods so the device can be mounted as a filesystem.
-
-Example usage on pyboard:
-
- import pyb, sdcard, os
- sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
- pyb.mount(sd, '/sd2')
- os.listdir('/')
-
-Example usage on ESP8266:
-
- import machine, sdcard, os
- sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15))
- os.mount(sd, '/sd')
- os.listdir('/')
-
-"""
-
-from micropython import const
-import time
-
-
-_CMD_TIMEOUT = const(100)
-
-_R1_IDLE_STATE = const(1 << 0)
-# R1_ERASE_RESET = const(1 << 1)
-_R1_ILLEGAL_COMMAND = const(1 << 2)
-# R1_COM_CRC_ERROR = const(1 << 3)
-# R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
-# R1_ADDRESS_ERROR = const(1 << 5)
-# R1_PARAMETER_ERROR = const(1 << 6)
-_TOKEN_CMD25 = const(0xFC)
-_TOKEN_STOP_TRAN = const(0xFD)
-_TOKEN_DATA = const(0xFE)
-
-
-class SDCard:
- def __init__(self, spi, cs, baudrate=1320000):
- self.spi = spi
- self.cs = cs
-
- self.cmdbuf = bytearray(6)
- self.dummybuf = bytearray(512)
- self.tokenbuf = bytearray(1)
- for i in range(512):
- self.dummybuf[i] = 0xFF
- self.dummybuf_memoryview = memoryview(self.dummybuf)
-
- # initialise the card
- self.init_card(baudrate)
-
- def init_spi(self, baudrate):
- try:
- master = self.spi.MASTER
- except AttributeError:
- # on ESP8266
- self.spi.init(baudrate=baudrate, phase=0, polarity=0)
- else:
- # on pyboard
- self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
-
- def init_card(self, baudrate):
-
- # init CS pin
- self.cs.init(self.cs.OUT, value=1)
-
- # init SPI bus; use low data rate for initialisation
- self.init_spi(100000)
-
- # clock card at least 100 cycles with cs high
- for i in range(16):
- self.spi.write(b"\xff")
-
- # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
- for _ in range(5):
- if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
- break
- else:
- raise OSError("no SD card")
-
- # CMD8: determine card version
- r = self.cmd(8, 0x01AA, 0x87, 4)
- if r == _R1_IDLE_STATE:
- self.init_card_v2()
- elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
- self.init_card_v1()
- else:
- raise OSError("couldn't determine SD card version")
-
- # get the number of sectors
- # CMD9: response R2 (R1 byte + 16-byte block read)
- if self.cmd(9, 0, 0, 0, False) != 0:
- raise OSError("no response from SD card")
- csd = bytearray(16)
- self.readinto(csd)
- if csd[0] & 0xC0 == 0x40: # CSD version 2.0
- self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
- elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
- c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6
- c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
- read_bl_len = csd[5] & 0b1111
- capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
- self.sectors = capacity // 512
- else:
- raise OSError("SD card CSD format not supported")
- # print('sectors', self.sectors)
-
- # CMD16: set block length to 512 bytes
- if self.cmd(16, 512, 0) != 0:
- raise OSError("can't set 512 block size")
-
- # set to high data rate now that it's initialised
- self.init_spi(baudrate)
-
- def init_card_v1(self):
- for i in range(_CMD_TIMEOUT):
- self.cmd(55, 0, 0)
- if self.cmd(41, 0, 0) == 0:
- # SDSC card, uses byte addressing in read/write/erase commands
- self.cdv = 512
- # print("[SDCard] v1 card")
- return
- raise OSError("timeout waiting for v1 card")
-
- def init_card_v2(self):
- for i in range(_CMD_TIMEOUT):
- time.sleep_ms(50)
- self.cmd(58, 0, 0, 4)
- self.cmd(55, 0, 0)
- if self.cmd(41, 0x40000000, 0) == 0:
- self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
- ocr = self.tokenbuf[0] # get first byte of response, which is OCR
- if not ocr & 0x40:
- # SDSC card, uses byte addressing in read/write/erase commands
- self.cdv = 512
- else:
- # SDHC/SDXC card, uses block addressing in read/write/erase commands
- self.cdv = 1
- # print("[SDCard] v2 card")
- return
- raise OSError("timeout waiting for v2 card")
-
- def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
- self.cs(0)
-
- # create and send the command
- buf = self.cmdbuf
- buf[0] = 0x40 | cmd
- buf[1] = arg >> 24
- buf[2] = arg >> 16
- buf[3] = arg >> 8
- buf[4] = arg
- buf[5] = crc
- self.spi.write(buf)
-
- if skip1:
- self.spi.readinto(self.tokenbuf, 0xFF)
-
- # wait for the response (response[7] == 0)
- for i in range(_CMD_TIMEOUT):
- self.spi.readinto(self.tokenbuf, 0xFF)
- response = self.tokenbuf[0]
- if not (response & 0x80):
- # this could be a big-endian integer that we are getting here
- # if final<0 then store the first byte to tokenbuf and discard the rest
- if final < 0:
- self.spi.readinto(self.tokenbuf, 0xFF)
- final = -1 - final
- for j in range(final):
- self.spi.write(b"\xff")
- if release:
- self.cs(1)
- self.spi.write(b"\xff")
- return response
-
- # timeout
- self.cs(1)
- self.spi.write(b"\xff")
- return -1
-
- def readinto(self, buf):
- self.cs(0)
-
- # read until start byte (0xff)
- for i in range(_CMD_TIMEOUT):
- self.spi.readinto(self.tokenbuf, 0xFF)
- if self.tokenbuf[0] == _TOKEN_DATA:
- break
- time.sleep_ms(1)
- else:
- self.cs(1)
- raise OSError("timeout waiting for response")
-
- # read data
- mv = self.dummybuf_memoryview
- if len(buf) != len(mv):
- mv = mv[: len(buf)]
- self.spi.write_readinto(mv, buf)
-
- # read checksum
- self.spi.write(b"\xff")
- self.spi.write(b"\xff")
-
- self.cs(1)
- self.spi.write(b"\xff")
-
- def write(self, token, buf):
- self.cs(0)
-
- # send: start of block, data, checksum
- self.spi.read(1, token)
- self.spi.write(buf)
- self.spi.write(b"\xff")
- self.spi.write(b"\xff")
-
- # check the response
- if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
- self.cs(1)
- self.spi.write(b"\xff")
- return
-
- # wait for write to finish
- while self.spi.read(1, 0xFF)[0] == 0:
- pass
-
- self.cs(1)
- self.spi.write(b"\xff")
-
- def write_token(self, token):
- self.cs(0)
- self.spi.read(1, token)
- self.spi.write(b"\xff")
- # wait for write to finish
- while self.spi.read(1, 0xFF)[0] == 0x00:
- pass
-
- self.cs(1)
- self.spi.write(b"\xff")
-
- def readblocks(self, block_num, buf):
- nblocks = len(buf) // 512
- assert nblocks and not len(buf) % 512, "Buffer length is invalid"
- if nblocks == 1:
- # CMD17: set read address for single block
- if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
- # release the card
- self.cs(1)
- raise OSError(5) # EIO
- # receive the data and release card
- self.readinto(buf)
- else:
- # CMD18: set read address for multiple blocks
- if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
- # release the card
- self.cs(1)
- raise OSError(5) # EIO
- offset = 0
- mv = memoryview(buf)
- while nblocks:
- # receive the data and release card
- self.readinto(mv[offset : offset + 512])
- offset += 512
- nblocks -= 1
- if self.cmd(12, 0, 0xFF, skip1=True):
- raise OSError(5) # EIO
-
- def writeblocks(self, block_num, buf):
- nblocks, err = divmod(len(buf), 512)
- assert nblocks and not err, "Buffer length is invalid"
- if nblocks == 1:
- # CMD24: set write address for single block
- if self.cmd(24, block_num * self.cdv, 0) != 0:
- raise OSError(5) # EIO
-
- # send the data
- self.write(_TOKEN_DATA, buf)
- else:
- # CMD25: set write address for first block
- if self.cmd(25, block_num * self.cdv, 0) != 0:
- raise OSError(5) # EIO
- # send the data
- offset = 0
- mv = memoryview(buf)
- while nblocks:
- self.write(_TOKEN_CMD25, mv[offset : offset + 512])
- offset += 512
- nblocks -= 1
- self.write_token(_TOKEN_STOP_TRAN)
-
- def ioctl(self, op, arg):
- if op == 4: # get number of blocks
- return self.sectors
- if op == 5: # get block size in bytes
- return 512
diff --git a/drivers/sdcard/sdtest.py b/drivers/sdcard/sdtest.py
deleted file mode 100644
index 018ef7c64aa19..0000000000000
--- a/drivers/sdcard/sdtest.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Test for sdcard block protocol
-# Peter hinch 30th Jan 2016
-import os, sdcard, machine
-
-
-def sdtest():
- spi = machine.SPI(1)
- spi.init() # Ensure right baudrate
- sd = sdcard.SDCard(spi, machine.Pin.board.X21) # Compatible with PCB
- vfs = os.VfsFat(sd)
- os.mount(vfs, "/fc")
- print("Filesystem check")
- print(os.listdir("/fc"))
-
- line = "abcdefghijklmnopqrstuvwxyz\n"
- lines = line * 200 # 5400 chars
- short = "1234567890\n"
-
- fn = "/fc/rats.txt"
- print()
- print("Multiple block read/write")
- with open(fn, "w") as f:
- n = f.write(lines)
- print(n, "bytes written")
- n = f.write(short)
- print(n, "bytes written")
- n = f.write(lines)
- print(n, "bytes written")
-
- with open(fn, "r") as f:
- result1 = f.read()
- print(len(result1), "bytes read")
-
- fn = "/fc/rats1.txt"
- print()
- print("Single block read/write")
- with open(fn, "w") as f:
- n = f.write(short) # one block
- print(n, "bytes written")
-
- with open(fn, "r") as f:
- result2 = f.read()
- print(len(result2), "bytes read")
-
- os.umount("/fc")
-
- print()
- print("Verifying data read back")
- success = True
- if result1 == "".join((lines, short, lines)):
- print("Large file Pass")
- else:
- print("Large file Fail")
- success = False
- if result2 == short:
- print("Small file Pass")
- else:
- print("Small file Fail")
- success = False
- print()
- print("Tests", "passed" if success else "failed")
diff --git a/drivers/wiznet5k/README.md b/drivers/wiznet5k/README.md
deleted file mode 100644
index 88f25a2b8dbcb..0000000000000
--- a/drivers/wiznet5k/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-This is the driver for the WIZnet5x00 series of Ethernet controllers.
-
-Adapted for MicroPython.
-
-Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary
-Taken on: 30 August 2014
diff --git a/drivers/wiznet5k/ethernet/socket.c b/drivers/wiznet5k/ethernet/socket.c
deleted file mode 100644
index 3ffda3a722dfa..0000000000000
--- a/drivers/wiznet5k/ethernet/socket.c
+++ /dev/null
@@ -1,725 +0,0 @@
-//*****************************************************************************
-//
-//! \file socket.c
-//! \brief SOCKET APIs Implements file.
-//! \details SOCKET APIs like as Berkeley Socket APIs.
-//! \version 1.0.3
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.3. Refer to M20140501
-//! 1. Implicit type casting -> Explicit type casting.
-//! 2. replace 0x01 with PACK_REMAINED in recvfrom()
-//! 3. Validation a destination ip in connect() & sendto():
-//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address.
-//! Copy 4 byte addr value into temporary uint32 variable and then compares it.
-//! <2013/12/20> V1.0.2 Refer to M20131220
-//! Remove Warning.
-//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
-//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT)
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************
-
-#include
-
-#include "py/mpthread.h"
-#include "socket.h"
-
-#define SOCK_ANY_PORT_NUM 0xC000;
-
-static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
-static uint16_t sock_io_mode = 0;
-static uint16_t sock_is_sending = 0;
-static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
-static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
-
-#if _WIZCHIP_ == 5200
- static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
-#endif
-
-#define CHECK_SOCKNUM() \
- do{ \
- if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \
- }while(0); \
-
-#define CHECK_SOCKMODE(mode) \
- do{ \
- if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \
- }while(0); \
-
-#define CHECK_SOCKINIT() \
- do{ \
- if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
- }while(0); \
-
-#define CHECK_SOCKDATA() \
- do{ \
- if(len == 0) return SOCKERR_DATALEN; \
- }while(0); \
-
-void WIZCHIP_EXPORT(socket_reset)(void) {
- sock_any_port = SOCK_ANY_PORT_NUM;
- sock_io_mode = 0;
- sock_is_sending = 0;
- /*
- memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
- memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t));
- */
-
-#if _WIZCHIP_ == 5200
- memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
-#endif
-}
-
-int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
-{
- CHECK_SOCKNUM();
- switch(protocol)
- {
- case Sn_MR_TCP :
- case Sn_MR_UDP :
- case Sn_MR_MACRAW :
- break;
- #if ( _WIZCHIP_ < 5200 )
- case Sn_MR_IPRAW :
- case Sn_MR_PPPoE :
- break;
- #endif
- default :
- return SOCKERR_SOCKMODE;
- }
- if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
-#if _WIZCHIP_ == 5200
- if(flag & 0x10) return SOCKERR_SOCKFLAG;
-#endif
-
- if(flag != 0)
- {
- switch(protocol)
- {
- case Sn_MR_TCP:
- if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
- break;
- case Sn_MR_UDP:
- if(flag & SF_IGMP_VER2)
- {
- if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
- }
- #if _WIZCHIP_ == 5500
- if(flag & SF_UNI_BLOCK)
- {
- if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
- }
- #endif
- break;
- default:
- break;
- }
- }
- WIZCHIP_EXPORT(close)(sn);
- setSn_MR(sn, (protocol | (flag & 0xF0)));
- if(!port)
- {
- port = sock_any_port++;
- if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
- }
- setSn_PORT(sn,port);
- setSn_CR(sn,Sn_CR_OPEN);
- while(getSn_CR(sn));
- sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
- sock_is_sending &= ~(1< freesize) len = freesize; // check size not to exceed MAX size.
- while(1)
- {
- freesize = getSn_TX_FSR(sn);
- tmp = getSn_SR(sn);
- if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
- {
- WIZCHIP_EXPORT(close)(sn);
- return SOCKERR_SOCKSTATUS;
- }
- if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY;
- if(len <= freesize) break;
- MICROPY_THREAD_YIELD();
- }
- wiz_send_data(sn, buf, len);
- #if _WIZCHIP_ == 5200
- sock_next_rd[sn] = getSn_TX_RD(sn) + len;
- #endif
- setSn_CR(sn,Sn_CR_SEND);
- /* wait to process the command... */
- while(getSn_CR(sn));
- sock_is_sending |= (1 << sn);
- return len;
-}
-
-
-int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len)
-{
- uint8_t tmp = 0;
- uint16_t recvsize = 0;
- CHECK_SOCKNUM();
- CHECK_SOCKMODE(Sn_MR_TCP);
- CHECK_SOCKDATA();
-
- recvsize = getSn_RxMAX(sn);
- if(recvsize < len) len = recvsize;
- while(1)
- {
- recvsize = getSn_RX_RSR(sn);
- tmp = getSn_SR(sn);
- if (tmp != SOCK_ESTABLISHED)
- {
- if(tmp == SOCK_CLOSE_WAIT)
- {
- if(recvsize != 0) break;
- else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
- {
- // dpgeorge: Getting here seems to be an orderly shutdown of the
- // socket, and trying to get POSIX behaviour we return 0 because:
- // "If no messages are available to be received and the peer has per‐
- // formed an orderly shutdown, recv() shall return 0".
- // TODO this return value clashes with SOCK_BUSY in non-blocking mode.
- WIZCHIP_EXPORT(close)(sn);
- return 0;
- }
- }
- else
- {
- WIZCHIP_EXPORT(close)(sn);
- return SOCKERR_SOCKSTATUS;
- }
- }
- if((sock_io_mode & (1< freesize) len = freesize; // check size not to exceed MAX size.
- while(1)
- {
- freesize = getSn_TX_FSR(sn);
- if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
- if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY;
- if(len <= freesize) break;
- MICROPY_THREAD_YIELD();
- };
- wiz_send_data(sn, buf, len);
-
- #if _WIZCHIP_ == 5200 // for W5200 ARP errata
- setSUBR(wizchip_getsubn());
- #endif
-
- setSn_CR(sn,Sn_CR_SEND);
- /* wait to process the command... */
- while(getSn_CR(sn));
- while(1)
- {
- tmp = getSn_IR(sn);
- if(tmp & Sn_IR_SENDOK)
- {
- setSn_IR(sn, Sn_IR_SENDOK);
- break;
- }
- //M:20131104
- //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
- else if(tmp & Sn_IR_TIMEOUT)
- {
- setSn_IR(sn, Sn_IR_TIMEOUT);
- #if _WIZCHIP_ == 5200 // for W5200 ARP errata
- setSUBR((uint8_t*)"\x00\x00\x00\x00");
- #endif
- return SOCKERR_TIMEOUT;
- }
- ////////////
- MICROPY_THREAD_YIELD();
- }
- #if _WIZCHIP_ == 5200 // for W5200 ARP errata
- setSUBR((uint8_t*)"\x00\x00\x00\x00");
- #endif
- return len;
-}
-
-
-
-int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
-{
- uint8_t mr;
- uint8_t head[8];
- uint16_t pack_len=0;
-
- CHECK_SOCKNUM();
- //CHECK_SOCKMODE(Sn_MR_UDP);
- switch((mr=getSn_MR(sn)) & 0x0F)
- {
- case Sn_MR_UDP:
- case Sn_MR_MACRAW:
- break;
- #if ( _WIZCHIP_ < 5200 )
- case Sn_MR_IPRAW:
- case Sn_MR_PPPoE:
- break;
- #endif
- default:
- return SOCKERR_SOCKMODE;
- }
- CHECK_SOCKDATA();
- if(sock_remained_size[sn] == 0)
- {
- while(1)
- {
- pack_len = getSn_RX_RSR(sn);
- if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
- if( (sock_io_mode & (1< 1514)
- {
- WIZCHIP_EXPORT(close)(sn);
- return SOCKFATAL_PACKLEN;
- }
- sock_pack_info[sn] = PACK_FIRST;
- }
- if(len < sock_remained_size[sn]) pack_len = len;
- else pack_len = sock_remained_size[sn];
- wiz_recv_data(sn,buf,pack_len);
- break;
- #if ( _WIZCHIP_ < 5200 )
- case Sn_MR_IPRAW:
- if(sock_remained_size[sn] == 0)
- {
- wiz_recv_data(sn, head, 6);
- setSn_CR(sn,Sn_CR_RECV);
- while(getSn_CR(sn));
- addr[0] = head[0];
- addr[1] = head[1];
- addr[2] = head[2];
- addr[3] = head[3];
- sock_remained_size[sn] = head[4];
- sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
- sock_pack_info[sn] = PACK_FIRST;
- }
- //
- // Need to packet length check
- //
- if(len < sock_remained_size[sn]) pack_len = len;
- else pack_len = sock_remained_size[sn];
- wiz_recv_data(sn, buf, pack_len); // data copy.
- break;
- #endif
- default:
- wiz_recv_ignore(sn, pack_len); // data copy.
- sock_remained_size[sn] = pack_len;
- break;
- }
- setSn_CR(sn,Sn_CR_RECV);
- /* wait to process the command... */
- while(getSn_CR(sn)) ;
- sock_remained_size[sn] -= pack_len;
- //M20140501 : replace 0x01 with PACK_REMAINED
- //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
- if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED;
- //
- return pack_len;
-}
-
-
-int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg)
-{
- uint8_t tmp = 0;
- CHECK_SOCKNUM();
- switch(cstype)
- {
- case CS_SET_IOMODE:
- tmp = *((uint8_t*)arg);
- if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1< explict type casting
- //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
- *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
- //
- break;
- case CS_GET_MAXTXBUF:
- *((uint16_t*)arg) = getSn_TxMAX(sn);
- break;
- case CS_GET_MAXRXBUF:
- *((uint16_t*)arg) = getSn_RxMAX(sn);
- break;
- case CS_CLR_INTERRUPT:
- if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
- setSn_IR(sn,*(uint8_t*)arg);
- break;
- case CS_GET_INTERRUPT:
- *((uint8_t*)arg) = getSn_IR(sn);
- break;
- case CS_SET_INTMASK:
- if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
- setSn_IMR(sn,*(uint8_t*)arg);
- break;
- case CS_GET_INTMASK:
- *((uint8_t*)arg) = getSn_IMR(sn);
- default:
- return SOCKERR_ARG;
- }
- return SOCK_OK;
-}
-
-int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
-{
- // M20131220 : Remove warning
- //uint8_t tmp;
- CHECK_SOCKNUM();
- switch(sotype)
- {
- case SO_TTL:
- setSn_TTL(sn,*(uint8_t*)arg);
- break;
- case SO_TOS:
- setSn_TOS(sn,*(uint8_t*)arg);
- break;
- case SO_MSS:
- setSn_MSSR(sn,*(uint16_t*)arg);
- break;
- case SO_DESTIP:
- setSn_DIPR(sn, (uint8_t*)arg);
- break;
- case SO_DESTPORT:
- setSn_DPORT(sn, *(uint16_t*)arg);
- break;
-#if _WIZCHIP_ != 5100
- case SO_KEEPALIVESEND:
- CHECK_SOCKMODE(Sn_MR_TCP);
- #if _WIZCHIP_ > 5200
- if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
- #endif
- setSn_CR(sn,Sn_CR_SEND_KEEP);
- while(getSn_CR(sn) != 0)
- {
- // M20131220
- //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
- if (getSn_IR(sn) & Sn_IR_TIMEOUT)
- {
- setSn_IR(sn, Sn_IR_TIMEOUT);
- return SOCKERR_TIMEOUT;
- }
- }
- break;
- #if _WIZCHIP_ > 5200
- case SO_KEEPALIVEAUTO:
- CHECK_SOCKMODE(Sn_MR_TCP);
- setSn_KPALVTR(sn,*(uint8_t*)arg);
- break;
- #endif
-#endif
- default:
- return SOCKERR_ARG;
- }
- return SOCK_OK;
-}
-
-int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
-{
- CHECK_SOCKNUM();
- switch(sotype)
- {
- case SO_FLAG:
- *(uint8_t*)arg = getSn_MR(sn) & 0xF0;
- break;
- case SO_TTL:
- *(uint8_t*) arg = getSn_TTL(sn);
- break;
- case SO_TOS:
- *(uint8_t*) arg = getSn_TOS(sn);
- break;
- case SO_MSS:
- *(uint8_t*) arg = getSn_MSSR(sn);
- case SO_DESTIP:
- getSn_DIPR(sn, (uint8_t*)arg);
- break;
- case SO_DESTPORT:
- *(uint16_t*) arg = getSn_DPORT(sn);
- break;
- #if _WIZCHIP_ > 5200
- case SO_KEEPALIVEAUTO:
- CHECK_SOCKMODE(Sn_MR_TCP);
- *(uint16_t*) arg = getSn_KPALVTR(sn);
- break;
- #endif
- case SO_SENDBUF:
- *(uint16_t*) arg = getSn_TX_FSR(sn);
- case SO_RECVBUF:
- *(uint16_t*) arg = getSn_RX_RSR(sn);
- case SO_STATUS:
- *(uint8_t*) arg = getSn_SR(sn);
- break;
- case SO_REMAINSIZE:
- if(getSn_MR(sn) == Sn_MR_TCP)
- *(uint16_t*)arg = getSn_RX_RSR(sn);
- else
- *(uint16_t*)arg = sock_remained_size[sn];
- break;
- case SO_PACKINFO:
- CHECK_SOCKMODE(Sn_MR_TCP);
- *(uint8_t*)arg = sock_pack_info[sn];
- break;
- default:
- return SOCKERR_SOCKOPT;
- }
- return SOCK_OK;
-}
diff --git a/drivers/wiznet5k/ethernet/socket.h b/drivers/wiznet5k/ethernet/socket.h
deleted file mode 100644
index 2f03a34eba015..0000000000000
--- a/drivers/wiznet5k/ethernet/socket.h
+++ /dev/null
@@ -1,472 +0,0 @@
-//*****************************************************************************
-//
-//! \file socket.h
-//! \brief SOCKET APIs Header file.
-//! \details SOCKET APIs like as berkeley socket api.
-//! \version 1.0.2
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.2. Refer to M20140501
-//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED
-//! 2. Add the comment as zero byte udp data reception in getsockopt().
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************
-/**
- * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs
- * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface.
- * But there is a little bit of difference.
- * @details
- * Comparison between WIZnet and Berkeley SOCKET APIs
- *
- *
API
WIZnet
Berkeley
- *
socket()
O
O
- *
bind()
X
O
- *
listen()
O
O
- *
connect()
O
O
- *
accept()
X
O
- *
recv()
O
O
- *
send()
O
O
- *
recvfrom()
O
O
- *
sendto()
O
O
- *
closesocket()
O close() & disconnect()
O
- *
- * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but,
- * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number,
- * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n
- * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port.
- * When the listen SOCKET accepts a connection request from a client, it keeps listening.
- * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n
- * Following figure shows network flow diagram by Berkeley SOCKET API.
- * @image html Berkeley_SOCKET.jpg ""
- * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n
- * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client,
- * it is changed in order to communicate with the client.
- * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n
- * If there're many listen SOCKET with same listen port number and a client requests a connection,
- * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n
- * Following figure shows network flow diagram by WIZnet SOCKET API.
- * @image html WIZnet_SOCKET.jpg ""
- */
-#ifndef _WIZCHIP_SOCKET_H_
-#define _WIZCHIP_SOCKET_H_
-
-// use this macro for exported names to avoid name clashes
-#define WIZCHIP_EXPORT(name) wizchip_ ## name
-
-#include "wizchip_conf.h"
-
-#define SOCKET uint8_t ///< SOCKET type define for legacy driver
-
-#define SOCK_OK 1 ///< Result is OK about socket process.
-#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode.
-#define SOCK_FATAL -1000 ///< Result is fatal error about socket process.
-
-#define SOCK_ERROR 0
-#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number
-#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option
-#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized
-#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed.
-#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation.
-#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag
-#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation.
-#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument.
-#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero
-#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address
-#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred
-#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size.
-#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication.
-
-#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error.
-
-/*
- * SOCKET FLAG
- */
-#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet
-#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2.
-#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack.
-#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode.
-
-#if _WIZCHIP_ == 5500
- #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500
- #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500
- #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500
- #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500
-#endif
-
-#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket().
-
-/*
- * UDP & MACRAW Packet Infomation
- */
-#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet.
-#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received.
-#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet.
-
-// resets all global state associated with the socket interface
-void WIZCHIP_EXPORT(socket_reset)(void);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Open a socket.
- * @details Initializes the socket with 'sn' passed as parameter and open.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param protocol Protocol type to operate such as TCP, UDP and MACRAW.
- * @param port Port number to be bined.
- * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n
- * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK.
- * @sa Sn_MR
- *
- * @return @b Success : The socket number @b 'sn' passed as parameter\n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
- * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n
- * @ref SOCKERR_SOCKFLAG - Invaild socket flag.
- */
-int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Close a socket.
- * @details It closes the socket with @b'sn' passed as parameter.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- *
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number
- */
-int8_t WIZCHIP_EXPORT(close)(uint8_t sn);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Listen to a connection request from a client.
- * @details It is listening to a connection request from a client.
- * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n
- * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly.
- */
-int8_t WIZCHIP_EXPORT(listen)(uint8_t sn);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Try to connect a server.
- * @details It requests connection to the server with destination IP address and port number passed as parameter.\n
- * @note It is valid only in TCP client mode.
- * In block io mode, it does not return until connection is completed.
- * In Non-block io mode, it return @ref SOCK_BUSY immediately.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
- * @param port Destination port number.
- *
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
- * @ref SOCKERR_SOCKMODE - Invalid socket mode\n
- * @ref SOCKERR_SOCKINIT - Socket is not initialized\n
- * @ref SOCKERR_IPINVALID - Wrong server IP address\n
- * @ref SOCKERR_PORTZERO - Server port zero\n
- * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n
- * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n
- */
-int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Try to disconnect a connection socket.
- * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client.
- * @note It is valid only in TCP server or client mode. \n
- * In block io mode, it does not return until disconnection is completed. \n
- * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n
-
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_TIMEOUT - Timeout occurred \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Send data to the connected peer in TCP socket.
- * @details It is used to send outgoing data to the connected socket.
- * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n
- * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n
- * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer containing data to be sent.
- * @param len The byte length of data in buf.
- * @return @b Success : The sent data size \n
- * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
- * @ref SOCKERR_TIMEOUT - Timeout occurred \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Receive data from the connected peer.
- * @details It is used to read incoming data from the connected socket.\n
- * It waits for data as much as the application wants to receive.
- * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n
- * In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer. \n
- * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. \n
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer to read incoming data.
- * @param len The max data length of data in buf.
- * @return @b Success : The real received data size \n
- * @b Fail :\n
- * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Sends datagram to the peer with destination IP address and port number passed as parameter.
- * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n
- * Even if the connectionless socket has been previously connected to a specific address,
- * the address and port number parameters override the destination address for that particular datagram only.
- * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than len.
- * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer to send outgoing data.
- * @param len The byte length of data in buf.
- * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
- * @param port Destination port number.
- *
- * @return @b Success : The sent data size \n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
- * @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCKERR_IPINVALID - Wrong server IP address\n
- * @ref SOCKERR_PORTZERO - Server port zero\n
- * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n
- * @ref SOCKERR_TIMEOUT - Timeout occurred \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Receive datagram of UDP or MACRAW
- * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n
- * This function is used to receive UDP and MAC_RAW mode, and handle the header as well.
- * This function can divide to received the packet data.
- * On the MACRAW SOCKET, the addr and port parameters are ignored.
- * @note In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer
- * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer to read incoming data.
- * @param len The max data length of data in buf.
- * When the received packet size <= len, receives data as packet sized.
- * When others, receives data as len.
- * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
- * It is valid only when the first call recvfrom for receiving the packet.
- * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
- * @param port Pointer variable of destination port number.
- * It is valid only when the first call recvform for receiving the packet.
-* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
- *
- * @return @b Success : This function return real received data size for success.\n
- * @b Fail : @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKBUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
-
-
-/////////////////////////////
-// SOCKET CONTROL & OPTION //
-/////////////////////////////
-#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt().
-#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt().
-
-/**
- * @defgroup DATA_TYPE DATA TYPE
- */
-
-/**
- * @ingroup DATA_TYPE
- * @brief The kind of Socket Interrupt.
- * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR()
- */
-typedef enum
-{
- SIK_CONNECTED = (1 << 0), ///< connected
- SIK_DISCONNECTED = (1 << 1), ///< disconnected
- SIK_RECEIVED = (1 << 2), ///< data received
- SIK_TIMEOUT = (1 << 3), ///< timeout occurred
- SIK_SENT = (1 << 4), ///< send ok
- SIK_ALL = 0x1F, ///< all interrupt
-}sockint_kind;
-
-/**
- * @ingroup DATA_TYPE
- * @brief The type of @ref ctlsocket().
- */
-typedef enum
-{
- CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK
- CS_GET_IOMODE, ///< get socket IO mode
- CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory
- CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory
- CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind
- CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind
- CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind
- CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind
-}ctlsock_type;
-
-
-/**
- * @ingroup DATA_TYPE
- * @brief The type of socket option in @ref setsockopt() or @ref getsockopt()
- */
-typedef enum
-{
- SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to flag in @ref socket().
- SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() )
- SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() )
- SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() )
- SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() )
- SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() )
-#if _WIZCHIP_ != 5100
- SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode
- #if _WIZCHIP_ > 5200
- SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode
- #endif
-#endif
- SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR()
- SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR()
- SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR()
- SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode.
- SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode.
-}sockopt_type;
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Control socket.
- * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information.
- * Refer to @ref ctlsock_type.
- * @param sn socket number
- * @param cstype type of control socket. refer to @ref ctlsock_type.
- * @param arg Data type and value is determined according to @ref ctlsock_type. \n
- *
- * @return @b Success @ref SOCK_OK \n
- * @b fail @ref SOCKERR_ARG - Invalid argument\n
- */
-int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief set socket options
- * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type.
- *
- * @param sn socket number
- * @param sotype socket option type. refer to @ref sockopt_type
- * @param arg Data type and value is determined according to sotype. \n
- *
- *
@b sotype
@b data type
@b value
- *
@ref SO_TTL
uint8_t
0 ~ 255
- *
@ref SO_TOS
uint8_t
0 ~ 255
- *
@ref SO_MSS
uint16_t
0 ~ 65535
- *
@ref SO_DESTIP
uint8_t[4]
- *
@ref SO_DESTPORT
uint16_t
0 ~ 65535
- *
@ref SO_KEEPALIVESEND
null
null
- *
@ref SO_KEEPALIVEAUTO
uint8_t
0 ~ 255
- *
- * @return
- * - @b Success : @ref SOCK_OK \n
- * - @b Fail
- * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
- * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
- * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
- * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n
- */
-int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief get socket options
- * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type
- * @param sn socket number
- * @param sotype socket option type. refer to @ref sockopt_type
- * @param arg Data type and value is determined according to sotype. \n
- *
- *
@b sotype
@b data type
@b value
- *
@ref SO_FLAG
uint8_t
@ref SF_ETHER_OWN, etc...
- *
@ref SO_TOS
uint8_t
0 ~ 255
- *
@ref SO_MSS
uint16_t
0 ~ 65535
- *
@ref SO_DESTIP
uint8_t[4]
- *
@ref SO_DESTPORT
uint16_t
- *
@ref SO_KEEPALIVEAUTO
uint8_t
0 ~ 255
- *
@ref SO_SENDBUF
uint16_t
0 ~ 65535
- *
@ref SO_RECVBUF
uint16_t
0 ~ 65535
- *
@ref SO_STATUS
uint8_t
@ref SOCK_ESTABLISHED, etc..
- *
@ref SO_REMAINSIZE
uint16_t
0~ 65535
- *
@ref SO_PACKINFO
uint8_t
@ref PACK_FIRST, etc...
- *
- * @return
- * - @b Success : @ref SOCK_OK \n
- * - @b Fail
- * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
- * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
- * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
- * @note
- * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n
- * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero,
- * This means the zero byte UDP data(UDP Header only) received.
- */
-int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
-
-#endif // _WIZCHIP_SOCKET_H_
diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.c b/drivers/wiznet5k/ethernet/w5200/w5200.c
deleted file mode 100644
index a84d3c9fa7bcb..0000000000000
--- a/drivers/wiznet5k/ethernet/w5200/w5200.c
+++ /dev/null
@@ -1,215 +0,0 @@
-// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200
-
-//*****************************************************************************
-//
-//! \file w5500.c
-//! \brief W5500 HAL Interface.
-//! \version 1.0.1
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.2
-//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
-//! Fixed the problem on porting into under 32bit MCU
-//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
-//! Thank for your interesting and serious advices.
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.0.1
-//! 1. Remove warning
-//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
-//! for loop optimized(removed). refer to M20131220
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************
-
-#include "w5200.h"
-
-#if WIZCHIP_USE_MAX_BUFFER
-// This option is intended to be used when MACRAW mode is enabled, to allow
-// the single raw socket to use all the available buffer space.
-#define SMASK (16 * 1024 - 1) /* tx buffer mask */
-#define RMASK (16 * 1024 - 1) /* rx buffer mask */
-#define SSIZE (16 * 1024) /* max tx buffer size */
-#define RSIZE (16 * 1024) /* max rx buffer size */
-#else
-#define SMASK (0x7ff) /* tx buffer mask */
-#define RMASK (0x7ff) /* rx buffer mask */
-#define SSIZE (2048) /* max tx buffer size */
-#define RSIZE (2048) /* max rx buffer size */
-#endif
-
-#define TXBUF_BASE (0x8000)
-#define RXBUF_BASE (0xc000)
-#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */
-#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */
-
-uint8_t WIZCHIP_READ(uint32_t AddrSel) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[4] = {
- AddrSel >> 8,
- AddrSel,
- 0x00,
- 0x01,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
- uint8_t ret;
- WIZCHIP.IF.SPI._read_bytes(&ret, 1);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-
- return ret;
-}
-
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[5] = {
- AddrSel >> 8,
- AddrSel,
- 0x80,
- 0x01,
- wb,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 5);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[4] = {
- AddrSel >> 8,
- AddrSel,
- 0x00 | ((len >> 8) & 0x7f),
- len & 0xff,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
- WIZCHIP.IF.SPI._read_bytes(pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[4] = {
- AddrSel >> 8,
- AddrSel,
- 0x80 | ((len >> 8) & 0x7f),
- len & 0xff,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
- WIZCHIP.IF.SPI._write_bytes(pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-uint16_t getSn_TX_FSR(uint8_t sn) {
- uint16_t val = 0, val1 = 0;
- do {
- val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
- if (val1 != 0) {
- val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
- }
- } while (val != val1);
- return val;
-}
-
-uint16_t getSn_RX_RSR(uint8_t sn) {
- uint16_t val = 0, val1 = 0;
- do {
- val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
- if (val1 != 0) {
- val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
- }
- } while (val != val1);
- return val;
-}
-
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
- if (len == 0) {
- return;
- }
-
- uint16_t ptr = getSn_TX_WR(sn);
- uint16_t offset = ptr & SMASK;
- uint32_t addr = offset + SBASE(sn);
-
- if (offset + len > SSIZE) {
- // implement wrap-around circular buffer
- uint16_t size = SSIZE - offset;
- WIZCHIP_WRITE_BUF(addr, wizdata, size);
- WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size);
- } else {
- WIZCHIP_WRITE_BUF(addr, wizdata, len);
- }
-
- ptr += len;
- setSn_TX_WR(sn, ptr);
-}
-
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
- if (len == 0) {
- return;
- }
-
- uint16_t ptr = getSn_RX_RD(sn);
- uint16_t offset = ptr & RMASK;
- uint16_t addr = RBASE(sn) + offset;
-
- if (offset + len > RSIZE) {
- // implement wrap-around circular buffer
- uint16_t size = RSIZE - offset;
- WIZCHIP_READ_BUF(addr, wizdata, size);
- WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size);
- } else {
- WIZCHIP_READ_BUF(addr, wizdata, len);
- }
-
- ptr += len;
- setSn_RX_RD(sn, ptr);
-}
-
-void wiz_recv_ignore(uint8_t sn, uint16_t len) {
- uint16_t ptr = getSn_RX_RD(sn);
- ptr += len;
- setSn_RX_RD(sn, ptr);
-}
diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.h b/drivers/wiznet5k/ethernet/w5200/w5200.h
deleted file mode 100644
index 63561940f8b55..0000000000000
--- a/drivers/wiznet5k/ethernet/w5200/w5200.h
+++ /dev/null
@@ -1,2092 +0,0 @@
-// dpgeorge: this file taken from w5500/w5500.h and adapted to W5200
-
-//*****************************************************************************
-//
-//! \file w5500.h
-//! \brief W5500 HAL Header File.
-//! \version 1.0.0
-//! \date 2013/10/21
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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 _W5200_H_
-#define _W5200_H_
-
-#include
-#include "../wizchip_conf.h"
-//#include "board.h"
-
-#define _W5200_IO_BASE_ 0x00000000
-
-#define WIZCHIP_CREG_ADDR(addr) (_W5200_IO_BASE_ + (addr))
-
-#define WIZCHIP_CH_BASE (0x4000)
-#define WIZCHIP_CH_SIZE (0x100)
-#define WIZCHIP_SREG_ADDR(sn, addr) (_W5200_IO_BASE_ + WIZCHIP_CH_BASE + (sn) * WIZCHIP_CH_SIZE + (addr))
-
-//////////////////////////////
-//-------------------------- defgroup ---------------------------------
-/**
- * @defgroup W5500 W5500
- *
- * @brief WHIZCHIP register defines and I/O functions of @b W5500.
- *
- * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group
- * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function
- */
-
-
-/**
- * @defgroup WIZCHIP_register WIZCHIP register
- * @ingroup W5500
- *
- * @brief WHIZCHIP register defines register group of @b W5500.
- *
- * - @ref Common_register_group : Common register group
- * - @ref Socket_register_group : \c SOCKET n register group
- */
-
-
-/**
- * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions
- * @ingroup W5500
- *
- * @brief This supports the basic I/O functions for @ref WIZCHIP_register.
- *
- * - Basic I/O function \n
- * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n
- *
- * - @ref Common_register_group access functions \n
- * -# @b Mode \n
- * getMR(), setMR()
- * -# @b Interrupt \n
- * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL()
- * -# Network Information \n
- * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
- * -# @b Retransmission \n
- * getRCR(), setRCR(), getRTR(), setRTR()
- * -# @b PPPoE \n
- * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU()
- * -# ICMP packet \n
- * getUIPR(), getUPORTR()
- * -# @b etc. \n
- * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n
- *
- * - \ref Socket_register_group access functions \n
- * -# SOCKET control \n
- * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR()
- * -# SOCKET information \n
- * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
- * getSn_MSSR(), setSn_MSSR()
- * -# SOCKET communication \n
- * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n
- * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
- * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
- * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR()
- * -# IP header field \n
- * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n
- * getSn_TTL(), setSn_TTL()
- */
-
-
-
-/**
- * @defgroup Common_register_group Common register
- * @ingroup WIZCHIP_register
- *
- * @brief Common register group\n
- * It set the basic for the networking\n
- * It set the configuration such as interrupt, network information, ICMP, etc.
- * @details
- * @sa MR : Mode register.
- * @sa GAR, SUBR, SHAR, SIPR
- * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt.
- * @sa RTR, RCR : Data retransmission.
- * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE.
- * @sa UIPR, UPORTR : ICMP message.
- * @sa PHYCFGR, VERSIONR : etc.
- */
-
-
-
-/**
- * @defgroup Socket_register_group Socket register
- * @ingroup WIZCHIP_register
- *
- * @brief Socket register group.\n
- * Socket register configures and control SOCKETn which is necessary to data communication.
- * @details
- * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control
- * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
- * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol.
- * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
- */
-
-
-
- /**
- * @defgroup Basic_IO_function Basic I/O function
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are basic input/output functions to read values from register or write values to register.
- */
-
-/**
- * @defgroup Common_register_access_function Common register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access common registers.
- */
-
-/**
- * @defgroup Socket_register_access_function Socket register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access socket registers.
- */
-
-//------------------------------- defgroup end --------------------------------------------
-//----------------------------- W5500 Common Registers IOMAP -----------------------------
-/**
- * @ingroup Common_register_group
- * @brief Mode Register address(R/W)\n
- * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
- * @details Each bit of @ref MR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
RST
Reserved
WOL
PB
PPPoE
Reserved
FARP
Reserved
- *
- * - \ref MR_RST : Reset
- * - \ref MR_WOL : Wake on LAN
- * - \ref MR_PB : Ping block
- * - \ref MR_PPPOE : PPPoE mode
- * - \ref MR_FARP : Force ARP mode
- */
-#define MR WIZCHIP_CREG_ADDR(0x0000)
-
-/**
- * @ingroup Common_register_group
- * @brief Gateway IP Register address(R/W)
- * @details @ref GAR configures the default gateway address.
- */
-#define GAR WIZCHIP_CREG_ADDR(0x0001)
-
-/**
- * @ingroup Common_register_group
- * @brief Subnet mask Register address(R/W)
- * @details @ref SUBR configures the subnet mask address.
- */
-#define SUBR WIZCHIP_CREG_ADDR(0x0005)
-
-/**
- * @ingroup Common_register_group
- * @brief Source MAC Register address(R/W)
- * @details @ref SHAR configures the source hardware address.
- */
-#define SHAR WIZCHIP_CREG_ADDR(0x0009)
-
-/**
- * @ingroup Common_register_group
- * @brief Source IP Register address(R/W)
- * @details @ref SIPR configures the source IP address.
- */
-#define SIPR WIZCHIP_CREG_ADDR(0x000f)
-
-/**
- * @ingroup Common_register_group
- * @brief Set Interrupt low level timer register address(R/W)
- * @details @ref INTLEVEL configures the Interrupt Assert Time.
- */
-//#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt Register(R/W)
- * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host.
- * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
- * Each bit of @ref IR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
CONFLICT
UNREACH
PPPoE
MP
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IR_CONFLICT : IP conflict
- * - \ref IR_UNREACH : Destination unreachable
- * - \ref IR_PPPoE : PPPoE connection close
- * - \ref IR_MP : Magic packet
- */
-#define IR WIZCHIP_CREG_ADDR(0x0015)
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt mask register(R/W)
- * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR.
- * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words,
- * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n
- * Each bit of @ref IMR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
IM_IR7
IM_IR6
IM_IR5
IM_IR4
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IM_IR7 : IP Conflict Interrupt Mask
- * - \ref IM_IR6 : Destination unreachable Interrupt Mask
- * - \ref IM_IR5 : PPPoE Close Interrupt Mask
- * - \ref IM_IR4 : Magic Packet Interrupt Mask
- */
-#define IMR WIZCHIP_CREG_ADDR(0x0016)
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Register(R/W)
- * @details @ref SIR indicates the interrupt status of Socket.\n
- * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n
- * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */
-//#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Mask Register(R/W)
- * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR.
- * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued.
- * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is
- */
-//#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Timeout register address( 1 is 100us )(R/W)
- * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000
- * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response
- * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
- * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout.
- */
-#define RTR WIZCHIP_CREG_ADDR(0x0017)
-
-/**
- * @ingroup Common_register_group
- * @brief Retry count register(R/W)
- * @details @ref RCR configures the number of time of retransmission.
- * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = .
- */
-#define RCR WIZCHIP_CREG_ADDR(0x0019)
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Request Timer register in PPPoE mode(R/W)
- * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
- */
-#define PTIMER WIZCHIP_CREG_ADDR(0x0028)
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Magic number register in PPPoE mode(R/W)
- * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
- */
-#define PMAGIC WIZCHIP_CREG_ADDR(0x0029)
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Destination MAC Register address(R/W)
- * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process.
- */
-//#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Session Identification Register(R/W)
- * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process.
- */
-//#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Maximum Segment Size(MSS) register(R/W)
- * @details @ref PMRU configures the maximum receive unit of PPPoE.
- */
-//#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable IP register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates
- * the destination IP address & port number respectively.
- */
-//#define UIPR (_W5500_IO_BASE_ + (0x002a << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable Port register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR
- * indicates the destination IP address & port number respectively.
- */
-//#define UPORTR (_W5500_IO_BASE_ + (0x002e << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PHY Status Register(R/W)
- * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link.
- */
-//#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-#define PHYSTATUS WIZCHIP_CREG_ADDR(0x0035)
-
-// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief chip version register address(R)
- * @details @ref VERSIONR always indicates the W5500 version as @b 0x04.
- */
-//#define VERSIONR (_W5200_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-
-//----------------------------- W5500 Socket Registers IOMAP -----------------------------
-/**
- * @ingroup Socket_register_group
- * @brief socket Mode register(R/W)
- * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n
- * Each bit of @ref Sn_MR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
MULTI/MFEN
BCASTB
ND/MC/MMB
UCASTB/MIP6B
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
- *
- * - @ref Sn_MR_MULTI : Support UDP Multicasting
- * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting
- * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag
- * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting
- * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode
- * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating
- * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * - Protocol
- *
- *
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
@b Meaning
- *
0
0
0
0
Closed
- *
0
0
0
1
TCP
- *
0
0
1
0
UDP
- *
0
1
0
0
MACRAW
- *
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n
- * - @ref Sn_MR_UDP : UDP
- * - @ref Sn_MR_TCP : TCP
- * - @ref Sn_MR_CLOSE : Unused socket
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR(N) WIZCHIP_SREG_ADDR(N, 0x0000)
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket command register(R/W)
- * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
- * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00.
- * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n
- * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR.
- * - @ref Sn_CR_OPEN : Initialize or open socket.
- * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode)
- * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode)
- * - @ref Sn_CR_DISCON : Send closing request in TCP mode.
- * - @ref Sn_CR_CLOSE : Close socket.
- * - @ref Sn_CR_SEND : Update TX buffer pointer and send data.
- * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process.
- * - @ref Sn_CR_SEND_KEEP : Send keep alive message.
- * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data.
- */
-#define Sn_CR(N) WIZCHIP_SREG_ADDR(N, 0x0001)
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket interrupt register(R)
- * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
- * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n
- * In order to clear the @ref Sn_IR bit, the host should write the bit to \n
- *
- *
7
6
5
4
3
2
1
0
- *
Reserved
Reserved
Reserved
SEND_OK
TIMEOUT
RECV
DISCON
CON
- *
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt
- * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt
- * - \ref Sn_IR_RECV : RECV Interrupt
- * - \ref Sn_IR_DISCON : DISCON Interrupt
- * - \ref Sn_IR_CON : CON Interrupt
- */
-#define Sn_IR(N) WIZCHIP_SREG_ADDR(N, 0x0002)
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket status register(R)
- * @details @ref Sn_SR indicates the status of Socket n.\n
- * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
- * @par Normal status
- * - @ref SOCK_CLOSED : Closed
- * - @ref SOCK_INIT : Initiate state
- * - @ref SOCK_LISTEN : Listen state
- * - @ref SOCK_ESTABLISHED : Success to connect
- * - @ref SOCK_CLOSE_WAIT : Closing state
- * - @ref SOCK_UDP : UDP socket
- * - @ref SOCK_MACRAW : MAC raw mode socket
- *@par Temporary status during changing the status of Socket n.
- * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
- * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
- * - @ref SOCK_FIN_WAIT : Connection state
- * - @ref SOCK_CLOSING : Closing state
- * - @ref SOCK_TIME_WAIT : Closing state
- * - @ref SOCK_LAST_ACK : Closing state
- */
-#define Sn_SR(N) WIZCHIP_SREG_ADDR(N, 0x0003)
-
-/**
- * @ingroup Socket_register_group
- * @brief source port register(R/W)
- * @details @ref Sn_PORT configures the source port number of Socket n.
- * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered.
- */
-#define Sn_PORT(N) WIZCHIP_SREG_ADDR(N, 0x0004)
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer MAC register address(R/W)
- * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
- * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
- */
-#define Sn_DHAR(N) WIZCHIP_SREG_ADDR(N, 0x0006)
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer IP register address(R/W)
- * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command.
- * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection.
- * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
- */
-#define Sn_DIPR(N) WIZCHIP_SREG_ADDR(N, 0x000c)
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer port register address(R/W)
- * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command.
- * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
- * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
- */
-#define Sn_DPORT(N) WIZCHIP_SREG_ADDR(N, 0x0010)
-
-/**
- * @ingroup Socket_register_group
- * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
- * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
- */
-#define Sn_MSSR(N) WIZCHIP_SREG_ADDR(N, 0x0012)
-
-// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief IP Type of Service(TOS) Register(R/W)
- * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TOS(N) WIZCHIP_SREG_ADDR(N, 0x0015)
-/**
- * @ingroup Socket_register_group
- * @brief IP Time to live(TTL) Register(R/W)
- * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TTL(N) WIZCHIP_SREG_ADDR(N, 0x0016)
-// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Receive memory size register(R/W)
- * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n.
- * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data cannot be normally received from a peer.
- * Although Socket n RX Buffer Block size is initially configured to 2Kbytes,
- * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data reception error is occurred.
- */
-#define Sn_RXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001e)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory size register(R/W)
- * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data can�t be normally transmitted to a peer.
- * Although Socket n TX Buffer Block size is initially configured to 2Kbytes,
- * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data transmission error is occurred.
- */
-#define Sn_TXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001f)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit free memory size register(R)
- * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE.
- * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
- * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
- * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
- * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
- */
-#define Sn_TX_FSR(N) WIZCHIP_SREG_ADDR(N, 0x0020)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory read pointer register address(R)
- * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.
- * After its initialization, it is auto-increased by SEND command.
- * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer.
- * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR.
- * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_TX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0022)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory write pointer register address(R/W)
- * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n
- * It should be read or be updated like as follows.\n
- * 1. Read the starting address for saving the transmitting data.\n
- * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
- * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size.
- * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
- * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
- */
-#define Sn_TX_WR(N) WIZCHIP_SREG_ADDR(N, 0x0024)
-
-/**
- * @ingroup Socket_register_group
- * @brief Received data size register(R)
- * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
- * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between
- * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD)
- */
-#define Sn_RX_RSR(N) WIZCHIP_SREG_ADDR(N, 0x0026)
-
-/**
- * @ingroup Socket_register_group
- * @brief Read point of Receive memory(R/W)
- * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
- * 1. Read the starting save address of the received data.\n
- * 2. Read data from the starting address of Socket n RX Buffer.\n
- * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size.
- * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
- * update with the lower 16bits value ignored the carry bit.\n
- * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500.
- */
-#define Sn_RX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0028)
-
-/**
- * @ingroup Socket_register_group
- * @brief Write point of Receive memory(R)
- * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
- * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_RX_WR(N) WIZCHIP_SREG_ADDR(N, 0x002a)
-
-/**
- * @ingroup Socket_register_group
- * @brief socket interrupt mask register(R)
- * @details @ref Sn_IMR masks the interrupt of Socket n.
- * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is
- * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is
- * Host is interrupted by asserted INTn PIN to low.
- */
-//#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Fragment field value in IP header register(R/W)
- * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header).
- */
-//#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Keep Alive Timer register(R/W)
- * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode,
- * and ignored in other modes. The time unit is 5s.
- * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once.
- * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process).
- * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate,
- * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process).
- * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'.
- */
-//#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-
-//----------------------------- W5500 Register values -----------------------------
-
-/* MODE register values */
-/**
- * @brief Reset
- * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset.
- */
-#define MR_RST 0x80
-
-/**
- * @brief Wake on LAN
- * @details 0 : Disable WOL mode\n
- * 1 : Enable WOL mode\n
- * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low.
- * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.)
- * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and
- * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode.
- */
-#define MR_WOL 0x20
-
-/**
- * @brief Ping block
- * @details 0 : Disable Ping block\n
- * 1 : Enable Ping block\n
- * If the bit is it blocks the response to a ping request.
- */
-#define MR_PB 0x10
-
-/**
- * @brief Enable PPPoE
- * @details 0 : DisablePPPoE mode\n
- * 1 : EnablePPPoE mode\n
- * If you use ADSL, this bit should be
- */
-#define MR_PPPOE 0x08
-
-/**
- * @brief Enable UDP_FORCE_ARP CHECHK
- * @details 0 : Disable Force ARP mode\n
- * 1 : Enable Force ARP mode\n
- * In Force ARP mode, It forces on sending ARP Request whenever data is sent.
- */
-#define MR_FARP 0x02
-
-/* IR register values */
-/**
- * @brief Check IP conflict.
- * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
- */
-#define IR_CONFLICT 0x80
-
-/**
- * @brief Get the destination unreachable message in UDP sending.
- * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as
- * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR.
- */
-#define IR_UNREACH 0x40
-
-/**
- * @brief Get the PPPoE close message.
- * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
- */
-#define IR_PPPoE 0x20
-
-/**
- * @brief Get the magic packet interrupt.
- * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set.
- */
-#define IR_MP 0x10
-
-
-/* PHYCFGR register value */
-#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask.
-#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value
-#define PHYCFGR_OPMDC_ALLA (7<<3)
-#define PHYCFGR_OPMDC_PDOWN (6<<3)
-#define PHYCFGR_OPMDC_NA (5<<3)
-#define PHYCFGR_OPMDC_100FA (4<<3)
-#define PHYCFGR_OPMDC_100F (3<<3)
-#define PHYCFGR_OPMDC_100H (2<<3)
-#define PHYCFGR_OPMDC_10F (1<<3)
-#define PHYCFGR_OPMDC_10H (0<<3)
-#define PHYCFGR_DPX_FULL (1<<2)
-#define PHYCFGR_DPX_HALF (0<<2)
-#define PHYCFGR_SPD_100 (1<<1)
-#define PHYCFGR_SPD_10 (0<<1)
-#define PHYCFGR_LNK_ON (1<<0)
-#define PHYCFGR_LNK_OFF (0<<0)
-
-// PHYSTATUS register
-#define PHYSTATUS_POWERDOWN (0x08)
-#define PHYSTATUS_LINK (0x20)
-
-/* IMR register values */
-/**
- * @brief IP Conflict Interrupt Mask.
- * @details 0: Disable IP Conflict Interrupt\n
- * 1: Enable IP Conflict Interrupt
- */
-#define IM_IR7 0x80
-
-/**
- * @brief Destination unreachable Interrupt Mask.
- * @details 0: Disable Destination unreachable Interrupt\n
- * 1: Enable Destination unreachable Interrupt
- */
-#define IM_IR6 0x40
-
-/**
- * @brief PPPoE Close Interrupt Mask.
- * @details 0: Disable PPPoE Close Interrupt\n
- * 1: Enable PPPoE Close Interrupt
- */
-#define IM_IR5 0x20
-
-/**
- * @brief Magic Packet Interrupt Mask.
- * @details 0: Disable Magic Packet Interrupt\n
- * 1: Enable Magic Packet Interrupt
- */
-#define IM_IR4 0x10
-
-/* Sn_MR Default values */
-/**
- * @brief Support UDP Multicasting
- * @details 0 : disable Multicasting\n
- * 1 : enable Multicasting\n
- * This bit is applied only during UDP mode(P[3:0] = 010.\n
- * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
- * before Socket n is opened by OPEN command of @ref Sn_CR.
- */
-#define Sn_MR_MULTI 0x80
-
-/**
- * @brief Broadcast block in UDP Multicasting.
- * @details 0 : disable Broadcast Blocking\n
- * 1 : enable Broadcast Blocking\n
- * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m
- * In addition, This bit does when MACRAW mode(P[3:0] = 100
- */
-//#define Sn_MR_BCASTB 0x40
-
-/**
- * @brief No Delayed Ack(TCP), Multicast flag
- * @details 0 : Disable No Delayed ACK option\n
- * 1 : Enable No Delayed ACK option\n
- * This bit is applied only during TCP mode (P[3:0] = 001.\n
- * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
- * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR.
- */
-#define Sn_MR_ND 0x20
-
-/**
- * @brief Unicast Block in UDP Multicasting
- * @details 0 : disable Unicast Blocking\n
- * 1 : enable Unicast Blocking\n
- * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI =
- */
-//#define Sn_MR_UCASTB 0x10
-
-/**
- * @brief MAC LAYER RAW SOCK
- * @details This configures the protocol mode of Socket n.
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR_MACRAW 0x04
-
-#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */
-
-/**
- * @brief UDP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_UDP 0x02
-
-/**
- * @brief TCP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_TCP 0x01
-
-/**
- * @brief Unused socket
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_CLOSE 0x00
-
-/* Sn_MR values used with Sn_MR_MACRAW */
-/**
- * @brief MAC filter enable in @ref Sn_MR_MACRAW mode
- * @details 0 : disable MAC Filtering\n
- * 1 : enable MAC Filtering\n
- * This bit is applied only during MACRAW mode(P[3:0] = 100.\n
- * When set as W5500 can only receive broadcasting packet or packet sent to itself.
- * When this bit is W5500 can receive all packets on Ethernet.
- * If user wants to implement Hybrid TCP/IP stack,
- * it is recommended that this bit is set as for reducing host overhead to process the all received packets.
- */
-#define Sn_MR_MFEN Sn_MR_MULTI
-
-/**
- * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : using IGMP version 2\n
- * 1 : using IGMP version 1\n
- * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI =
- * It configures the version for IGMP messages (Join/Leave/Report).
- */
-#define Sn_MR_MMB Sn_MR_ND
-
-/**
- * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : disable IPv6 Blocking\n
- * 1 : enable IPv6 Blocking\n
- * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet.
- */
-#define Sn_MR_MIP6B Sn_MR_UCASTB
-
-/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */
-/**
- * @brief IGMP version used in UDP mulitcasting
- * @details 0 : disable Multicast Blocking\n
- * 1 : enable Multicast Blocking\n
- * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address.
- */
-#define Sn_MR_MC Sn_MR_ND
-
-/* Sn_MR alternate values */
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_STREAM Sn_MR_TCP
-
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_DGRAM Sn_MR_UDP
-
-
-/* Sn_CR values */
-/**
- * @brief Initialize or open socket
- * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
- * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n
- *
- *
\b Sn_MR (P[3:0])
\b Sn_SR
- *
Sn_MR_CLOSE (000
- *
Sn_MR_TCP (001
SOCK_INIT (0x13)
- *
Sn_MR_UDP (010
SOCK_UDP (0x22)
- *
S0_MR_MACRAW (100
SOCK_MACRAW (0x02)
- *
- */
-#define Sn_CR_OPEN 0x01
-
-/**
- * @brief Wait connection request in TCP mode(Server mode)
- * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP).
- * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client
- * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.
- * When a �TCP clientconnection request is successfully established,
- * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes
- * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED.
- */
-#define Sn_CR_LISTEN 0x02
-
-/**
- * @brief Send connection request in TCP mode(Client mode)
- * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port).
- * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
- * The connect-request fails in the following three cases.\n
- * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n
- * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n
- * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client
- */
-#define Sn_CR_CONNECT 0x04
-
-/**
- * @brief Send closing request in TCP mode
- * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n
- * @par Active close
- * it transmits disconnect-request(FIN packet) to the connected peer\n
- * @par Passive close
- * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
- * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n
- * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_DISCON 0x08
-
-/**
- * @brief Close socket
- * @details Sn_SR is changed to @ref SOCK_CLOSED.
- */
-#define Sn_CR_CLOSE 0x10
-
-/**
- * @brief Update TX buffer pointer and send data
- * @details SEND transmits all the data in the Socket n TX buffer.\n
- * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n,
- * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD).
- */
-#define Sn_CR_SEND 0x20
-
-/**
- * @brief Send data with MAC address, so without ARP process
- * @details The basic operation is same as SEND.\n
- * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
- * But SEND_MAC transmits data without the automatic ARP-process.\n
- * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process.
- * @note Valid only in UDP mode.
- */
-#define Sn_CR_SEND_MAC 0x21
-
-/**
- * @brief Send keep alive message
- * @details It checks the connection status by sending 1byte keep-alive packet.\n
- * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_SEND_KEEP 0x22
-
-/**
- * @brief Update RX buffer pointer and receive data
- * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n
- * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR),
- * and Socket n RX Read Pointer Register (@ref Sn_RX_RD).
- */
-#define Sn_CR_RECV 0x40
-
-/* Sn_IR values */
-/**
- * @brief SEND_OK Interrupt
- * @details This is issued when SEND command is completed.
- */
-#define Sn_IR_SENDOK 0x10
-
-/**
- * @brief TIMEOUT Interrupt
- * @details This is issued when ARPTO or TCPTO occurs.
- */
-#define Sn_IR_TIMEOUT 0x08
-
-/**
- * @brief RECV Interrupt
- * @details This is issued whenever data is received from a peer.
- */
-#define Sn_IR_RECV 0x04
-
-/**
- * @brief DISCON Interrupt
- * @details This is issued when FIN or FIN/ACK packet is received from a peer.
- */
-#define Sn_IR_DISCON 0x02
-
-/**
- * @brief CON Interrupt
- * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED.
- */
-#define Sn_IR_CON 0x01
-
-/* Sn_SR values */
-/**
- * @brief Closed
- * @details This indicates that Socket n is released.\N
- * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status.
- */
-#define SOCK_CLOSED 0x00
-
-/**
- * @brief Initiate state
- * @details This indicates Socket n is opened with TCP mode.\N
- * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N
- * After @ref SOCK_INIT, user can use LISTEN /CONNECT command.
- */
-#define SOCK_INIT 0x13
-
-/**
- * @brief Listen state
- * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n
- * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n
- * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = .
- */
-#define SOCK_LISTEN 0x14
-
-/**
- * @brief Connection state
- * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
- * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n
- * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n
- * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred.
- */
-#define SOCK_SYNSENT 0x15
-
-/**
- * @brief Connection state
- * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
- * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n
- * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_SYNRECV 0x16
-
-/**
- * @brief Success to connect
- * @details This indicates the status of the connection of Socket n.\n
- * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or
- * when the CONNECT command is successful.\n
- * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
- */
-#define SOCK_ESTABLISHED 0x17
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_FIN_WAIT 0x18
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_CLOSING 0x1A
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_TIME_WAIT 0x1B
-
-/**
- * @brief Closing state
- * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
- * This is half-closing status, and data can be transferred.\n
- * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used.
- */
-#define SOCK_CLOSE_WAIT 0x1C
-
-/**
- * @brief Closing state
- * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
- * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_LAST_ACK 0x1D
-
-/**
- * @brief UDP socket
- * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n
- * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n
- * Unlike TCP mode, data can be transfered without the connection-process.
- */
-#define SOCK_UDP 0x22
-
-//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */
-
-/**
- * @brief MAC raw mode socket
- * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n
- * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n
- * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
- */
-#define SOCK_MACRAW 0x42
-
-//#define SOCK_PPPOE 0x5F
-
-/* IP PROTOCOL */
-#define IPPROTO_IP 0 //< Dummy for IP
-#define IPPROTO_ICMP 1 //< Control message protocol
-#define IPPROTO_IGMP 2 //< Internet group management protocol
-#define IPPROTO_GGP 3 //< Gateway^2 (deprecated)
-#define IPPROTO_TCP 6 //< TCP
-#define IPPROTO_PUP 12 //< PUP
-#define IPPROTO_UDP 17 //< UDP
-#define IPPROTO_IDP 22 //< XNS idp
-#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol
-#define IPPROTO_RAW 255 //< Raw IP packet
-
-
-/**
- * @brief Enter a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n \n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * \sa WIZCHIP_CRITICAL_EXIT()
- */
-#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter()
-
-/**
- * @brief Exit a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n\n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * @sa WIZCHIP_CRITICAL_ENTER()
- */
-#ifdef _exit
-#undef _exit
-#endif
-#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit()
-
-
-
-////////////////////////
-// Basic I/O Function //
-////////////////////////
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads 1 byte value from a register.
- * @param AddrSel Register address
- * @return The value of register
- */
-uint8_t WIZCHIP_READ (uint32_t AddrSel);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes 1 byte value to a register.
- * @param AddrSel Register address
- * @param wb Write data
- * @return void
- */
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads sequence data from registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to read data
- * @param len Data length
- */
-void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes sequence data to registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to write data
- * @param len Data length
- */
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/////////////////////////////////
-// Common Register I/O function //
-/////////////////////////////////
-/**
- * @ingroup Common_register_access_function
- * @brief Set Mode Register
- * @param (uint8_t)mr The value to be set.
- * @sa getMR()
- */
-#define setMR(mr) \
- WIZCHIP_WRITE(MR,mr)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get Mode Register
- * @return uint8_t. The value of Mode register.
- * @sa setMR()
- */
-#define getMR() \
- WIZCHIP_READ(MR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set gateway IP address
- * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
- * @sa getGAR()
- */
-#define setGAR(gar) \
- WIZCHIP_WRITE_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get gateway IP address
- * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
- * @sa setGAR()
- */
-#define getGAR(gar) \
- WIZCHIP_READ_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set subnet mask address
- * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
- * @sa getSUBR()
- */
-#define setSUBR(subr) \
- WIZCHIP_WRITE_BUF(SUBR, subr,4)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get subnet mask address
- * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
- * @sa setSUBR()
- */
-#define getSUBR(subr) \
- WIZCHIP_READ_BUF(SUBR, subr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local MAC address
- * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
- * @sa getSHAR()
- */
-#define setSHAR(shar) \
- WIZCHIP_WRITE_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local MAC address
- * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
- * @sa setSHAR()
- */
-#define getSHAR(shar) \
- WIZCHIP_READ_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local IP address
- * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
- * @sa getSIPR()
- */
-#define setSIPR(sipr) \
- WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
- * @sa setSIPR()
- */
-#define getSIPR(sipr) \
- WIZCHIP_READ_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set INTLEVEL register
- * @param (uint16_t)intlevel Value to set @ref INTLEVEL register.
- * @sa getINTLEVEL()
- */
-// dpgeorge: not yet implemented
-#define setINTLEVEL(intlevel) (void)intlevel
-#if 0
-#define setINTLEVEL(intlevel) {\
- WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \
- }
-#endif
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get INTLEVEL register
- * @return uint16_t. Value of @ref INTLEVEL register.
- * @sa setINTLEVEL()
- */
-// dpgeorge: not yet implemented
-#define getINTLEVEL() (0)
-#if 0
-#define getINTLEVEL() \
- ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1)))
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IR register
- * @param (uint8_t)ir Value to set @ref IR register.
- * @sa getIR()
- */
-#define setIR(ir) \
- WIZCHIP_WRITE(IR, (ir & 0xF0))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IR register
- * @return uint8_t. Value of @ref IR register.
- * @sa setIR()
- */
-#define getIR() \
- (WIZCHIP_READ(IR) & 0xF0)
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IMR register
- * @param (uint8_t)imr Value to set @ref IMR register.
- * @sa getIMR()
- */
-#define setIMR(imr) \
- WIZCHIP_WRITE(IMR, imr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IMR register
- * @return uint8_t. Value of @ref IMR register.
- * @sa setIMR()
- */
-#define getIMR() \
- WIZCHIP_READ(IMR)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIR register
- * @param (uint8_t)sir Value to set @ref SIR register.
- * @sa getSIR()
- */
-// dpgeorge: not yet implemented
-#define setSIR(sir) ((void)sir)
-#if 0
-#define setSIR(sir) \
- WIZCHIP_WRITE(SIR, sir)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIR register
- * @return uint8_t. Value of @ref SIR register.
- * @sa setSIR()
- */
-// dpgeorge: not yet implemented
-#define getSIR() (0)
-#if 0
-#define getSIR() \
- WIZCHIP_READ(SIR)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIMR register
- * @param (uint8_t)simr Value to set @ref SIMR register.
- * @sa getSIMR()
- */
-// dpgeorge: not yet implemented
-#define setSIMR(simr) ((void)simr)
-#if 0
-#define setSIMR(simr) \
- WIZCHIP_WRITE(SIMR, simr)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIMR register
- * @return uint8_t. Value of @ref SIMR register.
- * @sa setSIMR()
- */
-// dpgeorge: not yet implemented
-#define getSIMR() (0)
-#if 0
-#define getSIMR() \
- WIZCHIP_READ(SIMR)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RTR register
- * @param (uint16_t)rtr Value to set @ref RTR register.
- * @sa getRTR()
- */
-#define setRTR(rtr) {\
- WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \
- WIZCHIP_WRITE(RTR + 1, (uint8_t) rtr); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RTR register
- * @return uint16_t. Value of @ref RTR register.
- * @sa setRTR()
- */
-#define getRTR() \
- ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(RTR + 1))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RCR register
- * @param (uint8_t)rcr Value to set @ref RCR register.
- * @sa getRCR()
- */
-#define setRCR(rcr) \
- WIZCHIP_WRITE(RCR, rcr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RCR register
- * @return uint8_t. Value of @ref RCR register.
- * @sa setRCR()
- */
-#define getRCR() \
- WIZCHIP_READ(RCR)
-
-//================================================== test done ===========================================================
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PTIMER register
- * @param (uint8_t)ptimer Value to set @ref PTIMER register.
- * @sa getPTIMER()
- */
-#define setPTIMER(ptimer) \
- WIZCHIP_WRITE(PTIMER, ptimer)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PTIMER register
- * @return uint8_t. Value of @ref PTIMER register.
- * @sa setPTIMER()
- */
-#define getPTIMER() \
- WIZCHIP_READ(PTIMER)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMAGIC register
- * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
- * @sa getPMAGIC()
- */
-#define setPMAGIC(pmagic) \
- WIZCHIP_WRITE(PMAGIC, pmagic)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMAGIC register
- * @return uint8_t. Value of @ref PMAGIC register.
- * @sa setPMAGIC()
- */
-#define getPMAGIC() \
- WIZCHIP_READ(PMAGIC)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set PHAR address
- * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa getPHAR()
- */
-#if 0
-#define setPHAR(phar) \
- WIZCHIP_WRITE_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa setPHAR()
- */
-#define getPHAR(phar) \
- WIZCHIP_READ_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PSID register
- * @param (uint16_t)psid Value to set @ref PSID register.
- * @sa getPSID()
- */
-#define setPSID(psid) {\
- WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PSID register
- * @return uint16_t. Value of @ref PSID register.
- * @sa setPSID()
- */
-//uint16_t getPSID(void);
-#define getPSID() \
- ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMRU register
- * @param (uint16_t)pmru Value to set @ref PMRU register.
- * @sa getPMRU()
- */
-#define setPMRU(pmru) { \
- WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMRU register
- * @return uint16_t. Value of @ref PMRU register.
- * @sa setPMRU()
- */
-#define getPMRU() \
- ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get unreachable IP address
- * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes.
- */
-#define getUIPR(uipr) \
- WIZCHIP_READ_BUF(UIPR,uipr,6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref UPORTR register
- * @return uint16_t. Value of @ref UPORTR register.
- */
-#define getUPORTR() \
- ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PHYCFGR register
- * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register.
- * @sa getPHYCFGR()
- */
-#define setPHYCFGR(phycfgr) \
- WIZCHIP_WRITE(PHYCFGR, phycfgr)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PHYCFGR register
- * @return uint8_t. Value of @ref PHYCFGR register.
- * @sa setPHYCFGR()
- */
-#define getPHYSTATUS() \
- WIZCHIP_READ(PHYSTATUS)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref VERSIONR register
- * @return uint8_t. Value of @ref VERSIONR register.
- */
-/*
-#define getVERSIONR() \
- WIZCHIP_READ(VERSIONR)
- */
-/////////////////////////////////////
-
-///////////////////////////////////
-// Socket N register I/O function //
-///////////////////////////////////
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)mr Value to set @ref Sn_MR
- * @sa getSn_MR()
- */
-#define setSn_MR(sn, mr) \
- WIZCHIP_WRITE(Sn_MR(sn),mr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_MR.
- * @sa setSn_MR()
- */
-#define getSn_MR(sn) \
- WIZCHIP_READ(Sn_MR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)cr Value to set @ref Sn_CR
- * @sa getSn_CR()
- */
-#define setSn_CR(sn, cr) \
- WIZCHIP_WRITE(Sn_CR(sn), cr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_CR.
- * @sa setSn_CR()
- */
-#define getSn_CR(sn) \
- WIZCHIP_READ(Sn_CR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ir Value to set @ref Sn_IR
- * @sa getSn_IR()
- */
-#define setSn_IR(sn, ir) \
- WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IR.
- * @sa setSn_IR()
- */
-#define getSn_IR(sn) \
- (WIZCHIP_READ(Sn_IR(sn)) & 0x1F)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)imr Value to set @ref Sn_IMR
- * @sa getSn_IMR()
- */
-// dpgeorge: not yet implemented
-#define setSn_IMR(sn, imr) (void)sn; (void)imr
-#if 0
-#define setSn_IMR(sn, imr) \
- WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F))
-#endif
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IMR.
- * @sa setSn_IMR()
- */
-// dpgeorge: not yet implemented
-#define getSn_IMR(sn) (0)
-#if 0
-#define getSn_IMR(sn) \
- (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F)
-#endif
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_SR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_SR.
- */
-#define getSn_SR(sn) \
- WIZCHIP_READ(Sn_SR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)port Value to set @ref Sn_PORT.
- * @sa getSn_PORT()
- */
-#define setSn_PORT(sn, port) { \
- WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \
- WIZCHIP_WRITE(Sn_PORT(sn) + 1, (uint8_t) port); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_PORT.
- * @sa setSn_PORT()
- */
-#define getSn_PORT(sn) \
- ((WIZCHIP_READ(Sn_PORT(sn)) << 8) | WIZCHIP_READ(Sn_PORT(sn) + 1))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DHAR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
- * @sa getSn_DHAR()
- */
-#define setSn_DHAR(sn, dhar) \
- WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
- * @sa setSn_DHAR()
- */
-#define getSn_DHAR(sn, dhar) \
- WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
- * @sa getSn_DIPR()
- */
-#define setSn_DIPR(sn, dipr) \
- WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
- * @sa SetSn_DIPR()
- */
-#define getSn_DIPR(sn, dipr) \
- WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)dport Value to set @ref Sn_DPORT
- * @sa getSn_DPORT()
- */
-#define setSn_DPORT(sn, dport) { \
- WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \
- WIZCHIP_WRITE(Sn_DPORT(sn) + 1, (uint8_t) dport); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_DPORT.
- * @sa setSn_DPORT()
- */
-#define getSn_DPORT(sn) \
- ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ((Sn_DPORT(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)mss Value to set @ref Sn_MSSR
- * @sa setSn_MSSR()
- */
-#define setSn_MSSR(sn, mss) { \
- WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \
- WIZCHIP_WRITE((Sn_MSSR(sn)+1), (uint8_t) mss); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_MSSR.
- * @sa setSn_MSSR()
- */
-#define getSn_MSSR(sn) \
- ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ((Sn_MSSR(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)tos Value to set @ref Sn_TOS
- * @sa getSn_TOS()
- */
-#define setSn_TOS(sn, tos) \
- WIZCHIP_WRITE(Sn_TOS(sn), tos)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of Sn_TOS.
- * @sa setSn_TOS()
- */
-#define getSn_TOS(sn) \
- WIZCHIP_READ(Sn_TOS(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ttl Value to set @ref Sn_TTL
- * @sa getSn_TTL()
- */
-#define setSn_TTL(sn, ttl) \
- WIZCHIP_WRITE(Sn_TTL(sn), ttl)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TTL.
- * @sa setSn_TTL()
- */
-#define getSn_TTL(sn) \
- WIZCHIP_READ(Sn_TTL(sn))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE
- * @sa getSn_RXBUF_SIZE()
- */
-#define setSn_RXBUF_SIZE(sn, rxbufsize) \
- WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_RXBUF_SIZE.
- * @sa setSn_RXBUF_SIZE()
- */
-#define getSn_RXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_RXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE
- * @sa getSn_TXBUF_SIZE()
- */
-#define setSn_TXBUF_SIZE(sn, txbufsize) \
- WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TXBUF_SIZE.
- * @sa setSn_TXBUF_SIZE()
- */
-#define getSn_TXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_TXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_FSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_FSR.
- */
-uint16_t getSn_TX_FSR(uint8_t sn);
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_RD.
- */
-#define getSn_TX_RD(sn) \
- ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ((Sn_TX_RD(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
- * @sa GetSn_TX_WR()
- */
-#define setSn_TX_WR(sn, txwr) { \
- WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \
- WIZCHIP_WRITE((Sn_TX_WR(sn)+1), (uint8_t) txwr); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_WR.
- * @sa setSn_TX_WR()
- */
-#define getSn_TX_WR(sn) \
- ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ((Sn_TX_WR(sn)+1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_RSR.
- */
-uint16_t getSn_RX_RSR(uint8_t sn);
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
- * @sa getSn_RX_RD()
- */
-#define setSn_RX_RD(sn, rxrd) { \
- WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \
- WIZCHIP_WRITE((Sn_RX_RD(sn)+1), (uint8_t) rxrd); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @regurn uint16_t. Value of @ref Sn_RX_RD.
- * @sa setSn_RX_RD()
- */
-#define getSn_RX_RD(sn) \
- ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ((Sn_RX_RD(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_WR.
- */
-#define getSn_RX_WR(sn) \
- ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ((Sn_RX_WR(sn)+1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)frag Value to set @ref Sn_FRAG
- * @sa getSn_FRAD()
- */
-#if 0 // dpgeorge
-#define setSn_FRAG(sn, frag) { \
- WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_FRAG.
- * @sa setSn_FRAG()
- */
-#define getSn_FRAG(sn) \
- ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR
- * @sa getSn_KPALVTR()
- */
-#define setSn_KPALVTR(sn, kpalvt) \
- WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_KPALVTR.
- * @sa setSn_KPALVTR()
- */
-#define getSn_KPALVTR(sn) \
- WIZCHIP_READ(Sn_KPALVTR(sn))
-
-//////////////////////////////////////
-#endif
-
-/////////////////////////////////////
-// Sn_TXBUF & Sn_RXBUF IO function //
-/////////////////////////////////////
-/**
- * @brief Gets the max buffer size of socket sn passed as parameter.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n RX max buffer size.
- */
-#define getSn_RxMAX(sn) \
- (getSn_RXBUF_SIZE(sn) << 10)
-
-/**
- * @brief Gets the max buffer size of socket sn passed as parameters.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n TX max buffer size.
- */
-//uint16_t getSn_TxMAX(uint8_t sn);
-#define getSn_TxMAX(sn) \
- (getSn_TXBUF_SIZE(sn) << 10)
-
-void wiz_init(void);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to internal TX memory
- *
- * @details This function reads the Tx write pointer register and after that,
- * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory
- * and updates the Tx write pointer register.
- * This function is being called by send() and sendto() function also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to write data
- * @param len Data length
- * @sa wiz_recv_data()
- */
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to your buffer from internal RX memory
- *
- * @details This function read the Rx read pointer register and after that,
- * it copies the received data from internal RX memory
- * to wizdata(pointer variable) of the length of len(variable) bytes.
- * This function is being called by recv() also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to read data
- * @param len Data length
- * @sa wiz_send_data()
- */
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It discard the received data in RX memory.
- * @details It discards the data of the length of len(variable) bytes in internal RX memory.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param len Data length
- */
-void wiz_recv_ignore(uint8_t sn, uint16_t len);
-
-#endif // _W5500_H_
diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.c b/drivers/wiznet5k/ethernet/w5500/w5500.c
deleted file mode 100644
index 3107b1b71aa39..0000000000000
--- a/drivers/wiznet5k/ethernet/w5500/w5500.c
+++ /dev/null
@@ -1,247 +0,0 @@
-//*****************************************************************************
-//
-//! \file w5500.c
-//! \brief W5500 HAL Interface.
-//! \version 1.0.1
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.2
-//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
-//! Fixed the problem on porting into under 32bit MCU
-//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
-//! Thank for your interesting and serious advices.
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.0.1
-//! 1. Remove warning
-//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
-//! for loop optimized(removed). refer to M20131220
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************
-//#include
-#include "w5500.h"
-
-#define _W5500_SPI_VDM_OP_ 0x00
-#define _W5500_SPI_FDM_OP_LEN1_ 0x01
-#define _W5500_SPI_FDM_OP_LEN2_ 0x02
-#define _W5500_SPI_FDM_OP_LEN4_ 0x03
-
-////////////////////////////////////////////////////
-
-#define LPC_SSP0 (0)
-
-static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) {
- WIZCHIP.IF.SPI._read_bytes(buf, len);
-}
-
-static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) {
- WIZCHIP.IF.SPI._write_bytes(buf, len);
-}
-
-uint8_t WIZCHIP_READ(uint32_t AddrSel)
-{
- uint8_t ret;
- uint8_t spi_data[3];
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //ret = WIZCHIP.IF.SPI._read_byte();
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
- Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
- return ret;
-}
-
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
-{
- uint8_t spi_data[4];
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //WIZCHIP.IF.SPI._write_byte(wb);
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- spi_data[3] = wb;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
-{
- uint8_t spi_data[3];
- //uint16_t i;
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //for(i = 0; i < len; i++)
- // pBuf[i] = WIZCHIP.IF.SPI._read_byte();
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
- Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
-{
- uint8_t spi_data[3];
- //uint16_t i;
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //for(i = 0; i < len; i++)
- // WIZCHIP.IF.SPI._write_byte(pBuf[i]);
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-
-uint16_t getSn_TX_FSR(uint8_t sn)
-{
- uint16_t val=0,val1=0;
-
- do
- {
- val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
- val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
- if (val1 != 0)
- {
- val = WIZCHIP_READ(Sn_TX_FSR(sn));
- val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
- }
- }while (val != val1);
- return val;
-}
-
-
-uint16_t getSn_RX_RSR(uint8_t sn)
-{
- uint16_t val=0,val1=0;
-
- do
- {
- val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
- val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
- if (val1 != 0)
- {
- val = WIZCHIP_READ(Sn_RX_RSR(sn));
- val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
- }
- }while (val != val1);
- return val;
-}
-
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
-{
- uint16_t ptr = 0;
- uint32_t addrsel = 0;
-
- if(len == 0) return;
- ptr = getSn_TX_WR(sn);
- //M20140501 : implict type casting -> explict type casting
- //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
- addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
- //
- WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
-
- ptr += len;
- setSn_TX_WR(sn,ptr);
-}
-
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
-{
- uint16_t ptr = 0;
- uint32_t addrsel = 0;
-
- if(len == 0) return;
- ptr = getSn_RX_RD(sn);
- //M20140501 : implict type casting -> explict type casting
- //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
- addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
- //
- WIZCHIP_READ_BUF(addrsel, wizdata, len);
- ptr += len;
-
- setSn_RX_RD(sn,ptr);
-}
-
-
-void wiz_recv_ignore(uint8_t sn, uint16_t len)
-{
- uint16_t ptr = 0;
-
- ptr = getSn_RX_RD(sn);
- ptr += len;
- setSn_RX_RD(sn,ptr);
-}
-
diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.h b/drivers/wiznet5k/ethernet/w5500/w5500.h
deleted file mode 100644
index c2afb180ebbad..0000000000000
--- a/drivers/wiznet5k/ethernet/w5500/w5500.h
+++ /dev/null
@@ -1,2057 +0,0 @@
-//*****************************************************************************
-//
-//! \file w5500.h
-//! \brief W5500 HAL Header File.
-//! \version 1.0.0
-//! \date 2013/10/21
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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 _W5500_H_
-#define _W5500_H_
-
-#include
-#include "../wizchip_conf.h"
-
-#define _W5500_IO_BASE_ 0x00000000
-
-#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase
-#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase
-
-#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block
-#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block
-#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block
-#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block
-
-#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address
-
-
-///////////////////////////////////////
-// Definition For Legacy Chip Driver //
-///////////////////////////////////////
-#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver
-#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver
-#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver
-#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver
-
-//////////////////////////////
-//-------------------------- defgroup ---------------------------------
-/**
- * @defgroup W5500 W5500
- *
- * @brief WHIZCHIP register defines and I/O functions of @b W5500.
- *
- * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group
- * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function
- */
-
-
-/**
- * @defgroup WIZCHIP_register WIZCHIP register
- * @ingroup W5500
- *
- * @brief WHIZCHIP register defines register group of @b W5500.
- *
- * - @ref Common_register_group : Common register group
- * - @ref Socket_register_group : \c SOCKET n register group
- */
-
-
-/**
- * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions
- * @ingroup W5500
- *
- * @brief This supports the basic I/O functions for @ref WIZCHIP_register.
- *
- * - Basic I/O function \n
- * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n
- *
- * - @ref Common_register_group access functions \n
- * -# @b Mode \n
- * getMR(), setMR()
- * -# @b Interrupt \n
- * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL()
- * -# Network Information \n
- * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
- * -# @b Retransmission \n
- * getRCR(), setRCR(), getRTR(), setRTR()
- * -# @b PPPoE \n
- * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU()
- * -# ICMP packet \n
- * getUIPR(), getUPORTR()
- * -# @b etc. \n
- * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n
- *
- * - \ref Socket_register_group access functions \n
- * -# SOCKET control \n
- * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR()
- * -# SOCKET information \n
- * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
- * getSn_MSSR(), setSn_MSSR()
- * -# SOCKET communication \n
- * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n
- * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
- * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
- * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR()
- * -# IP header field \n
- * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n
- * getSn_TTL(), setSn_TTL()
- */
-
-
-
-/**
- * @defgroup Common_register_group Common register
- * @ingroup WIZCHIP_register
- *
- * @brief Common register group\n
- * It set the basic for the networking\n
- * It set the configuration such as interrupt, network information, ICMP, etc.
- * @details
- * @sa MR : Mode register.
- * @sa GAR, SUBR, SHAR, SIPR
- * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt.
- * @sa RTR, RCR : Data retransmission.
- * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE.
- * @sa UIPR, UPORTR : ICMP message.
- * @sa PHYCFGR, VERSIONR : etc.
- */
-
-
-
-/**
- * @defgroup Socket_register_group Socket register
- * @ingroup WIZCHIP_register
- *
- * @brief Socket register group.\n
- * Socket register configures and control SOCKETn which is necessary to data communication.
- * @details
- * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control
- * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
- * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol.
- * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
- */
-
-
-
- /**
- * @defgroup Basic_IO_function Basic I/O function
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are basic input/output functions to read values from register or write values to register.
- */
-
-/**
- * @defgroup Common_register_access_function Common register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access common registers.
- */
-
-/**
- * @defgroup Socket_register_access_function Socket register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access socket registers.
- */
-
-//------------------------------- defgroup end --------------------------------------------
-//----------------------------- W5500 Common Registers IOMAP -----------------------------
-/**
- * @ingroup Common_register_group
- * @brief Mode Register address(R/W)\n
- * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
- * @details Each bit of @ref MR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
RST
Reserved
WOL
PB
PPPoE
Reserved
FARP
Reserved
- *
- * - \ref MR_RST : Reset
- * - \ref MR_WOL : Wake on LAN
- * - \ref MR_PB : Ping block
- * - \ref MR_PPPOE : PPPoE mode
- * - \ref MR_FARP : Force ARP mode
- */
-#define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Gateway IP Register address(R/W)
- * @details @ref GAR configures the default gateway address.
- */
-#define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Subnet mask Register address(R/W)
- * @details @ref SUBR configures the subnet mask address.
- */
-#define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Source MAC Register address(R/W)
- * @details @ref SHAR configures the source hardware address.
- */
-#define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Source IP Register address(R/W)
- * @details @ref SIPR configures the source IP address.
- */
-#define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Set Interrupt low level timer register address(R/W)
- * @details @ref INTLEVEL configures the Interrupt Assert Time.
- */
-#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt Register(R/W)
- * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host.
- * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
- * Each bit of @ref IR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
CONFLICT
UNREACH
PPPoE
MP
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IR_CONFLICT : IP conflict
- * - \ref IR_UNREACH : Destination unreachable
- * - \ref IR_PPPoE : PPPoE connection close
- * - \ref IR_MP : Magic packet
- */
-#define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt mask register(R/W)
- * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR.
- * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words,
- * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n
- * Each bit of @ref IMR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
IM_IR7
IM_IR6
IM_IR5
IM_IR4
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IM_IR7 : IP Conflict Interrupt Mask
- * - \ref IM_IR6 : Destination unreachable Interrupt Mask
- * - \ref IM_IR5 : PPPoE Close Interrupt Mask
- * - \ref IM_IR4 : Magic Packet Interrupt Mask
- */
-#define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Register(R/W)
- * @details @ref SIR indicates the interrupt status of Socket.\n
- * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n
- * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */
-#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Mask Register(R/W)
- * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR.
- * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued.
- * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is
- */
-#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Timeout register address( 1 is 100us )(R/W)
- * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000
- * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response
- * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
- * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout.
- */
-#define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Retry count register(R/W)
- * @details @ref RCR configures the number of time of retransmission.
- * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = .
- */
-#define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Request Timer register in PPPoE mode(R/W)
- * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
- */
-#define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Magic number register in PPPoE mode(R/W)
- * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
- */
-#define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Destination MAC Register address(R/W)
- * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process.
- */
-#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Session Identification Register(R/W)
- * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process.
- */
-#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Maximum Segment Size(MSS) register(R/W)
- * @details @ref PMRU configures the maximum receive unit of PPPoE.
- */
-#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable IP register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates
- * the destination IP address & port number respectively.
- */
-#define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable Port register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR
- * indicates the destination IP address & port number respectively.
- */
-#define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PHY Status Register(R/W)
- * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link.
- */
-#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief chip version register address(R)
- * @details @ref VERSIONR always indicates the W5500 version as @b 0x04.
- */
-#define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-
-//----------------------------- W5500 Socket Registers IOMAP -----------------------------
-/**
- * @ingroup Socket_register_group
- * @brief socket Mode register(R/W)
- * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n
- * Each bit of @ref Sn_MR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
MULTI/MFEN
BCASTB
ND/MC/MMB
UCASTB/MIP6B
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
- *
- * - @ref Sn_MR_MULTI : Support UDP Multicasting
- * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting
- * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag
- * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting
- * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode
- * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating
- * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * - Protocol
- *
- *
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
@b Meaning
- *
0
0
0
0
Closed
- *
0
0
0
1
TCP
- *
0
0
1
0
UDP
- *
0
1
0
0
MACRAW
- *
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n
- * - @ref Sn_MR_UDP : UDP
- * - @ref Sn_MR_TCP : TCP
- * - @ref Sn_MR_CLOSE : Unused socket
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket command register(R/W)
- * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
- * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00.
- * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n
- * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR.
- * - @ref Sn_CR_OPEN : Initialize or open socket.
- * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode)
- * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode)
- * - @ref Sn_CR_DISCON : Send closing request in TCP mode.
- * - @ref Sn_CR_CLOSE : Close socket.
- * - @ref Sn_CR_SEND : Update TX buffer pointer and send data.
- * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process.
- * - @ref Sn_CR_SEND_KEEP : Send keep alive message.
- * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data.
- */
-#define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket interrupt register(R)
- * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
- * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n
- * In order to clear the @ref Sn_IR bit, the host should write the bit to \n
- *
- *
7
6
5
4
3
2
1
0
- *
Reserved
Reserved
Reserved
SEND_OK
TIMEOUT
RECV
DISCON
CON
- *
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt
- * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt
- * - \ref Sn_IR_RECV : RECV Interrupt
- * - \ref Sn_IR_DISCON : DISCON Interrupt
- * - \ref Sn_IR_CON : CON Interrupt
- */
-#define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket status register(R)
- * @details @ref Sn_SR indicates the status of Socket n.\n
- * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
- * @par Normal status
- * - @ref SOCK_CLOSED : Closed
- * - @ref SOCK_INIT : Initiate state
- * - @ref SOCK_LISTEN : Listen state
- * - @ref SOCK_ESTABLISHED : Success to connect
- * - @ref SOCK_CLOSE_WAIT : Closing state
- * - @ref SOCK_UDP : UDP socket
- * - @ref SOCK_MACRAW : MAC raw mode socket
- *@par Temporary status during changing the status of Socket n.
- * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
- * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
- * - @ref SOCK_FIN_WAIT : Connection state
- * - @ref SOCK_CLOSING : Closing state
- * - @ref SOCK_TIME_WAIT : Closing state
- * - @ref SOCK_LAST_ACK : Closing state
- */
-#define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief source port register(R/W)
- * @details @ref Sn_PORT configures the source port number of Socket n.
- * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered.
- */
-#define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer MAC register address(R/W)
- * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
- * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
- */
-#define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer IP register address(R/W)
- * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command.
- * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection.
- * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
- */
-#define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer port register address(R/W)
- * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command.
- * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
- * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
- */
-#define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
- * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
- */
-#define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief IP Type of Service(TOS) Register(R/W)
- * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-/**
- * @ingroup Socket_register_group
- * @brief IP Time to live(TTL) Register(R/W)
- * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Receive memory size register(R/W)
- * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n.
- * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data cannot be normally received from a peer.
- * Although Socket n RX Buffer Block size is initially configured to 2Kbytes,
- * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data reception error is occurred.
- */
-#define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory size register(R/W)
- * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data can�t be normally transmitted to a peer.
- * Although Socket n TX Buffer Block size is initially configured to 2Kbytes,
- * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data transmission error is occurred.
- */
-#define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit free memory size register(R)
- * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE.
- * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
- * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
- * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
- * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
- */
-#define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory read pointer register address(R)
- * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.
- * After its initialization, it is auto-increased by SEND command.
- * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer.
- * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR.
- * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory write pointer register address(R/W)
- * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n
- * It should be read or be updated like as follows.\n
- * 1. Read the starting address for saving the transmitting data.\n
- * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
- * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size.
- * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
- * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
- */
-#define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Received data size register(R)
- * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
- * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between
- * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD)
- */
-#define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Read point of Receive memory(R/W)
- * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
- * 1. Read the starting save address of the received data.\n
- * 2. Read data from the starting address of Socket n RX Buffer.\n
- * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size.
- * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
- * update with the lower 16bits value ignored the carry bit.\n
- * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500.
- */
-#define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Write point of Receive memory(R)
- * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
- * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief socket interrupt mask register(R)
- * @details @ref Sn_IMR masks the interrupt of Socket n.
- * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is
- * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is
- * Host is interrupted by asserted INTn PIN to low.
- */
-#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Fragment field value in IP header register(R/W)
- * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header).
- */
-#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Keep Alive Timer register(R/W)
- * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode,
- * and ignored in other modes. The time unit is 5s.
- * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once.
- * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process).
- * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate,
- * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process).
- * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'.
- */
-#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-
-//----------------------------- W5500 Register values -----------------------------
-
-/* MODE register values */
-/**
- * @brief Reset
- * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset.
- */
-#define MR_RST 0x80
-
-/**
- * @brief Wake on LAN
- * @details 0 : Disable WOL mode\n
- * 1 : Enable WOL mode\n
- * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low.
- * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.)
- * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and
- * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode.
- */
-#define MR_WOL 0x20
-
-/**
- * @brief Ping block
- * @details 0 : Disable Ping block\n
- * 1 : Enable Ping block\n
- * If the bit is it blocks the response to a ping request.
- */
-#define MR_PB 0x10
-
-/**
- * @brief Enable PPPoE
- * @details 0 : DisablePPPoE mode\n
- * 1 : EnablePPPoE mode\n
- * If you use ADSL, this bit should be
- */
-#define MR_PPPOE 0x08
-
-/**
- * @brief Enable UDP_FORCE_ARP CHECHK
- * @details 0 : Disable Force ARP mode\n
- * 1 : Enable Force ARP mode\n
- * In Force ARP mode, It forces on sending ARP Request whenever data is sent.
- */
-#define MR_FARP 0x02
-
-/* IR register values */
-/**
- * @brief Check IP conflict.
- * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
- */
-#define IR_CONFLICT 0x80
-
-/**
- * @brief Get the destination unreachable message in UDP sending.
- * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as
- * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR.
- */
-#define IR_UNREACH 0x40
-
-/**
- * @brief Get the PPPoE close message.
- * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
- */
-#define IR_PPPoE 0x20
-
-/**
- * @brief Get the magic packet interrupt.
- * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set.
- */
-#define IR_MP 0x10
-
-
-/* PHYCFGR register value */
-#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask.
-#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value
-#define PHYCFGR_OPMDC_ALLA (7<<3)
-#define PHYCFGR_OPMDC_PDOWN (6<<3)
-#define PHYCFGR_OPMDC_NA (5<<3)
-#define PHYCFGR_OPMDC_100FA (4<<3)
-#define PHYCFGR_OPMDC_100F (3<<3)
-#define PHYCFGR_OPMDC_100H (2<<3)
-#define PHYCFGR_OPMDC_10F (1<<3)
-#define PHYCFGR_OPMDC_10H (0<<3)
-#define PHYCFGR_DPX_FULL (1<<2)
-#define PHYCFGR_DPX_HALF (0<<2)
-#define PHYCFGR_SPD_100 (1<<1)
-#define PHYCFGR_SPD_10 (0<<1)
-#define PHYCFGR_LNK_ON (1<<0)
-#define PHYCFGR_LNK_OFF (0<<0)
-
-/* IMR register values */
-/**
- * @brief IP Conflict Interrupt Mask.
- * @details 0: Disable IP Conflict Interrupt\n
- * 1: Enable IP Conflict Interrupt
- */
-#define IM_IR7 0x80
-
-/**
- * @brief Destination unreachable Interrupt Mask.
- * @details 0: Disable Destination unreachable Interrupt\n
- * 1: Enable Destination unreachable Interrupt
- */
-#define IM_IR6 0x40
-
-/**
- * @brief PPPoE Close Interrupt Mask.
- * @details 0: Disable PPPoE Close Interrupt\n
- * 1: Enable PPPoE Close Interrupt
- */
-#define IM_IR5 0x20
-
-/**
- * @brief Magic Packet Interrupt Mask.
- * @details 0: Disable Magic Packet Interrupt\n
- * 1: Enable Magic Packet Interrupt
- */
-#define IM_IR4 0x10
-
-/* Sn_MR Default values */
-/**
- * @brief Support UDP Multicasting
- * @details 0 : disable Multicasting\n
- * 1 : enable Multicasting\n
- * This bit is applied only during UDP mode(P[3:0] = 010.\n
- * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
- * before Socket n is opened by OPEN command of @ref Sn_CR.
- */
-#define Sn_MR_MULTI 0x80
-
-/**
- * @brief Broadcast block in UDP Multicasting.
- * @details 0 : disable Broadcast Blocking\n
- * 1 : enable Broadcast Blocking\n
- * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m
- * In addition, This bit does when MACRAW mode(P[3:0] = 100
- */
-#define Sn_MR_BCASTB 0x40
-
-/**
- * @brief No Delayed Ack(TCP), Multicast flag
- * @details 0 : Disable No Delayed ACK option\n
- * 1 : Enable No Delayed ACK option\n
- * This bit is applied only during TCP mode (P[3:0] = 001.\n
- * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
- * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR.
- */
-#define Sn_MR_ND 0x20
-
-/**
- * @brief Unicast Block in UDP Multicasting
- * @details 0 : disable Unicast Blocking\n
- * 1 : enable Unicast Blocking\n
- * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI =
- */
-#define Sn_MR_UCASTB 0x10
-
-/**
- * @brief MAC LAYER RAW SOCK
- * @details This configures the protocol mode of Socket n.
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR_MACRAW 0x04
-
-//#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */
-
-/**
- * @brief UDP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_UDP 0x02
-
-/**
- * @brief TCP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_TCP 0x01
-
-/**
- * @brief Unused socket
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_CLOSE 0x00
-
-/* Sn_MR values used with Sn_MR_MACRAW */
-/**
- * @brief MAC filter enable in @ref Sn_MR_MACRAW mode
- * @details 0 : disable MAC Filtering\n
- * 1 : enable MAC Filtering\n
- * This bit is applied only during MACRAW mode(P[3:0] = 100.\n
- * When set as W5500 can only receive broadcasting packet or packet sent to itself.
- * When this bit is W5500 can receive all packets on Ethernet.
- * If user wants to implement Hybrid TCP/IP stack,
- * it is recommended that this bit is set as for reducing host overhead to process the all received packets.
- */
-#define Sn_MR_MFEN Sn_MR_MULTI
-
-/**
- * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : using IGMP version 2\n
- * 1 : using IGMP version 1\n
- * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI =
- * It configures the version for IGMP messages (Join/Leave/Report).
- */
-#define Sn_MR_MMB Sn_MR_ND
-
-/**
- * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : disable IPv6 Blocking\n
- * 1 : enable IPv6 Blocking\n
- * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet.
- */
-#define Sn_MR_MIP6B Sn_MR_UCASTB
-
-/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */
-/**
- * @brief IGMP version used in UDP mulitcasting
- * @details 0 : disable Multicast Blocking\n
- * 1 : enable Multicast Blocking\n
- * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address.
- */
-#define Sn_MR_MC Sn_MR_ND
-
-/* Sn_MR alternate values */
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_STREAM Sn_MR_TCP
-
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_DGRAM Sn_MR_UDP
-
-
-/* Sn_CR values */
-/**
- * @brief Initialize or open socket
- * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
- * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n
- *
- *
\b Sn_MR (P[3:0])
\b Sn_SR
- *
Sn_MR_CLOSE (000
- *
Sn_MR_TCP (001
SOCK_INIT (0x13)
- *
Sn_MR_UDP (010
SOCK_UDP (0x22)
- *
S0_MR_MACRAW (100
SOCK_MACRAW (0x02)
- *
- */
-#define Sn_CR_OPEN 0x01
-
-/**
- * @brief Wait connection request in TCP mode(Server mode)
- * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP).
- * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client
- * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.
- * When a �TCP clientconnection request is successfully established,
- * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes
- * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED.
- */
-#define Sn_CR_LISTEN 0x02
-
-/**
- * @brief Send connection request in TCP mode(Client mode)
- * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port).
- * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
- * The connect-request fails in the following three cases.\n
- * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n
- * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n
- * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client
- */
-#define Sn_CR_CONNECT 0x04
-
-/**
- * @brief Send closing request in TCP mode
- * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n
- * @par Active close
- * it transmits disconnect-request(FIN packet) to the connected peer\n
- * @par Passive close
- * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
- * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n
- * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_DISCON 0x08
-
-/**
- * @brief Close socket
- * @details Sn_SR is changed to @ref SOCK_CLOSED.
- */
-#define Sn_CR_CLOSE 0x10
-
-/**
- * @brief Update TX buffer pointer and send data
- * @details SEND transmits all the data in the Socket n TX buffer.\n
- * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n,
- * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD).
- */
-#define Sn_CR_SEND 0x20
-
-/**
- * @brief Send data with MAC address, so without ARP process
- * @details The basic operation is same as SEND.\n
- * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
- * But SEND_MAC transmits data without the automatic ARP-process.\n
- * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process.
- * @note Valid only in UDP mode.
- */
-#define Sn_CR_SEND_MAC 0x21
-
-/**
- * @brief Send keep alive message
- * @details It checks the connection status by sending 1byte keep-alive packet.\n
- * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_SEND_KEEP 0x22
-
-/**
- * @brief Update RX buffer pointer and receive data
- * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n
- * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR),
- * and Socket n RX Read Pointer Register (@ref Sn_RX_RD).
- */
-#define Sn_CR_RECV 0x40
-
-/* Sn_IR values */
-/**
- * @brief SEND_OK Interrupt
- * @details This is issued when SEND command is completed.
- */
-#define Sn_IR_SENDOK 0x10
-
-/**
- * @brief TIMEOUT Interrupt
- * @details This is issued when ARPTO or TCPTO occurs.
- */
-#define Sn_IR_TIMEOUT 0x08
-
-/**
- * @brief RECV Interrupt
- * @details This is issued whenever data is received from a peer.
- */
-#define Sn_IR_RECV 0x04
-
-/**
- * @brief DISCON Interrupt
- * @details This is issued when FIN or FIN/ACK packet is received from a peer.
- */
-#define Sn_IR_DISCON 0x02
-
-/**
- * @brief CON Interrupt
- * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED.
- */
-#define Sn_IR_CON 0x01
-
-/* Sn_SR values */
-/**
- * @brief Closed
- * @details This indicates that Socket n is released.\N
- * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status.
- */
-#define SOCK_CLOSED 0x00
-
-/**
- * @brief Initiate state
- * @details This indicates Socket n is opened with TCP mode.\N
- * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N
- * After @ref SOCK_INIT, user can use LISTEN /CONNECT command.
- */
-#define SOCK_INIT 0x13
-
-/**
- * @brief Listen state
- * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n
- * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n
- * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = .
- */
-#define SOCK_LISTEN 0x14
-
-/**
- * @brief Connection state
- * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
- * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n
- * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n
- * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred.
- */
-#define SOCK_SYNSENT 0x15
-
-/**
- * @brief Connection state
- * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
- * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n
- * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_SYNRECV 0x16
-
-/**
- * @brief Success to connect
- * @details This indicates the status of the connection of Socket n.\n
- * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or
- * when the CONNECT command is successful.\n
- * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
- */
-#define SOCK_ESTABLISHED 0x17
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_FIN_WAIT 0x18
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_CLOSING 0x1A
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_TIME_WAIT 0x1B
-
-/**
- * @brief Closing state
- * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
- * This is half-closing status, and data can be transferred.\n
- * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used.
- */
-#define SOCK_CLOSE_WAIT 0x1C
-
-/**
- * @brief Closing state
- * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
- * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_LAST_ACK 0x1D
-
-/**
- * @brief UDP socket
- * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n
- * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n
- * Unlike TCP mode, data can be transfered without the connection-process.
- */
-#define SOCK_UDP 0x22
-
-//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */
-
-/**
- * @brief MAC raw mode socket
- * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n
- * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n
- * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
- */
-#define SOCK_MACRAW 0x42
-
-//#define SOCK_PPPOE 0x5F
-
-/* IP PROTOCOL */
-#define IPPROTO_IP 0 //< Dummy for IP
-#define IPPROTO_ICMP 1 //< Control message protocol
-#define IPPROTO_IGMP 2 //< Internet group management protocol
-#define IPPROTO_GGP 3 //< Gateway^2 (deprecated)
-#define IPPROTO_TCP 6 //< TCP
-#define IPPROTO_PUP 12 //< PUP
-#define IPPROTO_UDP 17 //< UDP
-#define IPPROTO_IDP 22 //< XNS idp
-#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol
-#define IPPROTO_RAW 255 //< Raw IP packet
-
-
-/**
- * @brief Enter a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n \n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * \sa WIZCHIP_CRITICAL_EXIT()
- */
-#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter()
-
-/**
- * @brief Exit a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n\n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * @sa WIZCHIP_CRITICAL_ENTER()
- */
-#ifdef _exit
-#undef _exit
-#endif
-#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit()
-
-
-
-////////////////////////
-// Basic I/O Function //
-////////////////////////
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads 1 byte value from a register.
- * @param AddrSel Register address
- * @return The value of register
- */
-uint8_t WIZCHIP_READ (uint32_t AddrSel);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes 1 byte value to a register.
- * @param AddrSel Register address
- * @param wb Write data
- * @return void
- */
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads sequence data from registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to read data
- * @param len Data length
- */
-void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes sequence data to registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to write data
- * @param len Data length
- */
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/////////////////////////////////
-// Common Register I/O function //
-/////////////////////////////////
-/**
- * @ingroup Common_register_access_function
- * @brief Set Mode Register
- * @param (uint8_t)mr The value to be set.
- * @sa getMR()
- */
-#define setMR(mr) \
- WIZCHIP_WRITE(MR,mr)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get Mode Register
- * @return uint8_t. The value of Mode register.
- * @sa setMR()
- */
-#define getMR() \
- WIZCHIP_READ(MR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set gateway IP address
- * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
- * @sa getGAR()
- */
-#define setGAR(gar) \
- WIZCHIP_WRITE_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get gateway IP address
- * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
- * @sa setGAR()
- */
-#define getGAR(gar) \
- WIZCHIP_READ_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set subnet mask address
- * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
- * @sa getSUBR()
- */
-#define setSUBR(subr) \
- WIZCHIP_WRITE_BUF(SUBR, subr,4)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get subnet mask address
- * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
- * @sa setSUBR()
- */
-#define getSUBR(subr) \
- WIZCHIP_READ_BUF(SUBR, subr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local MAC address
- * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
- * @sa getSHAR()
- */
-#define setSHAR(shar) \
- WIZCHIP_WRITE_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local MAC address
- * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
- * @sa setSHAR()
- */
-#define getSHAR(shar) \
- WIZCHIP_READ_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local IP address
- * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
- * @sa getSIPR()
- */
-#define setSIPR(sipr) \
- WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
- * @sa setSIPR()
- */
-#define getSIPR(sipr) \
- WIZCHIP_READ_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set INTLEVEL register
- * @param (uint16_t)intlevel Value to set @ref INTLEVEL register.
- * @sa getINTLEVEL()
- */
-#define setINTLEVEL(intlevel) {\
- WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \
- }
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get INTLEVEL register
- * @return uint16_t. Value of @ref INTLEVEL register.
- * @sa setINTLEVEL()
- */
-#define getINTLEVEL() \
- ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IR register
- * @param (uint8_t)ir Value to set @ref IR register.
- * @sa getIR()
- */
-#define setIR(ir) \
- WIZCHIP_WRITE(IR, (ir & 0xF0))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IR register
- * @return uint8_t. Value of @ref IR register.
- * @sa setIR()
- */
-#define getIR() \
- (WIZCHIP_READ(IR) & 0xF0)
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IMR register
- * @param (uint8_t)imr Value to set @ref IMR register.
- * @sa getIMR()
- */
-#define setIMR(imr) \
- WIZCHIP_WRITE(IMR, imr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IMR register
- * @return uint8_t. Value of @ref IMR register.
- * @sa setIMR()
- */
-#define getIMR() \
- WIZCHIP_READ(IMR)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIR register
- * @param (uint8_t)sir Value to set @ref SIR register.
- * @sa getSIR()
- */
-#define setSIR(sir) \
- WIZCHIP_WRITE(SIR, sir)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIR register
- * @return uint8_t. Value of @ref SIR register.
- * @sa setSIR()
- */
-#define getSIR() \
- WIZCHIP_READ(SIR)
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIMR register
- * @param (uint8_t)simr Value to set @ref SIMR register.
- * @sa getSIMR()
- */
-#define setSIMR(simr) \
- WIZCHIP_WRITE(SIMR, simr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIMR register
- * @return uint8_t. Value of @ref SIMR register.
- * @sa setSIMR()
- */
-#define getSIMR() \
- WIZCHIP_READ(SIMR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RTR register
- * @param (uint16_t)rtr Value to set @ref RTR register.
- * @sa getRTR()
- */
-#define setRTR(rtr) {\
- WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RTR,1), (uint8_t) rtr); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RTR register
- * @return uint16_t. Value of @ref RTR register.
- * @sa setRTR()
- */
-#define getRTR() \
- ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(RTR,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RCR register
- * @param (uint8_t)rcr Value to set @ref RCR register.
- * @sa getRCR()
- */
-#define setRCR(rcr) \
- WIZCHIP_WRITE(RCR, rcr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RCR register
- * @return uint8_t. Value of @ref RCR register.
- * @sa setRCR()
- */
-#define getRCR() \
- WIZCHIP_READ(RCR)
-
-//================================================== test done ===========================================================
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PTIMER register
- * @param (uint8_t)ptimer Value to set @ref PTIMER register.
- * @sa getPTIMER()
- */
-#define setPTIMER(ptimer) \
- WIZCHIP_WRITE(PTIMER, ptimer)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PTIMER register
- * @return uint8_t. Value of @ref PTIMER register.
- * @sa setPTIMER()
- */
-#define getPTIMER() \
- WIZCHIP_READ(PTIMER)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMAGIC register
- * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
- * @sa getPMAGIC()
- */
-#define setPMAGIC(pmagic) \
- WIZCHIP_WRITE(PMAGIC, pmagic)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMAGIC register
- * @return uint8_t. Value of @ref PMAGIC register.
- * @sa setPMAGIC()
- */
-#define getPMAGIC() \
- WIZCHIP_READ(PMAGIC)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set PHAR address
- * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa getPHAR()
- */
-#define setPHAR(phar) \
- WIZCHIP_WRITE_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa setPHAR()
- */
-#define getPHAR(phar) \
- WIZCHIP_READ_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PSID register
- * @param (uint16_t)psid Value to set @ref PSID register.
- * @sa getPSID()
- */
-#define setPSID(psid) {\
- WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PSID register
- * @return uint16_t. Value of @ref PSID register.
- * @sa setPSID()
- */
-//uint16_t getPSID(void);
-#define getPSID() \
- ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMRU register
- * @param (uint16_t)pmru Value to set @ref PMRU register.
- * @sa getPMRU()
- */
-#define setPMRU(pmru) { \
- WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMRU register
- * @return uint16_t. Value of @ref PMRU register.
- * @sa setPMRU()
- */
-#define getPMRU() \
- ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get unreachable IP address
- * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes.
- */
-#define getUIPR(uipr) \
- WIZCHIP_READ_BUF(UIPR,uipr,6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref UPORTR register
- * @return uint16_t. Value of @ref UPORTR register.
- */
-#define getUPORTR() \
- ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PHYCFGR register
- * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register.
- * @sa getPHYCFGR()
- */
-#define setPHYCFGR(phycfgr) \
- WIZCHIP_WRITE(PHYCFGR, phycfgr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PHYCFGR register
- * @return uint8_t. Value of @ref PHYCFGR register.
- * @sa setPHYCFGR()
- */
-#define getPHYCFGR() \
- WIZCHIP_READ(PHYCFGR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref VERSIONR register
- * @return uint8_t. Value of @ref VERSIONR register.
- */
-#define getVERSIONR() \
- WIZCHIP_READ(VERSIONR)
-
-/////////////////////////////////////
-
-///////////////////////////////////
-// Socket N register I/O function //
-///////////////////////////////////
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)mr Value to set @ref Sn_MR
- * @sa getSn_MR()
- */
-#define setSn_MR(sn, mr) \
- WIZCHIP_WRITE(Sn_MR(sn),mr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_MR.
- * @sa setSn_MR()
- */
-#define getSn_MR(sn) \
- WIZCHIP_READ(Sn_MR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)cr Value to set @ref Sn_CR
- * @sa getSn_CR()
- */
-#define setSn_CR(sn, cr) \
- WIZCHIP_WRITE(Sn_CR(sn), cr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_CR.
- * @sa setSn_CR()
- */
-#define getSn_CR(sn) \
- WIZCHIP_READ(Sn_CR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ir Value to set @ref Sn_IR
- * @sa getSn_IR()
- */
-#define setSn_IR(sn, ir) \
- WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IR.
- * @sa setSn_IR()
- */
-#define getSn_IR(sn) \
- (WIZCHIP_READ(Sn_IR(sn)) & 0x1F)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)imr Value to set @ref Sn_IMR
- * @sa getSn_IMR()
- */
-#define setSn_IMR(sn, imr) \
- WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IMR.
- * @sa setSn_IMR()
- */
-#define getSn_IMR(sn) \
- (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_SR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_SR.
- */
-#define getSn_SR(sn) \
- WIZCHIP_READ(Sn_SR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)port Value to set @ref Sn_PORT.
- * @sa getSn_PORT()
- */
-#define setSn_PORT(sn, port) { \
- WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_PORT.
- * @sa setSn_PORT()
- */
-#define getSn_PORT(sn) \
- ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DHAR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
- * @sa getSn_DHAR()
- */
-#define setSn_DHAR(sn, dhar) \
- WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
- * @sa setSn_DHAR()
- */
-#define getSn_DHAR(sn, dhar) \
- WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
- * @sa getSn_DIPR()
- */
-#define setSn_DIPR(sn, dipr) \
- WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
- * @sa SetSn_DIPR()
- */
-#define getSn_DIPR(sn, dipr) \
- WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)dport Value to set @ref Sn_DPORT
- * @sa getSn_DPORT()
- */
-#define setSn_DPORT(sn, dport) { \
- WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_DPORT.
- * @sa setSn_DPORT()
- */
-#define getSn_DPORT(sn) \
- ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)mss Value to set @ref Sn_MSSR
- * @sa setSn_MSSR()
- */
-#define setSn_MSSR(sn, mss) { \
- WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_MSSR.
- * @sa setSn_MSSR()
- */
-#define getSn_MSSR(sn) \
- ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)tos Value to set @ref Sn_TOS
- * @sa getSn_TOS()
- */
-#define setSn_TOS(sn, tos) \
- WIZCHIP_WRITE(Sn_TOS(sn), tos)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of Sn_TOS.
- * @sa setSn_TOS()
- */
-#define getSn_TOS(sn) \
- WIZCHIP_READ(Sn_TOS(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ttl Value to set @ref Sn_TTL
- * @sa getSn_TTL()
- */
-#define setSn_TTL(sn, ttl) \
- WIZCHIP_WRITE(Sn_TTL(sn), ttl)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TTL.
- * @sa setSn_TTL()
- */
-#define getSn_TTL(sn) \
- WIZCHIP_READ(Sn_TTL(sn))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE
- * @sa getSn_RXBUF_SIZE()
- */
-#define setSn_RXBUF_SIZE(sn, rxbufsize) \
- WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_RXBUF_SIZE.
- * @sa setSn_RXBUF_SIZE()
- */
-#define getSn_RXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_RXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE
- * @sa getSn_TXBUF_SIZE()
- */
-#define setSn_TXBUF_SIZE(sn, txbufsize) \
- WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TXBUF_SIZE.
- * @sa setSn_TXBUF_SIZE()
- */
-#define getSn_TXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_TXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_FSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_FSR.
- */
-uint16_t getSn_TX_FSR(uint8_t sn);
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_RD.
- */
-#define getSn_TX_RD(sn) \
- ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
- * @sa GetSn_TX_WR()
- */
-#define setSn_TX_WR(sn, txwr) { \
- WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_WR.
- * @sa setSn_TX_WR()
- */
-#define getSn_TX_WR(sn) \
- ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_RSR.
- */
-uint16_t getSn_RX_RSR(uint8_t sn);
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
- * @sa getSn_RX_RD()
- */
-#define setSn_RX_RD(sn, rxrd) { \
- WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @regurn uint16_t. Value of @ref Sn_RX_RD.
- * @sa setSn_RX_RD()
- */
-#define getSn_RX_RD(sn) \
- ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_WR.
- */
-#define getSn_RX_WR(sn) \
- ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)frag Value to set @ref Sn_FRAG
- * @sa getSn_FRAD()
- */
-#define setSn_FRAG(sn, frag) { \
- WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_FRAG.
- * @sa setSn_FRAG()
- */
-#define getSn_FRAG(sn) \
- ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR
- * @sa getSn_KPALVTR()
- */
-#define setSn_KPALVTR(sn, kpalvt) \
- WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_KPALVTR.
- * @sa setSn_KPALVTR()
- */
-#define getSn_KPALVTR(sn) \
- WIZCHIP_READ(Sn_KPALVTR(sn))
-
-//////////////////////////////////////
-
-/////////////////////////////////////
-// Sn_TXBUF & Sn_RXBUF IO function //
-/////////////////////////////////////
-/**
- * @brief Gets the max buffer size of socket sn passed as parameter.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n RX max buffer size.
- */
-#define getSn_RxMAX(sn) \
- (getSn_RXBUF_SIZE(sn) << 10)
-
-/**
- * @brief Gets the max buffer size of socket sn passed as parameters.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n TX max buffer size.
- */
-//uint16_t getSn_TxMAX(uint8_t sn);
-#define getSn_TxMAX(sn) \
- (getSn_TXBUF_SIZE(sn) << 10)
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to internal TX memory
- *
- * @details This function reads the Tx write pointer register and after that,
- * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory
- * and updates the Tx write pointer register.
- * This function is being called by send() and sendto() function also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to write data
- * @param len Data length
- * @sa wiz_recv_data()
- */
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to your buffer from internal RX memory
- *
- * @details This function read the Rx read pointer register and after that,
- * it copies the received data from internal RX memory
- * to wizdata(pointer variable) of the length of len(variable) bytes.
- * This function is being called by recv() also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to read data
- * @param len Data length
- * @sa wiz_send_data()
- */
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It discard the received data in RX memory.
- * @details It discards the data of the length of len(variable) bytes in internal RX memory.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param len Data length
- */
-void wiz_recv_ignore(uint8_t sn, uint16_t len);
-
-#endif // _W5500_H_
diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.c b/drivers/wiznet5k/ethernet/wizchip_conf.c
deleted file mode 100644
index 3e54d2c90bcd2..0000000000000
--- a/drivers/wiznet5k/ethernet/wizchip_conf.c
+++ /dev/null
@@ -1,662 +0,0 @@
-//****************************************************************************/
-//!
-//! \file wizchip_conf.c
-//! \brief WIZCHIP Config Header File.
-//! \version 1.0.1
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.1 Refer to M20140501
-//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte()
-// Issued by Mathias ClauBen.
-//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t*
-//! For remove the warning when pointer type size is not 32bit.
-//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type.
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************/
-//A20140501 : for use the type - ptrdiff_t
-#include
-//
-
-#include "wizchip_conf.h"
-#include "socket.h"
-
-/**
- * @brief Default function to enable interrupt.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cris_enter(void) {};
-/**
- * @brief Default function to disable interrupt.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cris_exit(void) {};
-/**
- * @brief Default function to select chip.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cs_select(void) {};
-/**
- * @brief Default function to deselect chip.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cs_deselect(void) {};
-/**
- * @brief Default function to read in direct or indirect interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
- //M20140501 : Explict pointer type casting
-//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); };
-uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); };
-/**
- * @brief Default function to write in direct or indirect interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-
-//M20140501 : Explict pointer type casting
-//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; };
-void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; };
-
-/**
- * @brief Default function to read in SPI interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {}
-/**
- * @brief Default function to write in SPI interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {}
-
-/**
- * @\ref _WIZCHIP instance
- */
-_WIZCHIP WIZCHIP =
- {
- .id = _WIZCHIP_ID_,
- .if_mode = _WIZCHIP_IO_MODE_,
- .CRIS._enter = wizchip_cris_enter,
- .CRIS._exit = wizchip_cris_exit,
- .CS._select = wizchip_cs_select,
- .CS._deselect = wizchip_cs_deselect,
- .IF.BUS._read_byte = wizchip_bus_readbyte,
- .IF.BUS._write_byte = wizchip_bus_writebyte
-// .IF.SPI._read_byte = wizchip_spi_readbyte,
-// .IF.SPI._write_byte = wizchip_spi_writebyte
- };
-
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
-static uint8_t _SUBN_[4]; // subnet
-#endif
-static uint8_t _DNS_[4]; // DNS server ip address
-static dhcp_mode _DHCP_; // DHCP mode
-
-void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
-{
- if(!cris_en || !cris_ex)
- {
- WIZCHIP.CRIS._enter = wizchip_cris_enter;
- WIZCHIP.CRIS._exit = wizchip_cris_exit;
- }
- else
- {
- WIZCHIP.CRIS._enter = cris_en;
- WIZCHIP.CRIS._exit = cris_ex;
- }
-}
-
-void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
-{
- if(!cs_sel || !cs_desel)
- {
- WIZCHIP.CS._select = wizchip_cs_select;
- WIZCHIP.CS._deselect = wizchip_cs_deselect;
- }
- else
- {
- WIZCHIP.CS._select = cs_sel;
- WIZCHIP.CS._deselect = cs_desel;
- }
-}
-
-void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb))
-{
- while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_));
-
- if(!bus_rb || !bus_wb)
- {
- WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte;
- WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte;
- }
- else
- {
- WIZCHIP.IF.BUS._read_byte = bus_rb;
- WIZCHIP.IF.BUS._write_byte = bus_wb;
- }
-}
-
-void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t))
-{
- while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
-
- if(!spi_rb || !spi_wb)
- {
- WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes;
- WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes;
- }
- else
- {
- WIZCHIP.IF.SPI._read_bytes = spi_rb;
- WIZCHIP.IF.SPI._write_bytes = spi_wb;
- }
-}
-
-int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg)
-{
- uint8_t tmp = 0;
- uint8_t* ptmp[2] = {0,0};
- switch(cwtype)
- {
- case CW_RESET_WIZCHIP:
- wizchip_sw_reset();
- break;
- case CW_INIT_WIZCHIP:
- if(arg != 0)
- {
- ptmp[0] = (uint8_t*)arg;
- ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
- }
- return wizchip_init(ptmp[0], ptmp[1]);
- case CW_CLR_INTERRUPT:
- wizchip_clrinterrupt(*((intr_kind*)arg));
- break;
- case CW_GET_INTERRUPT:
- *((intr_kind*)arg) = wizchip_getinterrupt();
- break;
- case CW_SET_INTRMASK:
- wizchip_setinterruptmask(*((intr_kind*)arg));
- break;
- case CW_GET_INTRMASK:
- *((intr_kind*)arg) = wizchip_getinterruptmask();
- break;
- #if _WIZCHIP_ > 5100
- case CW_SET_INTRTIME:
- setINTLEVEL(*(uint16_t*)arg);
- break;
- case CW_GET_INTRTIME:
- *(uint16_t*)arg = getINTLEVEL();
- break;
- #endif
- case CW_GET_ID:
- ((uint8_t*)arg)[0] = WIZCHIP.id[0];
- ((uint8_t*)arg)[1] = WIZCHIP.id[1];
- ((uint8_t*)arg)[2] = WIZCHIP.id[2];
- ((uint8_t*)arg)[3] = WIZCHIP.id[3];
- ((uint8_t*)arg)[4] = WIZCHIP.id[4];
- ((uint8_t*)arg)[5] = 0;
- break;
- #if _WIZCHIP_ == 5500
- case CW_RESET_PHY:
- wizphy_reset();
- break;
- case CW_SET_PHYCONF:
- wizphy_setphyconf((wiz_PhyConf*)arg);
- break;
- case CW_GET_PHYCONF:
- wizphy_getphyconf((wiz_PhyConf*)arg);
- break;
- case CW_GET_PHYSTATUS:
- break;
- case CW_SET_PHYPOWMODE:
- return wizphy_setphypmode(*(uint8_t*)arg);
- #endif
- case CW_GET_PHYPOWMODE:
- tmp = wizphy_getphypmode();
- if((int8_t)tmp == -1) return -1;
- *(uint8_t*)arg = tmp;
- break;
- case CW_GET_PHYLINK:
- tmp = wizphy_getphylink();
- if((int8_t)tmp == -1) return -1;
- *(uint8_t*)arg = tmp;
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-
-int8_t ctlnetwork(ctlnetwork_type cntype, void* arg)
-{
-
- switch(cntype)
- {
- case CN_SET_NETINFO:
- wizchip_setnetinfo((wiz_NetInfo*)arg);
- break;
- case CN_GET_NETINFO:
- wizchip_getnetinfo((wiz_NetInfo*)arg);
- break;
- case CN_SET_NETMODE:
- return wizchip_setnetmode(*(netmode_type*)arg);
- case CN_GET_NETMODE:
- *(netmode_type*)arg = wizchip_getnetmode();
- break;
- case CN_SET_TIMEOUT:
- wizchip_settimeout((wiz_NetTimeout*)arg);
- break;
- case CN_GET_TIMEOUT:
- wizchip_gettimeout((wiz_NetTimeout*)arg);
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-void wizchip_sw_reset(void)
-{
- uint8_t gw[4], sn[4], sip[4];
- uint8_t mac[6];
- getSHAR(mac);
- getGAR(gw); getSUBR(sn); getSIPR(sip);
- setMR(MR_RST);
- getMR(); // for delay
- setSHAR(mac);
- setGAR(gw);
- setSUBR(sn);
- setSIPR(sip);
-}
-
-int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
-{
- int8_t i;
- int8_t tmp = 0;
- wizchip_sw_reset();
- if(txsize)
- {
- tmp = 0;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- tmp += txsize[i];
- if(tmp > 16) return -1;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- setSn_TXBUF_SIZE(i, txsize[i]);
- }
- if(rxsize)
- {
- tmp = 0;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- tmp += rxsize[i];
- if(tmp > 16) return -1;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- setSn_RXBUF_SIZE(i, rxsize[i]);
- }
-
- WIZCHIP_EXPORT(socket_reset)();
-
- return 0;
-}
-
-void wizchip_clrinterrupt(intr_kind intr)
-{
- uint8_t ir = (uint8_t)intr;
- uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
-#if _WIZCHIP_ < 5500
- ir |= (1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- ir |= (1 << 6);
-#endif
-
-#if _WIZCHIP_ < 5200
- sir &= 0x0F;
-#endif
-
-#if _WIZCHIP_ == 5100
- ir |= sir;
- setIR(ir);
-#else
- setIR(ir);
- setSIR(sir);
-#endif
-}
-
-intr_kind wizchip_getinterrupt(void)
-{
- uint8_t ir = 0;
- uint8_t sir = 0;
- uint16_t ret = 0;
-#if _WIZCHIP_ == 5100
- ir = getIR();
- sir = ir 0x0F;
-#else
- ir = getIR();
- sir = getSIR();
-#endif
-
-#if _WIZCHIP_ < 5500
- ir &= ~(1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- ir &= ~(1 << 6);
-#endif
- ret = sir;
- ret = (ret << 8) + ir;
- return (intr_kind)ret;
-}
-
-void wizchip_setinterruptmask(intr_kind intr)
-{
- uint8_t imr = (uint8_t)intr;
- uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
-#if _WIZCHIP_ < 5500
- imr &= ~(1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- imr &= ~(1 << 6);
-#endif
-
-#if _WIZCHIP_ < 5200
- simr &= 0x0F;
-#endif
-
-#if _WIZCHIP_ == 5100
- imr |= simr;
- setIMR(imr);
-#else
- setIMR(imr);
- setSIMR(simr);
-#endif
-}
-
-intr_kind wizchip_getinterruptmask(void)
-{
- uint8_t imr = 0;
- uint8_t simr = 0;
- uint16_t ret = 0;
-#if _WIZCHIP_ == 5100
- imr = getIMR();
- simr = imr 0x0F;
-#else
- imr = getIMR();
- simr = getSIMR();
-#endif
-
-#if _WIZCHIP_ < 5500
- imr &= ~(1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- imr &= ~(1 << 6); // IK_DEST_UNREACH
-#endif
- ret = simr;
- ret = (ret << 8) + imr;
- return (intr_kind)ret;
-}
-
-int8_t wizphy_getphylink(void)
-{
- int8_t tmp;
-#if _WIZCHIP_ == 5200
- if(getPHYSTATUS() & PHYSTATUS_LINK)
- tmp = PHY_LINK_ON;
- else
- tmp = PHY_LINK_OFF;
-#elif _WIZCHIP_ == 5500
- if(getPHYCFGR() & PHYCFGR_LNK_ON)
- tmp = PHY_LINK_ON;
- else
- tmp = PHY_LINK_OFF;
-#else
- tmp = -1;
-#endif
- return tmp;
-}
-
-#if _WIZCHIP_ > 5100
-
-int8_t wizphy_getphypmode(void)
-{
- int8_t tmp = 0;
- #if _WIZCHIP_ == 5200
- if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
- tmp = PHY_POWER_DOWN;
- else
- tmp = PHY_POWER_NORM;
- #elif _WIZCHIP_ == 5500
- if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN)
- tmp = PHY_POWER_DOWN;
- else
- tmp = PHY_POWER_NORM;
- #else
- tmp = -1;
- #endif
- return tmp;
-}
-#endif
-
-#if _WIZCHIP_ == 5500
-void wizphy_reset(void)
-{
- uint8_t tmp = getPHYCFGR();
- tmp &= PHYCFGR_RST;
- setPHYCFGR(tmp);
- tmp = getPHYCFGR();
- tmp |= ~PHYCFGR_RST;
- setPHYCFGR(tmp);
-}
-
-void wizphy_setphyconf(wiz_PhyConf* phyconf)
-{
- uint8_t tmp = 0;
- if(phyconf->by == PHY_CONFBY_SW)
- tmp |= PHYCFGR_OPMD;
- else
- tmp &= ~PHYCFGR_OPMD;
- if(phyconf->mode == PHY_MODE_AUTONEGO)
- tmp |= PHYCFGR_OPMDC_ALLA;
- else
- {
- if(phyconf->duplex == PHY_DUPLEX_FULL)
- {
- if(phyconf->speed == PHY_SPEED_100)
- tmp |= PHYCFGR_OPMDC_100F;
- else
- tmp |= PHYCFGR_OPMDC_10F;
- }
- else
- {
- if(phyconf->speed == PHY_SPEED_100)
- tmp |= PHYCFGR_OPMDC_100H;
- else
- tmp |= PHYCFGR_OPMDC_10H;
- }
- }
- setPHYCFGR(tmp);
- wizphy_reset();
-}
-
-void wizphy_getphyconf(wiz_PhyConf* phyconf)
-{
- uint8_t tmp = 0;
- tmp = getPHYCFGR();
- phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
- switch(tmp & PHYCFGR_OPMDC_ALLA)
- {
- case PHYCFGR_OPMDC_ALLA:
- case PHYCFGR_OPMDC_100FA:
- phyconf->mode = PHY_MODE_AUTONEGO;
- break;
- default:
- phyconf->mode = PHY_MODE_MANUAL;
- break;
- }
- switch(tmp & PHYCFGR_OPMDC_ALLA)
- {
- case PHYCFGR_OPMDC_100FA:
- case PHYCFGR_OPMDC_100F:
- case PHYCFGR_OPMDC_100H:
- phyconf->speed = PHY_SPEED_100;
- break;
- default:
- phyconf->speed = PHY_SPEED_10;
- break;
- }
- switch(tmp & PHYCFGR_OPMDC_ALLA)
- {
- case PHYCFGR_OPMDC_100FA:
- case PHYCFGR_OPMDC_100F:
- case PHYCFGR_OPMDC_10F:
- phyconf->duplex = PHY_DUPLEX_FULL;
- break;
- default:
- phyconf->duplex = PHY_DUPLEX_HALF;
- break;
- }
-}
-
-void wizphy_getphystat(wiz_PhyConf* phyconf)
-{
- uint8_t tmp = getPHYCFGR();
- phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
- phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
-}
-
-int8_t wizphy_setphypmode(uint8_t pmode)
-{
- uint8_t tmp = 0;
- tmp = getPHYCFGR();
- if((tmp & PHYCFGR_OPMD)== 0) return -1;
- tmp &= ~PHYCFGR_OPMDC_ALLA;
- if( pmode == PHY_POWER_DOWN)
- tmp |= PHYCFGR_OPMDC_PDOWN;
- else
- tmp |= PHYCFGR_OPMDC_ALLA;
- setPHYCFGR(tmp);
- wizphy_reset();
- tmp = getPHYCFGR();
- if( pmode == PHY_POWER_DOWN)
- {
- if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
- }
- else
- {
- if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
- }
- return -1;
-}
-#endif
-
-
-void wizchip_setnetinfo(wiz_NetInfo* pnetinfo)
-{
- setSHAR(pnetinfo->mac);
- setGAR(pnetinfo->gw);
- setSUBR(pnetinfo->sn);
- setSIPR(pnetinfo->ip);
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
- _SUBN_[0] = pnetinfo->sn[0];
- _SUBN_[1] = pnetinfo->sn[1];
- _SUBN_[2] = pnetinfo->sn[2];
- _SUBN_[3] = pnetinfo->sn[3];
-#endif
- _DNS_[0] = pnetinfo->dns[0];
- _DNS_[1] = pnetinfo->dns[1];
- _DNS_[2] = pnetinfo->dns[2];
- _DNS_[3] = pnetinfo->dns[3];
- _DHCP_ = pnetinfo->dhcp;
-}
-
-void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
-{
- getSHAR(pnetinfo->mac);
- getGAR(pnetinfo->gw);
- getSUBR(pnetinfo->sn);
- getSIPR(pnetinfo->ip);
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
- pnetinfo->sn[0] = _SUBN_[0];
- pnetinfo->sn[1] = _SUBN_[1];
- pnetinfo->sn[2] = _SUBN_[2];
- pnetinfo->sn[3] = _SUBN_[3];
-#endif
- pnetinfo->dns[0]= _DNS_[0];
- pnetinfo->dns[1]= _DNS_[1];
- pnetinfo->dns[2]= _DNS_[2];
- pnetinfo->dns[3]= _DNS_[3];
- pnetinfo->dhcp = _DHCP_;
-}
-
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
-uint8_t *wizchip_getsubn(void) {
- return _SUBN_;
-}
-#endif
-
-int8_t wizchip_setnetmode(netmode_type netmode)
-{
- uint8_t tmp = 0;
-#if _WIZCHIP_ != 5500
- if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
-#else
- if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
-#endif
- tmp = getMR();
- tmp |= (uint8_t)netmode;
- setMR(tmp);
- return 0;
-}
-
-netmode_type wizchip_getnetmode(void)
-{
- return (netmode_type) getMR();
-}
-
-void wizchip_settimeout(wiz_NetTimeout* nettime)
-{
- setRCR(nettime->retry_cnt);
- setRTR(nettime->time_100us);
-}
-
-void wizchip_gettimeout(wiz_NetTimeout* nettime)
-{
- nettime->retry_cnt = getRCR();
- nettime->time_100us = getRTR();
-}
diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.h b/drivers/wiznet5k/ethernet/wizchip_conf.h
deleted file mode 100644
index 4a7a7bd691400..0000000000000
--- a/drivers/wiznet5k/ethernet/wizchip_conf.h
+++ /dev/null
@@ -1,554 +0,0 @@
-//*****************************************************************************
-//
-//! \file wizchip_conf.h
-//! \brief WIZCHIP Config Header File.
-//! \version 1.0.0
-//! \date 2013/10/21
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************
-
-/**
- * @defgroup extra_functions 2. WIZnet Extra Functions
- *
- * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions.
- * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n
- *
- */
-
-#ifndef _WIZCHIP_CONF_H_
-#define _WIZCHIP_CONF_H_
-
-#include
-/**
- * @brief Select WIZCHIP.
- * @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n
- * ex> #define \_WIZCHIP_ 5500
- */
-#ifndef _WIZCHIP_
-#define _WIZCHIP_ 5200 // 5100, 5200, 5500
-#endif
-
-#define _WIZCHIP_IO_MODE_NONE_ 0x0000
-#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */
-#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */
-//#define _WIZCHIP_IO_MODE_IIC_ 0x0400
-//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800
-// Add to
-//
-
-#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */
-#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */
-
-#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/
-#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/
-
-
-#if (_WIZCHIP_ == 5100)
- #define _WIZCHIP_ID_ "W5100\0"
-/**
- * @brief Define interface mode.
- * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
- */
-
-// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_
-// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
- #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
-
-#elif (_WIZCHIP_ == 5200)
- #define _WIZCHIP_ID_ "W5200\0"
-/**
- * @brief Define interface mode.
- * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
- */
-// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
- #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
- #include "w5200/w5200.h"
-#elif (_WIZCHIP_ == 5500)
- #define _WIZCHIP_ID_ "W5500\0"
-
-/**
- * @brief Define interface mode. \n
- * @todo Should select interface mode as chip.
- * - @ref \_WIZCHIP_IO_MODE_SPI_ \n
- * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
- * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
- * - @ref \_WIZCHIP_IO_MODE_BUS_ \n
- * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n
- * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n
- * - Others will be defined in future. \n\n
- * ex> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_
- *
- */
- //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_
- #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_
- #include "w5500/w5500.h"
-#else
- #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!"
-#endif
-
-#ifndef _WIZCHIP_IO_MODE_
- #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!"
-#endif
-
-/**
- * @brief Define I/O base address when BUS IF mode.
- * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_,
- * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n
- * ex> #define \_WIZCHIP_IO_BASE_ 0x00008000
- */
-#define _WIZCHIP_IO_BASE_ 0x00000000 //
-
-#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS
- #ifndef _WIZCHIP_IO_BASE_
- #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map."
- #endif
-#endif
-
-#if _WIZCHIP_ > 5100
- #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP
-#else
- #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP
-#endif
-
-
-/********************************************************
-* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC.
-*********************************************************/
-/**
- * @ingroup DATA_TYPE
- * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200
- */
-typedef struct __WIZCHIP
-{
- uint16_t if_mode; ///< host interface mode
- uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on.
- /**
- * The set of critical section callback func.
- */
- struct _CRIS
- {
- void (*_enter) (void); ///< crtical section enter
- void (*_exit) (void); ///< critial section exit
- }CRIS;
- /**
- * The set of @ref\_WIZCHIP_ select control callback func.
- */
- struct _CS
- {
- void (*_select) (void); ///< @ref \_WIZCHIP_ selected
- void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected
- }CS;
- /**
- * The set of interface IO callback func.
- */
- union _IF
- {
- /**
- * For BUS interface IO
- */
- struct
- {
- uint8_t (*_read_byte) (uint32_t AddrSel);
- void (*_write_byte) (uint32_t AddrSel, uint8_t wb);
- }BUS;
- /**
- * For SPI interface IO
- */
- struct
- {
- void (*_read_bytes) (uint8_t *buf, uint32_t len);
- void (*_write_bytes) (const uint8_t *buf, uint32_t len);
- }SPI;
- // To be added
- //
- }IF;
-}_WIZCHIP;
-
-extern _WIZCHIP WIZCHIP;
-
-/**
- * @ingroup DATA_TYPE
- * WIZCHIP control type enumration used in @ref ctlwizchip().
- */
-typedef enum
-{
- CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly
- CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t.
- CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP
- CW_CLR_INTERRUPT, ///< Clears interrupt
- CW_SET_INTRMASK, ///< Masks interrupt
- CW_GET_INTRMASK, ///< Get interrupt mask
- CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt.
- CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt.
- CW_GET_ID, ///< Gets WIZCHIP name.
-
-#if _WIZCHIP_ == 5500
- CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000
- CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000
- CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000
- CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000
- CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000
-#endif
- CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal
- CW_GET_PHYLINK ///< Get PHY Link status
-}ctlwizchip_type;
-
-/**
- * @ingroup DATA_TYPE
- * Network control type enumration used in @ref ctlnetwork().
- */
-typedef enum
-{
- CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo
- CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo
- CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode
- CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode
- CN_SET_TIMEOUT, ///< Set network timeout as retry count and time.
- CN_GET_TIMEOUT, ///< Get network timeout as retry count and time.
-}ctlnetwork_type;
-
-/**
- * @ingroup DATA_TYPE
- * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK
- * and CW_GET_INTRMASK is used in @ref ctlnetwork().
- * It can be used with OR operation.
- */
-typedef enum
-{
-#if _WIZCHIP_ > 5200
- IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500.
-#endif
-
- IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected
-
-#if _WIZCHIP_ != 5200
- IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200
-#endif
-
- IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred
-
- IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt
- IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt
- IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt
- IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt
-#if _WIZCHIP_ > 5100
- IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100
- IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100
- IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100
- IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100
-#endif
-
-#if _WIZCHIP_ > 5100
- IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt
-#else
- IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt
-#endif
-}intr_kind;
-
-#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin
-#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register
-#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting.
-#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation
-#define PHY_SPEED_10 0 ///< Link Speed 10
-#define PHY_SPEED_100 1 ///< Link Speed 100
-#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex
-#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex
-#define PHY_LINK_OFF 0 ///< Link Off
-#define PHY_LINK_ON 1 ///< Link On
-#define PHY_POWER_NORM 0 ///< PHY power normal mode
-#define PHY_POWER_DOWN 1 ///< PHY power down mode
-
-
-#if _WIZCHIP_ == 5500
-/**
- * @ingroup DATA_TYPE
- * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500,
- * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n
- * Valid only in W5500.
- */
-typedef struct wiz_PhyConf_t
-{
- uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW
- uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO
- uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100
- uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL
- //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN
- //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF
- }wiz_PhyConf;
-#endif
-
-/**
- * @ingroup DATA_TYPE
- * It used in setting dhcp_mode of @ref wiz_NetInfo.
- */
-typedef enum
-{
- NETINFO_STATIC = 1, ///< Static IP configuration by manually.
- NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever
-}dhcp_mode;
-
-/**
- * @ingroup DATA_TYPE
- * Network Information for WIZCHIP
- */
-typedef struct wiz_NetInfo_t
-{
- uint8_t mac[6]; ///< Source Mac Address
- uint8_t ip[4]; ///< Source IP Address
- uint8_t sn[4]; ///< Subnet Mask
- uint8_t gw[4]; ///< Gateway IP Address
- uint8_t dns[4]; ///< DNS server IP Address
- dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP
-}wiz_NetInfo;
-
-/**
- * @ingroup DATA_TYPE
- * Network mode
- */
-typedef enum
-{
-#if _WIZCHIP_ == 5500
- NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500
-#endif
- NM_WAKEONLAN = (1<<5), ///< Wake On Lan
- NM_PINGBLOCK = (1<<4), ///< Block ping-request
- NM_PPPOE = (1<<3), ///< PPPoE mode
-}netmode_type;
-
-/**
- * @ingroup DATA_TYPE
- * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation.
- */
-typedef struct wiz_NetTimeout_t
-{
- uint8_t retry_cnt; ///< retry count
- uint16_t time_100us; ///< time unit 100us
-}wiz_NetTimeout;
-
-/**
- *@brief Registers call back function for critical section of I/O functions such as
- *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF.
- *@param cris_en : callback function for critical section enter.
- *@param cris_ex : callback function for critical section exit.
- *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions.
- *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called.
- */
-void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));
-
-
-/**
- *@brief Registers call back function for WIZCHIP select & deselect.
- *@param cs_sel : callback function for WIZCHIP select
- *@param cs_desel : callback fucntion for WIZCHIP deselect
- *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions.
- *@note If you do not describe or register, null function is called.
- */
-void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));
-
-/**
- *@brief Registers call back function for bus interface.
- *@param bus_rb : callback function to read byte data using system bus
- *@param bus_wb : callback function to write byte data using system bus
- *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function
- *or register your functions.
- *@note If you do not describe or register, null function is called.
- */
-void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb));
-
-/**
- *@brief Registers call back function for SPI interface.
- *@param spi_rb : callback function to read byte usig SPI
- *@param spi_wb : callback function to write byte usig SPI
- *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
- *or register your functions.
- *@note If you do not describe or register, null function is called.
- */
-void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t));
-
-/**
- * @ingroup extra_functions
- * @brief Controls to the WIZCHIP.
- * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto),
- * controls interrupt & mask and so on.
- * @param cwtype : Decides to the control type
- * @param arg : arg type is dependent on cwtype.
- * @return 0 : Success \n
- * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP
- */
-int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg);
-
-/**
- * @ingroup extra_functions
- * @brief Controls to network.
- * @details Controls to network environment, mode, timeout and so on.
- * @param cntype : Input. Decides to the control type
- * @param arg : Inout. arg type is dependent on cntype.
- * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n
- * 0 : Success
- */
-int8_t ctlnetwork(ctlnetwork_type cntype, void* arg);
-
-
-/*
- * The following functions are implemented for internal use.
- * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork().
- */
-
-/**
- * @ingroup extra_functions
- * @brief Reset WIZCHIP by softly.
- */
-void wizchip_sw_reset(void);
-
-/**
- * @ingroup extra_functions
- * @brief Initializes WIZCHIP with socket buffer size
- * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB.
- * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB.
- * @return 0 : succcess \n
- * -1 : fail. Invalid buffer size
- */
-int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);
-
-/**
- * @ingroup extra_functions
- * @brief Clear Interrupt of WIZCHIP.
- * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
- */
-void wizchip_clrinterrupt(intr_kind intr);
-
-/**
- * @ingroup extra_functions
- * @brief Get Interrupt of WIZCHIP.
- * @return @ref intr_kind value operated OR. It can type-cast to uint16_t.
- */
-intr_kind wizchip_getinterrupt(void);
-
-/**
- * @ingroup extra_functions
- * @brief Mask or Unmask Interrupt of WIZCHIP.
- * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
- */
-void wizchip_setinterruptmask(intr_kind intr);
-
-/**
- * @ingroup extra_functions
- * @brief Get Interrupt mask of WIZCHIP.
- * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t.
- */
-intr_kind wizchip_getinterruptmask(void);
-
-#if _WIZCHIP_ > 5100
- int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100
- int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100
-#endif
-
-#if _WIZCHIP_ == 5500
- void wizphy_reset(void); ///< Reset phy. Vailid only in W5500
-/**
- * @ingroup extra_functions
- * @brief Set the phy information for WIZCHIP without power mode
- * @param phyconf : @ref wiz_PhyConf
- */
- void wizphy_setphyconf(wiz_PhyConf* phyconf);
- /**
- * @ingroup extra_functions
- * @brief Get phy configuration information.
- * @param phyconf : @ref wiz_PhyConf
- */
- void wizphy_getphyconf(wiz_PhyConf* phyconf);
- /**
- * @ingroup extra_functions
- * @brief Get phy status.
- * @param phyconf : @ref wiz_PhyConf
- */
- void wizphy_getphystat(wiz_PhyConf* phyconf);
- /**
- * @ingroup extra_functions
- * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200
- * @param pmode Settig value of power down mode.
- */
- int8_t wizphy_setphypmode(uint8_t pmode);
-#endif
-
-/**
-* @ingroup extra_functions
- * @brief Set the network information for WIZCHIP
- * @param pnetinfo : @ref wizNetInfo
- */
-void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);
-
-/**
- * @ingroup extra_functions
- * @brief Get the network information for WIZCHIP
- * @param pnetinfo : @ref wizNetInfo
- */
-void wizchip_getnetinfo(wiz_NetInfo* pnetinfo);
-
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
-uint8_t *wizchip_getsubn(void);
-#endif
-
-/**
- * @ingroup extra_functions
- * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc.
- * @param pnetinfo Value of network mode. Refer to @ref netmode_type.
- */
-int8_t wizchip_setnetmode(netmode_type netmode);
-
-/**
- * @ingroup extra_functions
- * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc.
- * @return Value of network mode. Refer to @ref netmode_type.
- */
-netmode_type wizchip_getnetmode(void);
-
-/**
- * @ingroup extra_functions
- * @brief Set retry time value(@ref RTR) and retry count(@ref RCR).
- * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
- * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
- */
-void wizchip_settimeout(wiz_NetTimeout* nettime);
-
-/**
- * @ingroup extra_functions
- * @brief Get retry time value(@ref RTR) and retry count(@ref RCR).
- * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
- * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
- */
-void wizchip_gettimeout(wiz_NetTimeout* nettime);
-
-#endif // _WIZCHIP_CONF_H_
diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.c b/drivers/wiznet5k/internet/dhcp/dhcp.c
deleted file mode 100644
index 5747582599db4..0000000000000
--- a/drivers/wiznet5k/internet/dhcp/dhcp.c
+++ /dev/null
@@ -1,978 +0,0 @@
-//*****************************************************************************
-//
-//! \file dhcp.c
-//! \brief DHCP APIs implement file.
-//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/11/18> 1st Release
-//! <2012/12/20> V1.1.0
-//! 1. Optimize code
-//! 2. Add reg_dhcp_cbfunc()
-//! 3. Add DHCP_stop()
-//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run()
-//! 5. Don't care system endian
-//! 6. Add comments
-//! <2012/12/26> V1.1.1
-//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************
-
-//#include "Ethernet/socket.h"
-//#include "Internet/DHCP/dhcp.h"
-#include "../../Ethernet/socket.h"
-#include "dhcp.h"
-
-/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
-
-#ifdef _DHCP_DEBUG_
- #include
-#endif
-
-/* DHCP state machine. */
-#define STATE_DHCP_INIT 0 ///< Initialize
-#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER
-#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK
-#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased
-#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP
-#define STATE_DHCP_RELEASE 5 ///< No use
-#define STATE_DHCP_STOP 6 ///< Stop processing DHCP
-
-#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG
-#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG
-
-/* DHCP message OP code */
-#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG
-#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG
-
-/* DHCP message type */
-#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG
-#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG
-#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG
-#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG
-#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG
-#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG
-#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use
-#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use
-
-#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG
-#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG
-
-#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG
-#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG
-#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG
-
-#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time
-
-#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG
-#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG
-
-/*
- * @brief DHCP option and value (cf. RFC1533)
- */
-enum
-{
- padOption = 0,
- subnetMask = 1,
- timerOffset = 2,
- routersOnSubnet = 3,
- timeServer = 4,
- nameServer = 5,
- dns = 6,
- logServer = 7,
- cookieServer = 8,
- lprServer = 9,
- impressServer = 10,
- resourceLocationServer = 11,
- hostName = 12,
- bootFileSize = 13,
- meritDumpFile = 14,
- domainName = 15,
- swapServer = 16,
- rootPath = 17,
- extentionsPath = 18,
- IPforwarding = 19,
- nonLocalSourceRouting = 20,
- policyFilter = 21,
- maxDgramReasmSize = 22,
- defaultIPTTL = 23,
- pathMTUagingTimeout = 24,
- pathMTUplateauTable = 25,
- ifMTU = 26,
- allSubnetsLocal = 27,
- broadcastAddr = 28,
- performMaskDiscovery = 29,
- maskSupplier = 30,
- performRouterDiscovery = 31,
- routerSolicitationAddr = 32,
- staticRoute = 33,
- trailerEncapsulation = 34,
- arpCacheTimeout = 35,
- ethernetEncapsulation = 36,
- tcpDefaultTTL = 37,
- tcpKeepaliveInterval = 38,
- tcpKeepaliveGarbage = 39,
- nisDomainName = 40,
- nisServers = 41,
- ntpServers = 42,
- vendorSpecificInfo = 43,
- netBIOSnameServer = 44,
- netBIOSdgramDistServer = 45,
- netBIOSnodeType = 46,
- netBIOSscope = 47,
- xFontServer = 48,
- xDisplayManager = 49,
- dhcpRequestedIPaddr = 50,
- dhcpIPaddrLeaseTime = 51,
- dhcpOptionOverload = 52,
- dhcpMessageType = 53,
- dhcpServerIdentifier = 54,
- dhcpParamRequest = 55,
- dhcpMsg = 56,
- dhcpMaxMsgSize = 57,
- dhcpT1value = 58,
- dhcpT2value = 59,
- dhcpClassIdentifier = 60,
- dhcpClientIdentifier = 61,
- endOption = 255
-};
-
-/*
- * @brief DHCP message format
- */
-typedef struct {
- uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
- uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
- uint8_t hlen; ///< @ref DHCP_HLENETHERNET
- uint8_t hops; ///< @ref DHCP_HOPS
- uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction.
- uint16_t secs; ///< @ref DHCP_SECS
- uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
- uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever
- uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server
- uint8_t siaddr[4]; ///< No use
- uint8_t giaddr[4]; ///< No use
- uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero
- uint8_t sname[64]; ///< No use
- uint8_t file[128]; ///< No use
- uint8_t OPT[OPT_SIZE]; ///< Option
-} RIP_MSG;
-
-
-
-uint8_t DHCP_SOCKET; // Socket number for DHCP
-
-uint8_t DHCP_SIP[4]; // DHCP Server IP address
-
-// Network information from DHCP Server
-uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address
-uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP
-uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP
-uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP
-uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP
-
-
-int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state
-int8_t dhcp_retry_count = 0;
-
-uint32_t dhcp_lease_time = INFINITE_LEASETIME;
-volatile uint32_t dhcp_tick_1s = 0; // unit 1 second
-uint32_t dhcp_tick_next = DHCP_WAIT_TIME ;
-
-uint32_t DHCP_XID; // Any number
-
-RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing
-
-uint8_t HOST_NAME[] = DCHP_HOST_NAME;
-
-uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address.
-
-/* The default callback function */
-void default_ip_assign(void);
-void default_ip_update(void);
-void default_ip_conflict(void);
-
-/* Callback handler */
-void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */
-void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */
-void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */
-
-void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
-
-
-/* send DISCOVER message to DHCP server */
-void send_DHCP_DISCOVER(void);
-
-/* send REQEUST message to DHCP server */
-void send_DHCP_REQUEST(void);
-
-/* send DECLINE message to DHCP server */
-void send_DHCP_DECLINE(void);
-
-/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
-int8_t check_DHCP_leasedIP(void);
-
-/* check the timeout in DHCP process */
-uint8_t check_DHCP_timeout(void);
-
-/* Intialize to timeout process. */
-void reset_DHCP_timeout(void);
-
-/* Parse message as OFFER and ACK and NACK from DHCP server.*/
-int8_t parseDHCPCMSG(void);
-
-/* The default handler of ip assign first */
-void default_ip_assign(void)
-{
- setSIPR(DHCP_allocated_ip);
- setSUBR(DHCP_allocated_sn);
- setGAR (DHCP_allocated_gw);
-}
-
-/* The default handler of ip changed */
-void default_ip_update(void)
-{
- /* WIZchip Software Reset */
- setMR(MR_RST);
- getMR(); // for delay
- default_ip_assign();
- setSHAR(DHCP_CHADDR);
-}
-
-/* The default handler of ip changed */
-void default_ip_conflict(void)
-{
- // WIZchip Software Reset
- setMR(MR_RST);
- getMR(); // for delay
- setSHAR(DHCP_CHADDR);
-}
-
-/* register the call back func. */
-void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void))
-{
- dhcp_ip_assign = default_ip_assign;
- dhcp_ip_update = default_ip_update;
- dhcp_ip_conflict = default_ip_conflict;
- if(ip_assign) dhcp_ip_assign = ip_assign;
- if(ip_update) dhcp_ip_update = ip_update;
- if(ip_conflict) dhcp_ip_conflict = ip_conflict;
-}
-
-/* make the common DHCP message */
-void makeDHCPMSG(void)
-{
- uint8_t bk_mac[6];
- uint8_t* ptmp;
- uint8_t i;
- getSHAR(bk_mac);
- pDHCPMSG->op = DHCP_BOOTREQUEST;
- pDHCPMSG->htype = DHCP_HTYPE10MB;
- pDHCPMSG->hlen = DHCP_HLENETHERNET;
- pDHCPMSG->hops = DHCP_HOPS;
- ptmp = (uint8_t*)(&pDHCPMSG->xid);
- *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
- *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
- *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
- *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
- pDHCPMSG->secs = DHCP_SECS;
- ptmp = (uint8_t*)(&pDHCPMSG->flags);
- *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
- *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
-
- pDHCPMSG->ciaddr[0] = 0;
- pDHCPMSG->ciaddr[1] = 0;
- pDHCPMSG->ciaddr[2] = 0;
- pDHCPMSG->ciaddr[3] = 0;
-
- pDHCPMSG->yiaddr[0] = 0;
- pDHCPMSG->yiaddr[1] = 0;
- pDHCPMSG->yiaddr[2] = 0;
- pDHCPMSG->yiaddr[3] = 0;
-
- pDHCPMSG->siaddr[0] = 0;
- pDHCPMSG->siaddr[1] = 0;
- pDHCPMSG->siaddr[2] = 0;
- pDHCPMSG->siaddr[3] = 0;
-
- pDHCPMSG->giaddr[0] = 0;
- pDHCPMSG->giaddr[1] = 0;
- pDHCPMSG->giaddr[2] = 0;
- pDHCPMSG->giaddr[3] = 0;
-
- pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
- pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
- pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
- pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
- pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
- pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
-
- for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
- for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
- for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
-
- // MAGIC_COOKIE
- pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
- pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
- pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
- pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0;
-}
-
-/* SEND DHCP DISCOVER */
-void send_DHCP_DISCOVER(void)
-{
- uint16_t i;
- uint8_t ip[4];
- uint16_t k = 0;
-
- makeDHCPMSG();
-
- k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
-
- // Option Request Param
- pDHCPMSG->OPT[k++] = dhcpMessageType;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
-
- // Client identifier
- pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
- pDHCPMSG->OPT[k++] = 0x07;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
- // host name
- pDHCPMSG->OPT[k++] = hostName;
- pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
- for(i = 0 ; HOST_NAME[i] != 0; i++)
- pDHCPMSG->OPT[k++] = HOST_NAME[i];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
- pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
-
- pDHCPMSG->OPT[k++] = dhcpParamRequest;
- pDHCPMSG->OPT[k++] = 0x06; // length of request
- pDHCPMSG->OPT[k++] = subnetMask;
- pDHCPMSG->OPT[k++] = routersOnSubnet;
- pDHCPMSG->OPT[k++] = dns;
- pDHCPMSG->OPT[k++] = domainName;
- pDHCPMSG->OPT[k++] = dhcpT1value;
- pDHCPMSG->OPT[k++] = dhcpT2value;
- pDHCPMSG->OPT[k++] = endOption;
-
- for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
-
- // send broadcasting packet
- ip[0] = 255;
- ip[1] = 255;
- ip[2] = 255;
- ip[3] = 255;
-
-#ifdef _DHCP_DEBUG_
- printf("> Send DHCP_DISCOVER\r\n");
-#endif
-
- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
-}
-
-/* SEND DHCP REQUEST */
-void send_DHCP_REQUEST(void)
-{
- int i;
- uint8_t ip[4];
- uint16_t k = 0;
-
- makeDHCPMSG();
-
- if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
- {
- *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
- *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
- pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
- pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
- pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
- pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
- ip[0] = DHCP_SIP[0];
- ip[1] = DHCP_SIP[1];
- ip[2] = DHCP_SIP[2];
- ip[3] = DHCP_SIP[3];
- }
- else
- {
- ip[0] = 255;
- ip[1] = 255;
- ip[2] = 255;
- ip[3] = 255;
- }
-
- k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
-
- // Option Request Param.
- pDHCPMSG->OPT[k++] = dhcpMessageType;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_REQUEST;
-
- pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
- pDHCPMSG->OPT[k++] = 0x07;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
- if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
- {
- pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
-
- pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_SIP[0];
- pDHCPMSG->OPT[k++] = DHCP_SIP[1];
- pDHCPMSG->OPT[k++] = DHCP_SIP[2];
- pDHCPMSG->OPT[k++] = DHCP_SIP[3];
- }
-
- // host name
- pDHCPMSG->OPT[k++] = hostName;
- pDHCPMSG->OPT[k++] = 0; // length of hostname
- for(i = 0 ; HOST_NAME[i] != 0; i++)
- pDHCPMSG->OPT[k++] = HOST_NAME[i];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
- pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
-
- pDHCPMSG->OPT[k++] = dhcpParamRequest;
- pDHCPMSG->OPT[k++] = 0x08;
- pDHCPMSG->OPT[k++] = subnetMask;
- pDHCPMSG->OPT[k++] = routersOnSubnet;
- pDHCPMSG->OPT[k++] = dns;
- pDHCPMSG->OPT[k++] = domainName;
- pDHCPMSG->OPT[k++] = dhcpT1value;
- pDHCPMSG->OPT[k++] = dhcpT2value;
- pDHCPMSG->OPT[k++] = performRouterDiscovery;
- pDHCPMSG->OPT[k++] = staticRoute;
- pDHCPMSG->OPT[k++] = endOption;
-
- for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
-
-#ifdef _DHCP_DEBUG_
- printf("> Send DHCP_REQUEST\r\n");
-#endif
-
- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
-
-}
-
-/* SEND DHCP DHCPDECLINE */
-void send_DHCP_DECLINE(void)
-{
- int i;
- uint8_t ip[4];
- uint16_t k = 0;
-
- makeDHCPMSG();
-
- k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
-
- *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
- *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
-
- // Option Request Param.
- pDHCPMSG->OPT[k++] = dhcpMessageType;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_DECLINE;
-
- pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
- pDHCPMSG->OPT[k++] = 0x07;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
- pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
-
- pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_SIP[0];
- pDHCPMSG->OPT[k++] = DHCP_SIP[1];
- pDHCPMSG->OPT[k++] = DHCP_SIP[2];
- pDHCPMSG->OPT[k++] = DHCP_SIP[3];
-
- pDHCPMSG->OPT[k++] = endOption;
-
- for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
-
- //send broadcasting packet
- ip[0] = 0xFF;
- ip[1] = 0xFF;
- ip[2] = 0xFF;
- ip[3] = 0xFF;
-
-#ifdef _DHCP_DEBUG_
- printf("\r\n> Send DHCP_DECLINE\r\n");
-#endif
-
- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
-}
-
-/* PARSE REPLY pDHCPMSG */
-int8_t parseDHCPMSG(void)
-{
- uint8_t svr_addr[6];
- uint16_t svr_port;
- uint16_t len;
-
- uint8_t * p;
- uint8_t * e;
- uint8_t type;
- uint8_t opt_len;
-
- if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
- {
- len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port);
- #ifdef _DHCP_DEBUG_
- printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len);
- #endif
- }
- else return 0;
- if (svr_port == DHCP_SERVER_PORT) {
- // compare mac address
- if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
- (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
- (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) )
- return 0;
- type = 0;
- p = (uint8_t *)(&pDHCPMSG->op);
- p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
- e = p + (len - 240);
-
- while ( p < e ) {
-
- switch ( *p ) {
-
- case endOption :
- p = e; // for break while(p < e)
- break;
- case padOption :
- p++;
- break;
- case dhcpMessageType :
- p++;
- p++;
- type = *p++;
- break;
- case subnetMask :
- p++;
- p++;
- DHCP_allocated_sn[0] = *p++;
- DHCP_allocated_sn[1] = *p++;
- DHCP_allocated_sn[2] = *p++;
- DHCP_allocated_sn[3] = *p++;
- break;
- case routersOnSubnet :
- p++;
- opt_len = *p++;
- DHCP_allocated_gw[0] = *p++;
- DHCP_allocated_gw[1] = *p++;
- DHCP_allocated_gw[2] = *p++;
- DHCP_allocated_gw[3] = *p++;
- p = p + (opt_len - 4);
- break;
- case dns :
- p++;
- opt_len = *p++;
- DHCP_allocated_dns[0] = *p++;
- DHCP_allocated_dns[1] = *p++;
- DHCP_allocated_dns[2] = *p++;
- DHCP_allocated_dns[3] = *p++;
- p = p + (opt_len - 4);
- break;
- case dhcpIPaddrLeaseTime :
- p++;
- opt_len = *p++;
- dhcp_lease_time = *p++;
- dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
- dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
- dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
- #ifdef _DHCP_DEBUG_
- dhcp_lease_time = 10;
- #endif
- break;
- case dhcpServerIdentifier :
- p++;
- opt_len = *p++;
- DHCP_SIP[0] = *p++;
- DHCP_SIP[1] = *p++;
- DHCP_SIP[2] = *p++;
- DHCP_SIP[3] = *p++;
- break;
- default :
- p++;
- opt_len = *p++;
- p += opt_len;
- break;
- } // switch
- } // while
- } // if
- return type;
-}
-
-uint8_t DHCP_run(void)
-{
- uint8_t type;
- uint8_t ret;
-
- if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
-
- if(getSn_SR(DHCP_SOCKET) != SOCK_UDP)
- socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
-
- ret = DHCP_RUNNING;
- type = parseDHCPMSG();
-
- switch ( dhcp_state ) {
- case STATE_DHCP_INIT :
- DHCP_allocated_ip[0] = 0;
- DHCP_allocated_ip[1] = 0;
- DHCP_allocated_ip[2] = 0;
- DHCP_allocated_ip[3] = 0;
- send_DHCP_DISCOVER();
- dhcp_state = STATE_DHCP_DISCOVER;
- break;
- case STATE_DHCP_DISCOVER :
- if (type == DHCP_OFFER){
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_OFFER\r\n");
-#endif
- DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
- DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
- DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
- DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
-
- send_DHCP_REQUEST();
- dhcp_state = STATE_DHCP_REQUEST;
- } else ret = check_DHCP_timeout();
- break;
-
- case STATE_DHCP_REQUEST :
- if (type == DHCP_ACK) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_ACK\r\n");
-#endif
- if (check_DHCP_leasedIP()) {
- // Network info assignment from DHCP
- dhcp_ip_assign();
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_LEASED;
- } else {
- // IP address conflict occurred
- reset_DHCP_timeout();
- dhcp_ip_conflict();
- dhcp_state = STATE_DHCP_INIT;
- }
- } else if (type == DHCP_NAK) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_NACK\r\n");
-#endif
-
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_DISCOVER;
- } else ret = check_DHCP_timeout();
- break;
-
- case STATE_DHCP_LEASED :
- ret = DHCP_IP_LEASED;
- if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Maintains the IP address \r\n");
-#endif
-
- type = 0;
- OLD_allocated_ip[0] = DHCP_allocated_ip[0];
- OLD_allocated_ip[1] = DHCP_allocated_ip[1];
- OLD_allocated_ip[2] = DHCP_allocated_ip[2];
- OLD_allocated_ip[3] = DHCP_allocated_ip[3];
-
- DHCP_XID++;
-
- send_DHCP_REQUEST();
-
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_REREQUEST;
- }
- break;
-
- case STATE_DHCP_REREQUEST :
- ret = DHCP_IP_LEASED;
- if (type == DHCP_ACK) {
- dhcp_retry_count = 0;
- if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
- OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
- OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
- OLD_allocated_ip[3] != DHCP_allocated_ip[3])
- {
- ret = DHCP_IP_CHANGED;
- dhcp_ip_update();
- #ifdef _DHCP_DEBUG_
- printf(">IP changed.\r\n");
- #endif
-
- }
- #ifdef _DHCP_DEBUG_
- else printf(">IP is continued.\r\n");
- #endif
- reset_DHCP_timeout();
- dhcp_state = STATE_DHCP_LEASED;
- } else if (type == DHCP_NAK) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
-#endif
-
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_DISCOVER;
- } else ret = check_DHCP_timeout();
- break;
- default :
- break;
- }
-
- return ret;
-}
-
-void DHCP_stop(void)
-{
- close(DHCP_SOCKET);
- dhcp_state = STATE_DHCP_STOP;
-}
-
-uint8_t check_DHCP_timeout(void)
-{
- uint8_t ret = DHCP_RUNNING;
-
- if (dhcp_retry_count < MAX_DHCP_RETRY) {
- if (dhcp_tick_next < dhcp_tick_1s) {
-
- switch ( dhcp_state ) {
- case STATE_DHCP_DISCOVER :
-// printf("<> state : STATE_DHCP_DISCOVER\r\n");
- send_DHCP_DISCOVER();
- break;
-
- case STATE_DHCP_REQUEST :
-// printf("<> state : STATE_DHCP_REQUEST\r\n");
-
- send_DHCP_REQUEST();
- break;
-
- case STATE_DHCP_REREQUEST :
-// printf("<> state : STATE_DHCP_REREQUEST\r\n");
-
- send_DHCP_REQUEST();
- break;
-
- default :
- break;
- }
-
- dhcp_tick_1s = 0;
- dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
- dhcp_retry_count++;
- }
- } else { // timeout occurred
-
- switch(dhcp_state) {
- case STATE_DHCP_DISCOVER:
- dhcp_state = STATE_DHCP_INIT;
- ret = DHCP_FAILED;
- break;
- case STATE_DHCP_REQUEST:
- case STATE_DHCP_REREQUEST:
- send_DHCP_DISCOVER();
- dhcp_state = STATE_DHCP_DISCOVER;
- break;
- default :
- break;
- }
- reset_DHCP_timeout();
- }
- return ret;
-}
-
-int8_t check_DHCP_leasedIP(void)
-{
- uint8_t tmp;
- int32_t ret;
-
- //WIZchip RCR value changed for ARP Timeout count control
- tmp = getRCR();
- setRCR(0x03);
-
- // IP conflict detection : ARP request - ARP reply
- // Broadcasting ARP Request for check the IP conflict using UDP sendto() function
- ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
-
- // RCR value restore
- setRCR(tmp);
-
- if(ret == SOCKERR_TIMEOUT) {
- // UDP send Timeout occurred : allocated IP address is unique, DHCP Success
-
-#ifdef _DHCP_DEBUG_
- printf("\r\n> Check leased IP - OK\r\n");
-#endif
-
- return 1;
- } else {
- // Received ARP reply or etc : IP address conflict occur, DHCP Failed
- send_DHCP_DECLINE();
-
- ret = dhcp_tick_1s;
- while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message;
-
- return 0;
- }
-}
-
-void DHCP_init(uint8_t s, uint8_t * buf)
-{
- uint8_t zeroip[4] = {0,0,0,0};
- getSHAR(DHCP_CHADDR);
- if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
- {
- // assign temporary mac address, you should be set SHAR before call this function.
- DHCP_CHADDR[0] = 0x00;
- DHCP_CHADDR[1] = 0x08;
- DHCP_CHADDR[2] = 0xdc;
- DHCP_CHADDR[3] = 0x00;
- DHCP_CHADDR[4] = 0x00;
- DHCP_CHADDR[5] = 0x00;
- setSHAR(DHCP_CHADDR);
- }
-
- DHCP_SOCKET = s; // SOCK_DHCP
- pDHCPMSG = (RIP_MSG*)buf;
- DHCP_XID = 0x12345678;
-
- // WIZchip Netinfo Clear
- setSIPR(zeroip);
- setSIPR(zeroip);
- setGAR(zeroip);
-
- reset_DHCP_timeout();
- dhcp_state = STATE_DHCP_INIT;
-}
-
-
-/* Rset the DHCP timeout count and retry count. */
-void reset_DHCP_timeout(void)
-{
- dhcp_tick_1s = 0;
- dhcp_tick_next = DHCP_WAIT_TIME;
- dhcp_retry_count = 0;
-}
-
-void DHCP_time_handler(void)
-{
- dhcp_tick_1s++;
-}
-
-void getIPfromDHCP(uint8_t* ip)
-{
- ip[0] = DHCP_allocated_ip[0];
- ip[1] = DHCP_allocated_ip[1];
- ip[2] = DHCP_allocated_ip[2];
- ip[3] = DHCP_allocated_ip[3];
-}
-
-void getGWfromDHCP(uint8_t* ip)
-{
- ip[0] =DHCP_allocated_gw[0];
- ip[1] =DHCP_allocated_gw[1];
- ip[2] =DHCP_allocated_gw[2];
- ip[3] =DHCP_allocated_gw[3];
-}
-
-void getSNfromDHCP(uint8_t* ip)
-{
- ip[0] = DHCP_allocated_sn[0];
- ip[1] = DHCP_allocated_sn[1];
- ip[2] = DHCP_allocated_sn[2];
- ip[3] = DHCP_allocated_sn[3];
-}
-
-void getDNSfromDHCP(uint8_t* ip)
-{
- ip[0] = DHCP_allocated_dns[0];
- ip[1] = DHCP_allocated_dns[1];
- ip[2] = DHCP_allocated_dns[2];
- ip[3] = DHCP_allocated_dns[3];
-}
-
-uint32_t getDHCPLeasetime(void)
-{
- return dhcp_lease_time;
-}
-
-
-
-
diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.h b/drivers/wiznet5k/internet/dhcp/dhcp.h
deleted file mode 100644
index ee154d506ac37..0000000000000
--- a/drivers/wiznet5k/internet/dhcp/dhcp.h
+++ /dev/null
@@ -1,150 +0,0 @@
-//*****************************************************************************
-//
-//! \file dhcp.h
-//! \brief DHCP APIs Header file.
-//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/11/18> 1st Release
-//! <2012/12/20> V1.1.0
-//! 1. Move unreferenced DEFINE to dhcp.c
-//! <2012/12/26> V1.1.1
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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 _DHCP_H_
-#define _DHCP_H_
-
-/*
- * @brief
- * @details If you want to display debug & processing message, Define _DHCP_DEBUG_
- * @note If defined, it depends on
- */
-
-//#define _DHCP_DEBUG_
-
-/* Retry to processing DHCP */
-#define MAX_DHCP_RETRY 2 ///< Maximum retry count
-#define DHCP_WAIT_TIME 10 ///< Wait Time 10s
-
-/* UDP port numbers for DHCP */
-#define DHCP_SERVER_PORT 67 ///< DHCP server port number
-#define DHCP_CLIENT_PORT 68 ///< DHCP client port number
-
-#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number
-
-#define DCHP_HOST_NAME "WIZnet\0"
-
-/*
- * @brief return value of @ref DHCP_run()
- */
-enum
-{
- DHCP_FAILED = 0, ///< Processing Fail
- DHCP_RUNNING, ///< Processing DHCP protocol
- DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign)
- DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update)
- DHCP_IP_LEASED, ///< Stand by
- DHCP_STOPPED ///< Stop processing DHCP protocol
-};
-
-/*
- * @brief DHCP client initialization (outside of the main loop)
- * @param s - socket number
- * @param buf - buffer for processing DHCP message
- */
-void DHCP_init(uint8_t s, uint8_t * buf);
-
-/*
- * @brief DHCP 1s Tick Timer handler
- * @note SHOULD BE register to your system 1s Tick timer handler
- */
-void DHCP_time_handler(void);
-
-/*
- * @brief Register call back function
- * @param ip_assign - callback func when IP is assigned from DHCP server first
- * @param ip_update - callback func when IP is changed
- * @prarm ip_conflict - callback func when the assigned IP is conflict with others.
- */
-void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
-
-/*
- * @brief DHCP client in the main loop
- * @return The value is as the follow \n
- * @ref DHCP_FAILED \n
- * @ref DHCP_RUNNING \n
- * @ref DHCP_IP_ASSIGN \n
- * @ref DHCP_IP_CHANGED \n
- * @ref DHCP_IP_LEASED \n
- * @ref DHCP_STOPPED \n
- *
- * @note This function is always called by you main task.
- */
-uint8_t DHCP_run(void);
-
-/*
- * @brief Stop DHCP processing
- * @note If you want to restart. call DHCP_init() and DHCP_run()
- */
-void DHCP_stop(void);
-
-/* Get Network information assigned from DHCP server */
-/*
- * @brief Get IP address
- * @param ip - IP address to be returned
- */
-void getIPfromDHCP(uint8_t* ip);
-/*
- * @brief Get Gateway address
- * @param ip - Gateway address to be returned
- */
-void getGWfromDHCP(uint8_t* ip);
-/*
- * @brief Get Subnet mask value
- * @param ip - Subnet mask to be returned
- */
-void getSNfromDHCP(uint8_t* ip);
-/*
- * @brief Get DNS address
- * @param ip - DNS address to be returned
- */
-void getDNSfromDHCP(uint8_t* ip);
-
-/*
- * @brief Get the leased time by DHCP sever
- * @return unit 1s
- */
-uint32_t getDHCPLeasetime(void);
-
-#endif /* _DHCP_H_ */
diff --git a/drivers/wiznet5k/internet/dns/dns.c b/drivers/wiznet5k/internet/dns/dns.c
deleted file mode 100644
index c0ad570c00970..0000000000000
--- a/drivers/wiznet5k/internet/dns/dns.c
+++ /dev/null
@@ -1,566 +0,0 @@
-//*****************************************************************************
-//
-//! \file dns.c
-//! \brief DNS APIs Implement file.
-//! \details Send DNS query & Receive DNS reponse. \n
-//! It depends on stdlib.h & string.h in ansi-c library
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.1.0
-//! 1. Remove secondary DNS server in DNS_run
-//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
-//! 2. DNS_timerHandler -> DNS_time_handler
-//! 3. Remove the unused define
-//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
-//! <2013/12/20> V1.1.0
-//!
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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.
-//
-//*****************************************************************************
-
-#include
-#include
-
-//#include "Ethernet/socket.h"
-//#include "Internet/DNS/dns.h"
-#include "../../ethernet/socket.h"
-#include "dns.h"
-
-#ifdef _DNS_DEBUG_
- #include
-#endif
-
-#define INITRTT 2000L /* Initial smoothed response time */
-#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */
-
-#define TYPE_A 1 /* Host address */
-#define TYPE_NS 2 /* Name server */
-#define TYPE_MD 3 /* Mail destination (obsolete) */
-#define TYPE_MF 4 /* Mail forwarder (obsolete) */
-#define TYPE_CNAME 5 /* Canonical name */
-#define TYPE_SOA 6 /* Start of Authority */
-#define TYPE_MB 7 /* Mailbox name (experimental) */
-#define TYPE_MG 8 /* Mail group member (experimental) */
-#define TYPE_MR 9 /* Mail rename name (experimental) */
-#define TYPE_NULL 10 /* Null (experimental) */
-#define TYPE_WKS 11 /* Well-known sockets */
-#define TYPE_PTR 12 /* Pointer record */
-#define TYPE_HINFO 13 /* Host information */
-#define TYPE_MINFO 14 /* Mailbox information (experimental)*/
-#define TYPE_MX 15 /* Mail exchanger */
-#define TYPE_TXT 16 /* Text strings */
-#define TYPE_ANY 255 /* Matches any type */
-
-#define CLASS_IN 1 /* The ARPA Internet */
-
-/* Round trip timing parameters */
-#define AGAIN 8 /* Average RTT gain = 1/8 */
-#define LAGAIN 3 /* Log2(AGAIN) */
-#define DGAIN 4 /* Mean deviation gain = 1/4 */
-#define LDGAIN 2 /* log2(DGAIN) */
-
-/* Header for all domain messages */
-struct dhdr
-{
- uint16_t id; /* Identification */
- uint8_t qr; /* Query/Response */
-#define QUERY 0
-#define RESPONSE 1
- uint8_t opcode;
-#define IQUERY 1
- uint8_t aa; /* Authoratative answer */
- uint8_t tc; /* Truncation */
- uint8_t rd; /* Recursion desired */
- uint8_t ra; /* Recursion available */
- uint8_t rcode; /* Response code */
-#define NO_ERROR 0
-#define FORMAT_ERROR 1
-#define SERVER_FAIL 2
-#define NAME_ERROR 3
-#define NOT_IMPL 4
-#define REFUSED 5
- uint16_t qdcount; /* Question count */
- uint16_t ancount; /* Answer count */
- uint16_t nscount; /* Authority (name server) count */
- uint16_t arcount; /* Additional record count */
-};
-
-
-uint8_t* pDNSMSG; // DNS message buffer
-uint8_t DNS_SOCKET; // SOCKET number for DNS
-uint16_t DNS_MSGID; // DNS message ID
-
-extern uint32_t HAL_GetTick(void);
-uint32_t hal_sys_tick;
-
-/* converts uint16_t from network buffer to a host byte order integer. */
-uint16_t get16(uint8_t * s)
-{
- uint16_t i;
- i = *s++ << 8;
- i = i + *s;
- return i;
-}
-
-/* copies uint16_t to the network buffer with network byte order. */
-uint8_t * put16(uint8_t * s, uint16_t i)
-{
- *s++ = i >> 8;
- *s++ = i;
- return s;
-}
-
-
-/*
- * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM
- *
- * Description : This function converts a compressed domain name to the human-readable form
- * Arguments : msg - is a pointer to the reply message
- * compressed - is a pointer to the domain name in reply message.
- * buf - is a pointer to the buffer for the human-readable form name.
- * len - is the MAX. size of buffer.
- * Returns : the length of compressed message
- */
-int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len)
-{
- uint16_t slen; /* Length of current segment */
- uint8_t * cp;
- int clen = 0; /* Total length of compressed name */
- int indirect = 0; /* Set if indirection encountered */
- int nseg = 0; /* Total number of segments in name */
-
- cp = compressed;
-
- for (;;)
- {
- slen = *cp++; /* Length of this segment */
-
- if (!indirect) clen++;
-
- if ((slen & 0xc0) == 0xc0)
- {
- if (!indirect)
- clen++;
- indirect = 1;
- /* Follow indirection */
- cp = &msg[((slen & 0x3f)<<8) + *cp];
- slen = *cp++;
- }
-
- if (slen == 0) /* zero length == all done */
- break;
-
- len -= slen + 1;
-
- if (len < 0) return -1;
-
- if (!indirect) clen += slen;
-
- while (slen-- != 0) *buf++ = (char)*cp++;
- *buf++ = '.';
- nseg++;
- }
-
- if (nseg == 0)
- {
- /* Root name; represent as single dot */
- *buf++ = '.';
- len--;
- }
-
- *buf++ = '\0';
- len--;
-
- return clen; /* Length of compressed message */
-}
-
-/*
- * PARSE QUESTION SECTION
- *
- * Description : This function parses the question record of the reply message.
- * Arguments : msg - is a pointer to the reply message
- * cp - is a pointer to the question record.
- * Returns : a pointer the to next record.
- */
-uint8_t * dns_question(uint8_t * msg, uint8_t * cp)
-{
- int len;
- char name[MAXCNAME];
-
- len = parse_name(msg, cp, name, MAXCNAME);
-
-
- if (len == -1) return 0;
-
- cp += len;
- cp += 2; /* type */
- cp += 2; /* class */
-
- return cp;
-}
-
-
-/*
- * PARSE ANSER SECTION
- *
- * Description : This function parses the answer record of the reply message.
- * Arguments : msg - is a pointer to the reply message
- * cp - is a pointer to the answer record.
- * Returns : a pointer the to next record.
- */
-uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns)
-{
- int len, type;
- char name[MAXCNAME];
-
- len = parse_name(msg, cp, name, MAXCNAME);
-
- if (len == -1) return 0;
-
- cp += len;
- type = get16(cp);
- cp += 2; /* type */
- cp += 2; /* class */
- cp += 4; /* ttl */
- cp += 2; /* len */
-
-
- switch (type)
- {
- case TYPE_A:
- /* Just read the address directly into the structure */
- ip_from_dns[0] = *cp++;
- ip_from_dns[1] = *cp++;
- ip_from_dns[2] = *cp++;
- ip_from_dns[3] = *cp++;
- break;
- case TYPE_CNAME:
- case TYPE_MB:
- case TYPE_MG:
- case TYPE_MR:
- case TYPE_NS:
- case TYPE_PTR:
- /* These types all consist of a single domain name */
- /* convert it to ASCII format */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
- break;
- case TYPE_HINFO:
- len = *cp++;
- cp += len;
-
- len = *cp++;
- cp += len;
- break;
- case TYPE_MX:
- cp += 2;
- /* Get domain name of exchanger */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
- break;
- case TYPE_SOA:
- /* Get domain name of name server */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
-
- /* Get domain name of responsible person */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
-
- cp += 4;
- cp += 4;
- cp += 4;
- cp += 4;
- cp += 4;
- break;
- case TYPE_TXT:
- /* Just stash */
- break;
- default:
- /* Ignore */
- break;
- }
-
- return cp;
-}
-
-/*
- * PARSE THE DNS REPLY
- *
- * Description : This function parses the reply message from DNS server.
- * Arguments : dhdr - is a pointer to the header for DNS message
- * buf - is a pointer to the reply message.
- * len - is the size of reply message.
- * Returns : -1 - Domain name length is too big
- * 0 - Fail (Timeout or parse error)
- * 1 - Success,
- */
-int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns)
-{
- uint16_t tmp;
- uint16_t i;
- uint8_t * msg;
- uint8_t * cp;
-
- msg = pbuf;
- memset(pdhdr, 0, sizeof(*pdhdr));
-
- pdhdr->id = get16(&msg[0]);
- tmp = get16(&msg[2]);
- if (tmp & 0x8000) pdhdr->qr = 1;
-
- pdhdr->opcode = (tmp >> 11) & 0xf;
-
- if (tmp & 0x0400) pdhdr->aa = 1;
- if (tmp & 0x0200) pdhdr->tc = 1;
- if (tmp & 0x0100) pdhdr->rd = 1;
- if (tmp & 0x0080) pdhdr->ra = 1;
-
- pdhdr->rcode = tmp & 0xf;
- pdhdr->qdcount = get16(&msg[4]);
- pdhdr->ancount = get16(&msg[6]);
- pdhdr->nscount = get16(&msg[8]);
- pdhdr->arcount = get16(&msg[10]);
-
-
- /* Now parse the variable length sections */
- cp = &msg[12];
-
- /* Question section */
- for (i = 0; i < pdhdr->qdcount; i++)
- {
- cp = dns_question(msg, cp);
- if(!cp)
- {
-#ifdef _DNS_DEBUG_
- printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
-#endif
- return -1;
- }
- }
-
- /* Answer section */
- for (i = 0; i < pdhdr->ancount; i++)
- {
- cp = dns_answer(msg, cp, ip_from_dns);
- if(!cp)
- {
-#ifdef _DNS_DEBUG_
- printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
-#endif
- return -1;
- }
-
- }
-
- /* Name server (authority) section */
- for (i = 0; i < pdhdr->nscount; i++)
- {
- ;
- }
-
- /* Additional section */
- for (i = 0; i < pdhdr->arcount; i++)
- {
- ;
- }
-
- if(pdhdr->rcode == 0) return 1; // No error
- else return 0;
-}
-
-
-/*
- * MAKE DNS QUERY MESSAGE
- *
- * Description : This function makes DNS query message.
- * Arguments : op - Recursion desired
- * name - is a pointer to the domain name.
- * buf - is a pointer to the buffer for DNS message.
- * len - is the MAX. size of buffer.
- * Returns : the pointer to the DNS message.
- */
-int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len)
-{
- uint8_t *cp;
- char *cp1;
- char sname[MAXCNAME];
- char *dname;
- uint16_t p;
- uint16_t dlen;
-
- cp = buf;
-
- DNS_MSGID++;
- cp = put16(cp, DNS_MSGID);
- p = (op << 11) | 0x0100; /* Recursion desired */
- cp = put16(cp, p);
- cp = put16(cp, 1);
- cp = put16(cp, 0);
- cp = put16(cp, 0);
- cp = put16(cp, 0);
-
- strcpy(sname, name);
- dname = sname;
- dlen = strlen(dname);
- for (;;)
- {
- /* Look for next dot */
- cp1 = strchr(dname, '.');
-
- if (cp1 != NULL) len = cp1 - dname; /* More to come */
- else len = dlen; /* Last component */
-
- *cp++ = len; /* Write length of component */
- if (len == 0) break;
-
- /* Copy component up to (but not including) dot */
- memcpy(cp, dname, len);
- cp += len;
- if (cp1 == NULL)
- {
- *cp++ = 0; /* Last one; write null and finish */
- break;
- }
- dname += len+1;
- dlen -= len+1;
- }
-
- cp = put16(cp, 0x0001); /* type */
- cp = put16(cp, 0x0001); /* class */
-
- return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf)));
-}
-
-/*
- * CHECK DNS TIMEOUT
- *
- * Description : This function check the DNS timeout
- * Arguments : None.
- * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur
- * Note : timeout : retry count and timer both over.
- */
-
-int8_t check_DNS_timeout(void)
-{
- static uint8_t retry_count;
-
- uint32_t tick = HAL_GetTick();
- if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000)
- {
- hal_sys_tick = tick;
- if(retry_count >= MAX_DNS_RETRY) {
- retry_count = 0;
- return -1; // timeout occurred
- }
- retry_count++;
- return 0; // timer over, but no timeout
- }
-
- return 1; // no timer over, no timeout occur
-}
-
-
-
-/* DNS CLIENT INIT */
-void DNS_init(uint8_t s, uint8_t * buf)
-{
- DNS_SOCKET = s; // SOCK_DNS
- pDNSMSG = buf; // User's shared buffer
- DNS_MSGID = DNS_MSG_ID;
-}
-
-/* DNS CLIENT RUN */
-int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns)
-{
- int8_t ret;
- struct dhdr dhp;
- uint8_t ip[4];
- uint16_t len, port;
- int8_t ret_check_timeout;
-
- hal_sys_tick = HAL_GetTick();
-
- // Socket open
- WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0);
-
-#ifdef _DNS_DEBUG_
- printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
-#endif
-
- len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE);
- WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
-
- while (1)
- {
- if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0)
- {
- if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE;
- len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port);
- #ifdef _DNS_DEBUG_
- printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len);
- #endif
- ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns);
- break;
- }
- // Check Timeout
- ret_check_timeout = check_DNS_timeout();
- if (ret_check_timeout < 0) {
-
-#ifdef _DNS_DEBUG_
- printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
-#endif
- return 0; // timeout occurred
- }
- else if (ret_check_timeout == 0) {
-
-#ifdef _DNS_DEBUG_
- printf("> DNS Timeout\r\n");
-#endif
- WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
- }
- }
- WIZCHIP_EXPORT(close)(DNS_SOCKET);
- // Return value
- // 0 > : failed / 1 - success
- return ret;
-}
diff --git a/drivers/wiznet5k/internet/dns/dns.h b/drivers/wiznet5k/internet/dns/dns.h
deleted file mode 100644
index de0039515e28f..0000000000000
--- a/drivers/wiznet5k/internet/dns/dns.h
+++ /dev/null
@@ -1,96 +0,0 @@
-//*****************************************************************************
-//
-//! \file dns.h
-//! \brief DNS APIs Header file.
-//! \details Send DNS query & Receive DNS reponse.
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.1.0
-//! 1. Remove secondary DNS server in DNS_run
-//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
-//! 2. DNS_timerHandler -> DNS_time_handler
-//! 3. Move the no reference define to dns.c
-//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
-//! <2013/12/20> V1.1.0
-//!
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! All rights reserved.
-//!
-//! 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 the 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 _DNS_H_
-#define _DNS_H_
-
-#include
-/*
- * @brief Define it for Debug & Monitor DNS processing.
- * @note If defined, it depends on
- */
-
-//#define _DNS_DEBUG_
-
-#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */
-/*
- * @brief Maximum length of your queried Domain name
- * @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1)
- * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack.
- */
-#define MAX_DOMAIN_NAME 32 // for example "www.google.com"
-
-#define MAX_DNS_RETRY 2 ///< Requery Count
-#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s.
-
-#define IPPORT_DOMAIN 53 ///< DNS server port number
-
-#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number
-/*
- * @brief DNS process initialize
- * @param s : Socket number for DNS
- * @param buf : Buffer for DNS message
- */
-void DNS_init(uint8_t s, uint8_t * buf);
-
-/*
- * @brief DNS process
- * @details Send DNS query and receive DNS response
- * @param dns_ip : DNS server ip address
- * @param name : Domain name to be queried
- * @param ip_from_dns : IP address from DNS server
- * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n
- * 0 : failed (Timeout or Parse error)\n
- * 1 : success
- * @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME
- */
-int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns);
-
-#endif /* _DNS_H_ */
diff --git a/examples/SDdatalogger/datalogger.py b/examples/SDdatalogger/datalogger.py
index 3d6f98b389272..1d1195700cbb4 100644
--- a/examples/SDdatalogger/datalogger.py
+++ b/examples/SDdatalogger/datalogger.py
@@ -10,7 +10,6 @@
# loop
while True:
-
# wait for interrupt
# this reduces power consumption while waiting for switch press
pyb.wfi()
diff --git a/examples/asmsum.py b/examples/asmsum.py
index f465b25afda75..f2c7f285badc7 100644
--- a/examples/asmsum.py
+++ b/examples/asmsum.py
@@ -1,6 +1,5 @@
@micropython.asm_thumb
def asm_sum_words(r0, r1):
-
# r0 = len
# r1 = ptr
# r2 = sum
@@ -25,7 +24,6 @@ def asm_sum_words(r0, r1):
@micropython.asm_thumb
def asm_sum_bytes(r0, r1):
-
# r0 = len
# r1 = ptr
# r2 = sum
diff --git a/examples/bluetooth/ble_simple_central.py b/examples/bluetooth/ble_simple_central.py
index a6bbdc6ee0795..3c0cf2a0d49ea 100644
--- a/examples/bluetooth/ble_simple_central.py
+++ b/examples/bluetooth/ble_simple_central.py
@@ -179,7 +179,7 @@ def connect(self, addr_type=None, addr=None, callback=None):
# Disconnect from current device.
def disconnect(self):
- if not self._conn_handle:
+ if self._conn_handle is None:
return
self._ble.gap_disconnect(self._conn_handle)
self._reset()
diff --git a/examples/bluetooth/ble_temperature_central.py b/examples/bluetooth/ble_temperature_central.py
index 96c4aad1445a1..afa914672ce47 100644
--- a/examples/bluetooth/ble_temperature_central.py
+++ b/examples/bluetooth/ble_temperature_central.py
@@ -39,14 +39,7 @@
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
# org.bluetooth.characteristic.temperature
_TEMP_UUID = bluetooth.UUID(0x2A6E)
-_TEMP_CHAR = (
- _TEMP_UUID,
- bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
-)
-_ENV_SENSE_SERVICE = (
- _ENV_SENSE_UUID,
- (_TEMP_CHAR,),
-)
+
# org.bluetooth.characteristic.gap.appearance.xml
_ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)
@@ -196,7 +189,7 @@ def connect(self, addr_type=None, addr=None, callback=None):
# Disconnect from current device.
def disconnect(self):
- if not self._conn_handle:
+ if self._conn_handle is None:
return
self._ble.gap_disconnect(self._conn_handle)
self._reset()
diff --git a/examples/bluetooth/ble_uart_repl.py b/examples/bluetooth/ble_uart_repl.py
index 9e8a38ff4b5e8..7d92c1f31829a 100644
--- a/examples/bluetooth/ble_uart_repl.py
+++ b/examples/bluetooth/ble_uart_repl.py
@@ -20,6 +20,7 @@
else:
_timer = None
+
# Batch writes into 50ms intervals.
def schedule_in(handler, delay_ms):
def _wrap(_arg):
diff --git a/examples/conwaylife.py b/examples/conwaylife.py
index 44c1a507be8a3..00cbd9cfccaae 100644
--- a/examples/conwaylife.py
+++ b/examples/conwaylife.py
@@ -4,6 +4,7 @@
lcd = pyb.LCD("x")
lcd.light(1)
+
# do 1 iteration of Conway's Game of Life
def conway_step():
for x in range(128): # loop over x coordinates
diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile
index 99f239a7c5af8..13bfdf12395d8 100644
--- a/examples/embedding/Makefile
+++ b/examples/embedding/Makefile
@@ -1,8 +1,25 @@
-MPTOP = ../..
-CFLAGS = -std=c99 -I. -I$(MPTOP) -DNO_QSTR
-LDFLAGS = -L.
+# This file is part of the MicroPython project, http://micropython.org/
+# The MIT License (MIT)
+# Copyright (c) 2022-2023 Damien P. George
+#
+# This is a very simple makefile that demonstrates how to build the embed port.
+# All it needs to do is build all *.c files in the micropython_embed directory.
+# This makefile would be replaced with your custom build system.
-hello-embed: hello-embed.o -lmicropython
+EMBED_DIR = micropython_embed
+PROG = embed
--lmicropython:
- $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP)
+CFLAGS += -I.
+CFLAGS += -I$(EMBED_DIR)
+CFLAGS += -I$(EMBED_DIR)/port
+CFLAGS += -Wall -Og
+
+SRC += main.c
+SRC += $(wildcard $(EMBED_DIR)/*/*.c) $(wildcard $(EMBED_DIR)/*/*/*.c)
+OBJ += $(SRC:.c=.o)
+
+$(PROG): $(OBJ)
+ $(CC) -o $@ $^
+
+clean:
+ /bin/rm -f $(OBJ) $(PROG)
diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib
index 217f2643c9d6a..e69de29bb2d1d 100644
--- a/examples/embedding/Makefile.upylib
+++ b/examples/embedding/Makefile.upylib
@@ -1,194 +0,0 @@
-MPTOP = ../..
--include mpconfigport.mk
-include $(MPTOP)/py/mkenv.mk
-
-all: lib
-
-# OS name, for simple autoconfig
-UNAME_S := $(shell uname -s)
-
-# include py core make definitions
-include $(MPTOP)/py/py.mk
-include $(MPTOP)/extmod/extmod.mk
-
-INC += -I.
-INC += -I..
-INC += -I$(MPTOP)
-INC += -I$(MPTOP)/ports/unix
-INC += -I$(BUILD)
-
-# compiler settings
-CWARN = -Wall -Werror
-CWARN += -Wpointer-arith -Wuninitialized
-CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
-
-# Some systems (eg MacOS) need -fno-common so that mp_state_ctx is placed in the BSS.
-CFLAGS += -fno-common
-
-# Debugging/Optimization
-ifdef DEBUG
-CFLAGS += -g
-COPT = -O0
-else
-COPT = -Os #-DNDEBUG
-# _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra
-# security for detecting buffer overflows. Some distros (Ubuntu at the very least)
-# have it enabled by default.
-#
-# gcc already optimizes some printf calls to call puts and/or putchar. When
-# _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some
-# printf calls will also be optimized to call __printf_chk (in glibc). Any
-# printfs which get redirected to __printf_chk are then no longer synchronized
-# with printfs that go through mp_printf.
-#
-# In MicroPython, we don't want to use the runtime library's printf but rather
-# go through mp_printf, so that stdout is properly tied into streams, etc.
-# This means that we either need to turn off _FORTIFY_SOURCE or provide our
-# own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE.
-# It should also be noted that the use of printf in MicroPython is typically
-# quite limited anyways (primarily for debug and some error reporting, etc
-# in the unix version).
-#
-# Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could
-# find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/
-# Original patchset was introduced by
-# https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html .
-#
-# Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater
-CFLAGS += -U _FORTIFY_SOURCE
-endif
-
-# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed.
-# The unix port of MicroPython on OSX must be compiled with clang,
-# while cross-compile ports require gcc, so we test here for OSX and
-# if necessary override the value of 'CC' set in py/mkenv.mk
-ifeq ($(UNAME_S),Darwin)
-CC = clang
-# Use clang syntax for map file
-LDFLAGS_ARCH = -Wl,-map,$@.map
-else
-# Use gcc syntax for map file
-LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref
-endif
-LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
-
-ifeq ($(MICROPY_FORCE_32BIT),1)
-# Note: you may need to install i386 versions of dependency packages,
-# starting with linux-libc-dev:i386
-ifeq ($(MICROPY_PY_FFI),1)
-ifeq ($(UNAME_S),Linux)
-CFLAGS_MOD += -I/usr/include/i686-linux-gnu
-endif
-endif
-endif
-
-ifeq ($(MICROPY_USE_READLINE),1)
-INC += -I$(MPTOP)/shared/readline
-CFLAGS_MOD += -DMICROPY_USE_READLINE=1
-SHARED_SRC_C_EXTRA += readline/readline.c
-endif
-ifeq ($(MICROPY_USE_READLINE),2)
-CFLAGS_MOD += -DMICROPY_USE_READLINE=2
-LDFLAGS_MOD += -lreadline
-# the following is needed for BSD
-#LDFLAGS_MOD += -ltermcap
-endif
-ifeq ($(MICROPY_PY_TIME),1)
-CFLAGS_MOD += -DMICROPY_PY_TIME=1
-SRC_MOD += modtime.c
-endif
-ifeq ($(MICROPY_PY_TERMIOS),1)
-CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1
-SRC_MOD += modtermios.c
-endif
-ifeq ($(MICROPY_PY_SOCKET),1)
-CFLAGS_MOD += -DMICROPY_PY_SOCKET=1
-SRC_MOD += modsocket.c
-endif
-
-ifeq ($(MICROPY_PY_FFI),1)
-
-ifeq ($(MICROPY_STANDALONE),1)
-LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(MPTOP)/lib/libffi/build_dir/out/lib/libffi-*/include)
- ifeq ($(MICROPY_FORCE_32BIT),1)
- LIBFFI_LDFLAGS_MOD = $(MPTOP)/lib/libffi/build_dir/out/lib32/libffi.a
- else
- LIBFFI_LDFLAGS_MOD = $(MPTOP)/lib/libffi/build_dir/out/lib/libffi.a
- endif
-else
-LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi)
-LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi)
-endif
-
-ifeq ($(UNAME_S),Linux)
-LIBFFI_LDFLAGS_MOD += -ldl
-endif
-
-CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1
-LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD)
-SRC_MOD += modffi.c
-endif
-
-MAIN_C = main.c
-
-# source files
-SRC_C = $(addprefix ports/unix/,\
- $(MAIN_C) \
- gccollect.c \
- unix_mphal.c \
- input.c \
- modmachine.c \
- moduselect.c \
- alloc.c \
- coverage.c \
- fatfs_port.c \
- $(SRC_MOD) \
- )
-
-SHARED_SRC_C = $(addprefix shared/,\
- libc/printf.c \
- runtime/gchelper_generic.c \
- timeutils/timeutils.c \
- $(SHARED_SRC_C_EXTRA) \
- )
-
-OBJ = $(PY_O)
-OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
-
-# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(SHARED_SRC_C)
-# Append any auto-generated sources that are needed by sources listed in
-# SRC_QSTR
-SRC_QSTR_AUTO_DEPS +=
-
-include $(MPTOP)/py/mkrules.mk
-
-# Value of configure's --host= option (required for cross-compilation).
-# Deduce it from CROSS_COMPILE by default, but can be overridden.
-ifneq ($(CROSS_COMPILE),)
-CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE))
-else
-CROSS_COMPILE_HOST =
-endif
-
-deplibs: libffi axtls
-
-# install-exec-recursive & install-data-am targets are used to avoid building
-# docs and depending on makeinfo
-libffi:
- cd $(MPTOP)/lib/libffi; git clean -d -x -f
- cd $(MPTOP)/lib/libffi; ./autogen.sh
- mkdir -p $(MPTOP)/lib/libffi/build_dir; cd $(MPTOP)/lib/libffi/build_dir; \
- ../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out CC="$(CC)" CXX="$(CXX)" LD="$(LD)"; \
- make install-exec-recursive; make -C include install-data-am
-
-axtls: $(MPTOP)/lib/axtls/README
- cd $(MPTOP)/lib/axtls; cp config/upyconfig config/.config
- cd $(MPTOP)/lib/axtls; make oldconfig -B
- cd $(MPTOP)/lib/axtls; make clean
- cd $(MPTOP)/lib/axtls; make all CC="$(CC)" LD="$(LD)"
-
-$(MPTOP)/lib/axtls/README:
- @echo "You cloned without --recursive, fetching submodules for you."
- (cd $(MPTOP); git submodule update --init --recursive)
diff --git a/examples/embedding/README.md b/examples/embedding/README.md
index 0dfc52e1dcad3..3f19aff41f257 100644
--- a/examples/embedding/README.md
+++ b/examples/embedding/README.md
@@ -1,67 +1,37 @@
Example of embedding MicroPython in a standalone C application
==============================================================
-This directory contains a (very simple!) example of how to embed a MicroPython
-in an existing C application.
-
-A C application is represented by the file `hello-embed.c`. It executes a simple
-Python statement which prints to the standard output.
+This directory contains a simple example of how to embed MicroPython in an
+existing C application.
+A C application is represented here by the file `main.c`. It executes two
+simple Python scripts which print things to the standard output.
Building the example
--------------------
-Building the example is as simple as running:
-
- make
-
-It's worth to trace what's happening behind the scenes though:
-
-1. As a first step, a MicroPython library is built. This is handled by a
-separate makefile, `Makefile.upylib`. It is more or less complex, but the
-good news is that you won't need to change anything in it, just use it
-as is, the main `Makefile` shows how. What may require editing though is
-a MicroPython configuration file. MicroPython is highly configurable, so
-you would need to build a library suiting your application well, while
-not bloating its size. Check the options in the file `mpconfigport.h`.
-Included is a copy of the "minimal" Unix port, which should be a good start
-for minimal embedding. For the list of all available options, see
-`py/mpconfig.h`.
+First build the embed port using:
-2. Once the MicroPython library is built, your application is compiled
-and linked it. The main Makefile is very simple and shows that the changes
-you would need to do to your application's `Makefile` (or other build
-configuration) are also simple:
+ $ make -f micropython_embed.mk
-a) You would need to use C99 standard (you're using this 15+ years old
-standard already, not a 25+ years old one, right?).
+This will generate the `micropython_embed` directory which is a self-contained
+copy of MicroPython suitable for embedding. The .c files in this directory need
+to be compiled into your project, in whatever way your project can do that. The
+example here uses make and a provided `Makefile`.
-b) You need to provide a path to MicroPython's top-level dir, for includes.
+To build the example project, based on `main.c`, use:
-c) You need to include `-DNO_QSTR` compile-time flag.
+ $ make
-d) Otherwise, just link with the MicroPython library produced in step 1.
+That will create an executable called `embed` which you can run:
+ $ ./embed
Out of tree build
-----------------
This example is set up to work out of the box, being part of the MicroPython
-tree. Your application of course will be outside of its tree, but the
-only thing you need to do is to pass `MPTOP` variable pointing to
-MicroPython directory to both Makefiles (in this example, the main Makefile
-automatically passes it to `Makefile.upylib`; in your own Makefile, don't forget
-to use a suitable value).
-
-A practical way to embed MicroPython in your application is to include it
-as a git submodule. Suppose you included it as `libs/micropython`. Then in
-your main Makefile you would have something like:
-
-~~~
-MPTOP = libs/micropython
-
-my_app: $(MY_OBJS) -lmicropython
-
--lmicropython:
- $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP)
-~~~
+tree. Your application will be outside of this tree, but the only thing you
+need to do for that is to change `MICROPYTHON_TOP` (found in `micropython_embed.mk`)
+to point to the location of the MicroPython repository. The MicroPython
+repository may, for example, be a git submodule in your project.
diff --git a/examples/embedding/hello-embed.c b/examples/embedding/hello-embed.c
deleted file mode 100644
index 0b778986b3a5d..0000000000000
--- a/examples/embedding/hello-embed.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016 Paul Sokolovsky
- *
- * 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/builtin.h"
-#include "py/compile.h"
-#include "py/runtime.h"
-#include "py/gc.h"
-#include "py/stackctrl.h"
-
-static char heap[16384];
-
-mp_obj_t execute_from_str(const char *str) {
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- qstr src_name = 1/*MP_QSTR_*/;
- mp_lexer_t *lex = mp_lexer_new_from_str_len(src_name, str, strlen(str), false);
- mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT);
- mp_obj_t module_fun = mp_compile(&pt, src_name, false);
- mp_call_function_0(module_fun);
- nlr_pop();
- return 0;
- } else {
- // uncaught exception
- return (mp_obj_t)nlr.ret_val;
- }
-}
-
-int main() {
- // Initialized stack limit
- mp_stack_set_limit(40000 * (sizeof(void *) / 4));
- // Initialize heap
- gc_init(heap, heap + sizeof(heap));
- // Initialize interpreter
- mp_init();
-
- const char str[] = "print('Hello world of easy embedding!')";
- if (execute_from_str(str)) {
- printf("Error\n");
- }
-}
-
-uint mp_import_stat(const char *path) {
- return MP_IMPORT_STAT_NO_EXIST;
-}
-
-void nlr_jump_fail(void *val) {
- printf("FATAL: uncaught NLR %p\n", val);
- exit(1);
-}
diff --git a/examples/embedding/main.c b/examples/embedding/main.c
new file mode 100644
index 0000000000000..ee673fc93a687
--- /dev/null
+++ b/examples/embedding/main.c
@@ -0,0 +1,44 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2022-2023 Damien P. George
+ */
+
+#include "port/micropython_embed.h"
+
+// This is example 1 script, which will be compiled and executed.
+static const char *example_1 =
+ "print('hello world!', list(x + 1 for x in range(10)), end='eol\\n')";
+
+// This is example 2 script, which will be compiled and executed.
+static const char *example_2 =
+ "for i in range(10):\n"
+ " print('iter {:08}'.format(i))\n"
+ "\n"
+ "try:\n"
+ " 1//0\n"
+ "except Exception as er:\n"
+ " print('caught exception', repr(er))\n"
+ "\n"
+ "import gc\n"
+ "print('run GC collect')\n"
+ "gc.collect()\n"
+ "\n"
+ "print('finish')\n"
+ ;
+
+// This array is the MicroPython GC heap.
+static char heap[8 * 1024];
+
+int main() {
+ // Initialise MicroPython.
+ mp_embed_init(&heap[0], sizeof(heap));
+
+ // Run the example scripts (they will be compiled first).
+ mp_embed_exec_str(example_1);
+ mp_embed_exec_str(example_2);
+
+ // Deinitialise MicroPython.
+ mp_embed_deinit();
+
+ return 0;
+}
diff --git a/examples/embedding/micropython_embed.mk b/examples/embedding/micropython_embed.mk
new file mode 100644
index 0000000000000..5db541592750c
--- /dev/null
+++ b/examples/embedding/micropython_embed.mk
@@ -0,0 +1,9 @@
+# This file is part of the MicroPython project, http://micropython.org/
+# The MIT License (MIT)
+# Copyright (c) 2022-2023 Damien P. George
+
+# Set the location of the top of the MicroPython repository.
+MICROPYTHON_TOP = ../..
+
+# Include the main makefile fragment to build the MicroPython component.
+include $(MICROPYTHON_TOP)/ports/embed/embed.mk
diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h
index 89c180b2a8153..ed34a5d766aeb 100644
--- a/examples/embedding/mpconfigport.h
+++ b/examples/embedding/mpconfigport.h
@@ -1 +1,15 @@
-#include "mpconfigport_minimal.h"
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2022-2023 Damien P. George
+ */
+
+// Include common MicroPython embed configuration.
+#include
+
+// Use the minimal starting configuration (disables all optional features).
+#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM)
+
+// MicroPython configuration.
+#define MICROPY_ENABLE_COMPILER (1)
+#define MICROPY_ENABLE_GC (1)
+#define MICROPY_PY_GC (1)
diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h
deleted file mode 100644
index 6cc84dcbc1e41..0000000000000
--- a/examples/embedding/mpconfigport_minimal.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 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.
- */
-
-// options to control how MicroPython is built
-
-#define MICROPY_ALLOC_PATH_MAX (PATH_MAX)
-#define MICROPY_ENABLE_GC (1)
-#define MICROPY_ENABLE_FINALISER (0)
-#define MICROPY_STACK_CHECK (0)
-#define MICROPY_COMP_CONST (0)
-#define MICROPY_MEM_STATS (0)
-#define MICROPY_DEBUG_PRINTERS (0)
-#define MICROPY_READER_POSIX (1)
-#define MICROPY_KBD_EXCEPTION (1)
-#define MICROPY_HELPER_REPL (1)
-#define MICROPY_HELPER_LEXER_UNIX (1)
-#define MICROPY_ENABLE_SOURCE_LINE (0)
-#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
-#define MICROPY_WARNINGS (0)
-#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
-#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
-#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
-#define MICROPY_STREAMS_NON_BLOCK (0)
-#define MICROPY_OPT_COMPUTED_GOTO (0)
-#define MICROPY_CAN_OVERRIDE_BUILTINS (0)
-#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
-#define MICROPY_CPYTHON_COMPAT (0)
-#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
-#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
-#define MICROPY_PY_BUILTINS_COMPILE (0)
-#define MICROPY_PY_BUILTINS_ENUMERATE (0)
-#define MICROPY_PY_BUILTINS_FILTER (0)
-#define MICROPY_PY_BUILTINS_FROZENSET (0)
-#define MICROPY_PY_BUILTINS_REVERSED (0)
-#define MICROPY_PY_BUILTINS_SET (0)
-#define MICROPY_PY_BUILTINS_SLICE (0)
-#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
-#define MICROPY_PY_BUILTINS_PROPERTY (0)
-#define MICROPY_PY_BUILTINS_MIN_MAX (0)
-#define MICROPY_PY___FILE__ (0)
-#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
-#define MICROPY_PY_GC (0)
-#define MICROPY_PY_GC_COLLECT_RETVAL (0)
-#define MICROPY_PY_ARRAY (0)
-#define MICROPY_PY_COLLECTIONS (0)
-#define MICROPY_PY_MATH (0)
-#define MICROPY_PY_CMATH (0)
-#define MICROPY_PY_IO (0)
-#define MICROPY_PY_IO_FILEIO (0)
-#define MICROPY_PY_STRUCT (0)
-#define MICROPY_PY_SYS (1)
-#define MICROPY_PY_SYS_EXIT (0)
-#define MICROPY_PY_SYS_PLATFORM "linux"
-#define MICROPY_PY_SYS_MAXSIZE (0)
-#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen"
-#define MICROPY_PY_SYS_STDFILES (0)
-#define MICROPY_PY_CMATH (0)
-#define MICROPY_PY_UCTYPES (0)
-#define MICROPY_PY_UZLIB (0)
-#define MICROPY_PY_UJSON (0)
-#define MICROPY_PY_UOS (1)
-#define MICROPY_PY_URE (0)
-#define MICROPY_PY_UHEAPQ (0)
-#define MICROPY_PY_UHASHLIB (0)
-#define MICROPY_PY_UBINASCII (0)
-
-#define MICROPY_PORT_ROOT_POINTERS \
-
-//////////////////////////////////////////
-// Do not change anything beyond this line
-//////////////////////////////////////////
-
-#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
-// Fall back to setjmp() implementation for discovery of GC pointers in registers.
-#define MICROPY_GCREGS_SETJMP (1)
-#endif
-
-// type definitions for the specific machine
-
-#ifdef __LP64__
-typedef long mp_int_t; // must be pointer size
-typedef unsigned long mp_uint_t; // must be pointer size
-#else
-// These are definitions for machines where sizeof(int) == sizeof(void*),
-// regardless for actual size.
-typedef int mp_int_t; // must be pointer size
-typedef unsigned int mp_uint_t; // must be pointer size
-#endif
-
-// Cannot include , as it may lead to symbol name clashes
-#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
-typedef long long mp_off_t;
-#else
-typedef long mp_off_t;
-#endif
-
-// We need to provide a declaration/definition of alloca()
-#ifdef __FreeBSD__
-#include
-#else
-#include
-#endif
diff --git a/examples/hwapi/README.md b/examples/hwapi/README.md
index 1992eb66094e8..a1b0c5642a2fb 100644
--- a/examples/hwapi/README.md
+++ b/examples/hwapi/README.md
@@ -5,7 +5,7 @@ which would work from a board to board, from a system to another systems.
This is inherently a hard problem, because hardware is different from one
board type to another, and even from examplar of board to another. For
example, if your app requires an external LED, one user may connect it
-to one GPIO pin, while another user may find it much more convinient to
+to one GPIO pin, while another user may find it much more convenient to
use another pin. This of course applies to relays, buzzers, sensors, etc.
With complications above in mind, it's still possible to write portable
@@ -40,13 +40,13 @@ application of this idea would look like:
`app.py`:
from hwconfig import *
- import utime
+ import time
while True:
LED.value(1)
- utime.sleep_ms(500)
+ time.sleep_ms(500)
LED.value(0)
- utime.sleep_ms(500)
+ time.sleep_ms(500)
To deploy this application to a particular board, a user will need:
@@ -116,7 +116,7 @@ For example, one may invent a "configuration manager" helper module which will
try to detect current board (among well-known ones), and load appropriate
`hwconfig_*.py` - this assumes that a user would lazily deploy them all
(or that application will be automatically installed, e.g. using MicroPython's
-`upip` package manager). The key point in this case remains the same as
+`mip` package manager). The key point in this case remains the same as
elaborated above - always assume there can, and will be a custom configuration,
and it should be well supported. So, any automatic detection should be
overridable by a user, and instructions how to do so are among the most
diff --git a/examples/hwapi/button_led.py b/examples/hwapi/button_led.py
index bd6fe0172988c..c73bcfc89a297 100644
--- a/examples/hwapi/button_led.py
+++ b/examples/hwapi/button_led.py
@@ -1,4 +1,4 @@
-import utime
+import time
from hwconfig import LED, BUTTON
# Light LED when (and while) a BUTTON is pressed
@@ -6,4 +6,4 @@
while 1:
LED.value(BUTTON.value())
# Don't burn CPU
- utime.sleep_ms(10)
+ time.sleep_ms(10)
diff --git a/examples/hwapi/button_reaction.py b/examples/hwapi/button_reaction.py
index e5a139a575f2c..52bdf793849ed 100644
--- a/examples/hwapi/button_reaction.py
+++ b/examples/hwapi/button_reaction.py
@@ -1,4 +1,4 @@
-import utime
+import time
import machine
from hwconfig import LED, BUTTON
@@ -18,4 +18,4 @@
print("Well, you're *really* slow")
else:
print("You are as slow as %d microseconds!" % delay)
- utime.sleep_ms(10)
+ time.sleep_ms(10)
diff --git a/examples/hwapi/hwconfig_pyboard.py b/examples/hwapi/hwconfig_pyboard.py
index a74a1ae151bb8..cb77e9f2d6827 100644
--- a/examples/hwapi/hwconfig_pyboard.py
+++ b/examples/hwapi/hwconfig_pyboard.py
@@ -1,6 +1,6 @@
from machine import Pin, Signal
-# Red LED on pin LED_RED also kown as A13
+# Red LED on pin LED_RED also known as A13
LED = Signal("LED_RED", Pin.OUT)
# Green LED on pin LED_GREEN also known as A14
diff --git a/examples/hwapi/soft_pwm.py b/examples/hwapi/soft_pwm.py
index 72291b0ecde52..466de08f09b6c 100644
--- a/examples/hwapi/soft_pwm.py
+++ b/examples/hwapi/soft_pwm.py
@@ -1,4 +1,4 @@
-import utime
+import time
from hwconfig import LED
@@ -15,10 +15,10 @@ def pwm_cycle(led, duty, cycles):
for i in range(cycles):
if duty:
led.on()
- utime.sleep_ms(duty)
+ time.sleep_ms(duty)
if duty_off:
led.off()
- utime.sleep_ms(duty_off)
+ time.sleep_ms(duty_off)
# At the duty setting of 1, an LED is still pretty bright, then
diff --git a/examples/hwapi/soft_pwm2_asyncio.py b/examples/hwapi/soft_pwm2_asyncio.py
new file mode 100644
index 0000000000000..6894990043273
--- /dev/null
+++ b/examples/hwapi/soft_pwm2_asyncio.py
@@ -0,0 +1,31 @@
+# Like soft_pwm_asyncio.py, but fading 2 LEDs with different phase.
+# Also see original soft_pwm.py.
+import asyncio
+from hwconfig import LED, LED2
+
+
+async def pwm_cycle(led, duty, cycles):
+ duty_off = 20 - duty
+ for i in range(cycles):
+ if duty:
+ led.value(1)
+ await asyncio.sleep_ms(duty)
+ if duty_off:
+ led.value(0)
+ await asyncio.sleep_ms(duty_off)
+
+
+async def fade_in_out(LED):
+ while True:
+ # Fade in
+ for i in range(1, 21):
+ await pwm_cycle(LED, i, 2)
+ # Fade out
+ for i in range(20, 0, -1):
+ await pwm_cycle(LED, i, 2)
+
+
+loop = asyncio.get_event_loop()
+loop.create_task(fade_in_out(LED))
+loop.call_later_ms(800, fade_in_out(LED2))
+loop.run_forever()
diff --git a/examples/hwapi/soft_pwm2_uasyncio.py b/examples/hwapi/soft_pwm2_uasyncio.py
deleted file mode 100644
index 908ef2d8ac202..0000000000000
--- a/examples/hwapi/soft_pwm2_uasyncio.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Like soft_pwm_uasyncio.py, but fading 2 LEDs with different phase.
-# Also see original soft_pwm.py.
-import uasyncio
-from hwconfig import LED, LED2
-
-
-async def pwm_cycle(led, duty, cycles):
- duty_off = 20 - duty
- for i in range(cycles):
- if duty:
- led.value(1)
- await uasyncio.sleep_ms(duty)
- if duty_off:
- led.value(0)
- await uasyncio.sleep_ms(duty_off)
-
-
-async def fade_in_out(LED):
- while True:
- # Fade in
- for i in range(1, 21):
- await pwm_cycle(LED, i, 2)
- # Fade out
- for i in range(20, 0, -1):
- await pwm_cycle(LED, i, 2)
-
-
-loop = uasyncio.get_event_loop()
-loop.create_task(fade_in_out(LED))
-loop.call_later_ms(800, fade_in_out(LED2))
-loop.run_forever()
diff --git a/examples/hwapi/soft_pwm_asyncio.py b/examples/hwapi/soft_pwm_asyncio.py
new file mode 100644
index 0000000000000..ae6c7340f6fdd
--- /dev/null
+++ b/examples/hwapi/soft_pwm_asyncio.py
@@ -0,0 +1,28 @@
+# See original soft_pwm.py for detailed comments.
+import asyncio
+from hwconfig import LED
+
+
+async def pwm_cycle(led, duty, cycles):
+ duty_off = 20 - duty
+ for i in range(cycles):
+ if duty:
+ led.value(1)
+ await asyncio.sleep_ms(duty)
+ if duty_off:
+ led.value(0)
+ await asyncio.sleep_ms(duty_off)
+
+
+async def fade_in_out(LED):
+ while True:
+ # Fade in
+ for i in range(1, 21):
+ await pwm_cycle(LED, i, 2)
+ # Fade out
+ for i in range(20, 0, -1):
+ await pwm_cycle(LED, i, 2)
+
+
+loop = asyncio.get_event_loop()
+loop.run_until_complete(fade_in_out(LED))
diff --git a/examples/hwapi/soft_pwm_uasyncio.py b/examples/hwapi/soft_pwm_uasyncio.py
deleted file mode 100644
index 8d7ad8c9e07ba..0000000000000
--- a/examples/hwapi/soft_pwm_uasyncio.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# See original soft_pwm.py for detailed comments.
-import uasyncio
-from hwconfig import LED
-
-
-async def pwm_cycle(led, duty, cycles):
- duty_off = 20 - duty
- for i in range(cycles):
- if duty:
- led.value(1)
- await uasyncio.sleep_ms(duty)
- if duty_off:
- led.value(0)
- await uasyncio.sleep_ms(duty_off)
-
-
-async def fade_in_out(LED):
- while True:
- # Fade in
- for i in range(1, 21):
- await pwm_cycle(LED, i, 2)
- # Fade out
- for i in range(20, 0, -1):
- await pwm_cycle(LED, i, 2)
-
-
-loop = uasyncio.get_event_loop()
-loop.run_until_complete(fade_in_out(LED))
diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c
index 5e8a34ac40095..c897f2e9a3859 100644
--- a/examples/natmod/btree/btree_c.c
+++ b/examples/natmod/btree/btree_c.c
@@ -51,7 +51,7 @@ int *__errno (void)
ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
mp_obj_base_t* o = stream;
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol);
mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
@@ -62,7 +62,7 @@ ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
mp_obj_base_t* o = stream;
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol);
mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
@@ -73,7 +73,7 @@ ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
const mp_obj_base_t* o = stream;
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol);
struct mp_stream_seek_t seek_s;
seek_s.offset = offset;
seek_s.whence = whence;
@@ -86,7 +86,7 @@ off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
int mp_stream_posix_fsync(void *stream) {
mp_obj_base_t* o = stream;
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol);
mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno);
if (res == MP_STREAM_ERROR) {
return -1;
@@ -94,7 +94,8 @@ int mp_stream_posix_fsync(void *stream) {
return res;
}
-mp_obj_type_t btree_type;
+mp_obj_full_type_t btree_type;
+mp_getiter_iternext_custom_t btree_getiter_iternext;
#include "extmod/modbtree.c"
@@ -122,13 +123,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
+ btree_getiter_iternext.getiter = btree_getiter;
+ btree_getiter_iternext.iternext = btree_iternext;
+
btree_type.base.type = (void*)&mp_fun_table.type_type;
+ btree_type.flags = MP_TYPE_FLAG_ITER_IS_CUSTOM;
btree_type.name = MP_QSTR_btree;
- btree_type.print = btree_print;
- btree_type.getiter = btree_getiter;
- btree_type.iternext = btree_iternext;
- btree_type.binary_op = btree_binary_op;
- btree_type.subscr = btree_subscr;
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, print, btree_print, 0);
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, iter, &btree_getiter_iternext, 1);
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, binary_op, btree_binary_op, 2);
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, subscr, btree_subscr, 3);
btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) };
btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) };
btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) };
@@ -137,7 +141,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) };
btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) };
btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) };
- btree_type.locals_dict = (void*)&btree_locals_dict;
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 4);
mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj));
mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL));
diff --git a/examples/natmod/features1/features1.c b/examples/natmod/features1/features1.c
index f865f1887cd08..d2494b2138865 100644
--- a/examples/natmod/features1/features1.c
+++ b/examples/natmod/features1/features1.c
@@ -88,7 +88,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
// This must be first, it sets up the globals dict and other things
MP_DYNRUNTIME_INIT_ENTRY
- // Messages can be printed as usualy
+ // Messages can be printed as usual
mp_printf(&mp_plat_print, "initialising module self=%p\n", self);
// Make the functions available in the module's namespace
diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c
index 8d488cffd685a..32b67eabcf84f 100644
--- a/examples/natmod/framebuf/framebuf.c
+++ b/examples/natmod/framebuf/framebuf.c
@@ -8,11 +8,11 @@ void *memset(void *s, int c, size_t n) {
}
#endif
-mp_obj_type_t mp_type_framebuf;
+mp_obj_full_type_t mp_type_framebuf;
#include "extmod/modframebuf.c"
-mp_map_elem_t framebuf_locals_dict_table[10];
+mp_map_elem_t framebuf_locals_dict_table[11];
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
@@ -20,8 +20,8 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
mp_type_framebuf.base.type = (void*)&mp_type_type;
mp_type_framebuf.name = MP_QSTR_FrameBuffer;
- mp_type_framebuf.make_new = framebuf_make_new;
- mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer;
+ MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, make_new, framebuf_make_new, 0);
+ MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, buffer, framebuf_get_buffer, 1);
framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) };
framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) };
framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) };
@@ -29,10 +29,11 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) };
framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) };
framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) };
- framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
- framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
- framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
- mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict;
+ framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ellipse), MP_OBJ_FROM_PTR(&framebuf_ellipse_obj) };
+ framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
+ framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
+ framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
+ MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 2);
mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf));
mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj));
diff --git a/examples/natmod/heapq/Makefile b/examples/natmod/heapq/Makefile
new file mode 100644
index 0000000000000..af45b472da1ae
--- /dev/null
+++ b/examples/natmod/heapq/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in heapq so it can coexist)
+MOD = heapq_$(ARCH)
+
+# Source files (.c or .py)
+SRC = heapq.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/heapq/heapq.c b/examples/natmod/heapq/heapq.c
new file mode 100644
index 0000000000000..ed19652a66b1d
--- /dev/null
+++ b/examples/natmod/heapq/heapq.c
@@ -0,0 +1,16 @@
+#define MICROPY_PY_HEAPQ (1)
+
+#include "py/dynruntime.h"
+
+#include "extmod/modheapq.c"
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_heapq));
+ mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_heapq_heappush_obj));
+ mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_heapq_heappop_obj));
+ mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_heapq_heapify_obj));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/random/Makefile b/examples/natmod/random/Makefile
new file mode 100644
index 0000000000000..5c50227b15f9d
--- /dev/null
+++ b/examples/natmod/random/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in random so it can coexist)
+MOD = random_$(ARCH)
+
+# Source files (.c or .py)
+SRC = random.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/random/random.c b/examples/natmod/random/random.c
new file mode 100644
index 0000000000000..92257b8bc6811
--- /dev/null
+++ b/examples/natmod/random/random.c
@@ -0,0 +1,33 @@
+#define MICROPY_PY_RANDOM (1)
+#define MICROPY_PY_RANDOM_EXTRA_FUNCS (1)
+
+#include "py/dynruntime.h"
+
+// Dynamic native modules don't support a data section so these must go in the BSS
+uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
+uint8_t yasmarang_dat;
+
+#include "extmod/modrandom.c"
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ yasmarang_pad = 0xeda4baba;
+ yasmarang_n = 69;
+ yasmarang_d = 233;
+
+ mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_random));
+ mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_random_getrandbits_obj));
+ mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_random_seed_obj));
+ #if MICROPY_PY_RANDOM_EXTRA_FUNCS
+ mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_random_randrange_obj));
+ mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_random_randint_obj));
+ mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_random_choice_obj));
+ #if MICROPY_PY_BUILTINS_FLOAT
+ mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_random_random_obj));
+ mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_random_uniform_obj));
+ #endif
+ #endif
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/re/Makefile b/examples/natmod/re/Makefile
new file mode 100644
index 0000000000000..1ba540110650d
--- /dev/null
+++ b/examples/natmod/re/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in re so it can coexist)
+MOD = re_$(ARCH)
+
+# Source files (.c or .py)
+SRC = re.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/re/re.c b/examples/natmod/re/re.c
new file mode 100644
index 0000000000000..df89ea83530ec
--- /dev/null
+++ b/examples/natmod/re/re.c
@@ -0,0 +1,78 @@
+#define MICROPY_STACK_CHECK (1)
+#define MICROPY_PY_RE (1)
+#define MICROPY_PY_RE_MATCH_GROUPS (1)
+#define MICROPY_PY_RE_MATCH_SPAN_START_END (1)
+#define MICROPY_PY_RE_SUB (0) // requires vstr interface
+
+#include
+#include "py/dynruntime.h"
+
+#define STACK_LIMIT (2048)
+
+const char *stack_top;
+
+void mp_stack_check(void) {
+ // Assumes descending stack on target
+ volatile char dummy;
+ if (stack_top - &dummy >= STACK_LIMIT) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("maximum recursion depth exceeded"));
+ }
+}
+
+#if !defined(__linux__)
+void *memcpy(void *dst, const void *src, size_t n) {
+ return mp_fun_table.memmove_(dst, src, n);
+}
+void *memset(void *s, int c, size_t n) {
+ return mp_fun_table.memset_(s, c, n);
+}
+#endif
+
+void *memmove(void *dest, const void *src, size_t n) {
+ return mp_fun_table.memmove_(dest, src, n);
+}
+
+mp_obj_full_type_t match_type;
+mp_obj_full_type_t re_type;
+
+#include "extmod/modre.c"
+
+mp_map_elem_t match_locals_dict_table[5];
+STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
+
+mp_map_elem_t re_locals_dict_table[3];
+STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ char dummy;
+ stack_top = &dummy;
+
+ // Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section
+ // to copy in this key/value pair if they are specified as a struct, so assign them separately.
+
+ match_type.base.type = (void*)&mp_fun_table.type_type;
+ match_type.name = MP_QSTR_match;
+ MP_OBJ_TYPE_SET_SLOT(&match_type, print, match_print, 0);
+ match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) };
+ match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) };
+ match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) };
+ match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) };
+ match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) };
+ MP_OBJ_TYPE_SET_SLOT(&match_type, locals_dict, (void*)&match_locals_dict, 1);
+
+ re_type.base.type = (void*)&mp_fun_table.type_type;
+ re_type.name = MP_QSTR_re;
+ MP_OBJ_TYPE_SET_SLOT(&re_type, print, re_print, 0);
+ re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) };
+ re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) };
+ re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) };
+ MP_OBJ_TYPE_SET_SLOT(&re_type, locals_dict, (void*)&re_locals_dict, 1);
+
+ mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj));
+ mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj));
+ mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&re_search_obj));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/uheapq/Makefile b/examples/natmod/uheapq/Makefile
deleted file mode 100644
index 55de3cc081857..0000000000000
--- a/examples/natmod/uheapq/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Location of top-level MicroPython directory
-MPY_DIR = ../../..
-
-# Name of module (different to built-in uheapq so it can coexist)
-MOD = uheapq_$(ARCH)
-
-# Source files (.c or .py)
-SRC = uheapq.c
-
-# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
-ARCH = x64
-
-include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/uheapq/uheapq.c b/examples/natmod/uheapq/uheapq.c
deleted file mode 100644
index 9da6bb4ada4b4..0000000000000
--- a/examples/natmod/uheapq/uheapq.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#define MICROPY_PY_UHEAPQ (1)
-
-#include "py/dynruntime.h"
-
-#include "extmod/moduheapq.c"
-
-mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
- MP_DYNRUNTIME_INIT_ENTRY
-
- mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq));
- mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj));
- mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj));
- mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj));
-
- MP_DYNRUNTIME_INIT_EXIT
-}
diff --git a/examples/natmod/urandom/Makefile b/examples/natmod/urandom/Makefile
deleted file mode 100644
index 3f018baaf76b6..0000000000000
--- a/examples/natmod/urandom/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Location of top-level MicroPython directory
-MPY_DIR = ../../..
-
-# Name of module (different to built-in urandom so it can coexist)
-MOD = urandom_$(ARCH)
-
-# Source files (.c or .py)
-SRC = urandom.c
-
-# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
-ARCH = x64
-
-include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/urandom/urandom.c b/examples/natmod/urandom/urandom.c
deleted file mode 100644
index e1fed6a554fce..0000000000000
--- a/examples/natmod/urandom/urandom.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#define MICROPY_PY_URANDOM (1)
-#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
-
-#include "py/dynruntime.h"
-
-// Dynamic native modules don't support a data section so these must go in the BSS
-uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
-uint8_t yasmarang_dat;
-
-#include "extmod/modurandom.c"
-
-mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
- MP_DYNRUNTIME_INIT_ENTRY
-
- yasmarang_pad = 0xeda4baba;
- yasmarang_n = 69;
- yasmarang_d = 233;
-
- mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom));
- mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj));
- mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj));
- #if MICROPY_PY_URANDOM_EXTRA_FUNCS
- mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj));
- mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj));
- mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj));
- #if MICROPY_PY_BUILTINS_FLOAT
- mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj));
- mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj));
- #endif
- #endif
-
- MP_DYNRUNTIME_INIT_EXIT
-}
diff --git a/examples/natmod/ure/Makefile b/examples/natmod/ure/Makefile
deleted file mode 100644
index f5254298fdd90..0000000000000
--- a/examples/natmod/ure/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Location of top-level MicroPython directory
-MPY_DIR = ../../..
-
-# Name of module (different to built-in ure so it can coexist)
-MOD = ure_$(ARCH)
-
-# Source files (.c or .py)
-SRC = ure.c
-
-# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
-ARCH = x64
-
-include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c
deleted file mode 100644
index 175b93e395ef9..0000000000000
--- a/examples/natmod/ure/ure.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#define MICROPY_STACK_CHECK (1)
-#define MICROPY_PY_URE (1)
-#define MICROPY_PY_URE_MATCH_GROUPS (1)
-#define MICROPY_PY_URE_MATCH_SPAN_START_END (1)
-#define MICROPY_PY_URE_SUB (0) // requires vstr interface
-
-#include
-#include "py/dynruntime.h"
-
-#define STACK_LIMIT (2048)
-
-const char *stack_top;
-
-void mp_stack_check(void) {
- // Assumes descending stack on target
- volatile char dummy;
- if (stack_top - &dummy >= STACK_LIMIT) {
- mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("maximum recursion depth exceeded"));
- }
-}
-
-#if !defined(__linux__)
-void *memcpy(void *dst, const void *src, size_t n) {
- return mp_fun_table.memmove_(dst, src, n);
-}
-void *memset(void *s, int c, size_t n) {
- return mp_fun_table.memset_(s, c, n);
-}
-#endif
-
-void *memmove(void *dest, const void *src, size_t n) {
- return mp_fun_table.memmove_(dest, src, n);
-}
-
-mp_obj_type_t match_type;
-mp_obj_type_t re_type;
-
-#include "extmod/modure.c"
-
-mp_map_elem_t match_locals_dict_table[5];
-STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
-
-mp_map_elem_t re_locals_dict_table[3];
-STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
-
-mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
- MP_DYNRUNTIME_INIT_ENTRY
-
- char dummy;
- stack_top = &dummy;
-
- // Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section
- // to copy in this key/value pair if they are specified as a struct, so assign them separately.
-
- match_type.base.type = (void*)&mp_fun_table.type_type;
- match_type.name = MP_QSTR_match;
- match_type.print = match_print;
- match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) };
- match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) };
- match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) };
- match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) };
- match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) };
- match_type.locals_dict = (void*)&match_locals_dict;
-
- re_type.base.type = (void*)&mp_fun_table.type_type;
- re_type.name = MP_QSTR_ure;
- re_type.print = re_print;
- re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) };
- re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) };
- re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) };
- re_type.locals_dict = (void*)&re_locals_dict;
-
- mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj));
- mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj));
- mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&re_search_obj));
-
- MP_DYNRUNTIME_INIT_EXIT
-}
diff --git a/examples/natmod/uzlib/Makefile b/examples/natmod/uzlib/Makefile
deleted file mode 100644
index 8761caf2dd26c..0000000000000
--- a/examples/natmod/uzlib/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# Location of top-level MicroPython directory
-MPY_DIR = ../../..
-
-# Name of module (different to built-in uzlib so it can coexist)
-MOD = uzlib_$(ARCH)
-
-# Source files (.c or .py)
-SRC = uzlib.c
-
-# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
-ARCH = x64
-
-include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c
deleted file mode 100644
index 99b3691761ea4..0000000000000
--- a/examples/natmod/uzlib/uzlib.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#define MICROPY_PY_UZLIB (1)
-
-#include "py/dynruntime.h"
-
-#if !defined(__linux__)
-void *memset(void *s, int c, size_t n) {
- return mp_fun_table.memset_(s, c, n);
-}
-#endif
-
-mp_obj_type_t decompio_type;
-
-#include "extmod/moduzlib.c"
-
-mp_map_elem_t decompio_locals_dict_table[3];
-STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
-
-mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
- MP_DYNRUNTIME_INIT_ENTRY
-
- decompio_type.base.type = mp_fun_table.type_type;
- decompio_type.name = MP_QSTR_DecompIO;
- decompio_type.make_new = decompio_make_new;
- decompio_type.protocol = &decompio_stream_p;
- decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
- decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
- decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };
- decompio_type.locals_dict = (void*)&decompio_locals_dict;
-
- mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib));
- mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj));
- mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type));
-
- MP_DYNRUNTIME_INIT_EXIT
-}
diff --git a/examples/natmod/zlib/Makefile b/examples/natmod/zlib/Makefile
new file mode 100644
index 0000000000000..e4b4e0712ef2e
--- /dev/null
+++ b/examples/natmod/zlib/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in zlib so it can coexist)
+MOD = zlib_$(ARCH)
+
+# Source files (.c or .py)
+SRC = zlib.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/zlib/zlib.c b/examples/natmod/zlib/zlib.c
new file mode 100644
index 0000000000000..2b0dbd5ca0155
--- /dev/null
+++ b/examples/natmod/zlib/zlib.c
@@ -0,0 +1,35 @@
+#define MICROPY_PY_ZLIB (1)
+
+#include "py/dynruntime.h"
+
+#if !defined(__linux__)
+void *memset(void *s, int c, size_t n) {
+ return mp_fun_table.memset_(s, c, n);
+}
+#endif
+
+mp_obj_full_type_t decompio_type;
+
+#include "extmod/modzlib.c"
+
+mp_map_elem_t decompio_locals_dict_table[3];
+STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ decompio_type.base.type = mp_fun_table.type_type;
+ decompio_type.name = MP_QSTR_DecompIO;
+ MP_OBJ_TYPE_SET_SLOT(&decompio_type, make_new, &decompio_make_new, 0);
+ MP_OBJ_TYPE_SET_SLOT(&decompio_type, protocol, &decompio_stream_p, 1);
+ decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
+ decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
+ decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };
+ MP_OBJ_TYPE_SET_SLOT(&decompio_type, locals_dict, (void*)&decompio_locals_dict, 2);
+
+ mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_zlib));
+ mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_zlib_decompress_obj));
+ mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/network/http_client.py b/examples/network/http_client.py
index 0791c8066b676..661c286b70bc4 100644
--- a/examples/network/http_client.py
+++ b/examples/network/http_client.py
@@ -1,7 +1,4 @@
-try:
- import usocket as socket
-except:
- import socket
+import socket
def main(use_stream=False):
diff --git a/examples/network/http_client_ssl.py b/examples/network/http_client_ssl.py
index 83f685fdf35db..323971c0ee24d 100644
--- a/examples/network/http_client_ssl.py
+++ b/examples/network/http_client_ssl.py
@@ -1,17 +1,11 @@
-try:
- import usocket as _socket
-except:
- import _socket
-try:
- import ussl as ssl
-except:
- import ssl
+import socket
+import ssl
def main(use_stream=True):
- s = _socket.socket()
+ s = socket.socket()
- ai = _socket.getaddrinfo("google.com", 443)
+ ai = socket.getaddrinfo("google.com", 443)
print("Address infos:", ai)
addr = ai[0][-1]
diff --git a/examples/network/http_server.py b/examples/network/http_server.py
index 76be3ab8173b0..a6ed53154a4eb 100644
--- a/examples/network/http_server.py
+++ b/examples/network/http_server.py
@@ -1,7 +1,4 @@
-try:
- import usocket as socket
-except:
- import socket
+import socket
CONTENT = b"""\
diff --git a/examples/network/http_server_simplistic.py b/examples/network/http_server_simplistic.py
index 71949419e67b8..09936b9d91ea8 100644
--- a/examples/network/http_server_simplistic.py
+++ b/examples/network/http_server_simplistic.py
@@ -1,9 +1,6 @@
# Do not use this code in real projects! Read
# http_server_simplistic_commented.py for details.
-try:
- import usocket as socket
-except:
- import socket
+import socket
CONTENT = b"""\
@@ -28,7 +25,6 @@ def main():
while True:
res = s.accept()
client_s = res[0]
- client_addr = res[1]
req = client_s.recv(4096)
print("Request:")
print(req)
diff --git a/examples/network/http_server_simplistic_commented.py b/examples/network/http_server_simplistic_commented.py
index da042c6c8a56e..d4710ad61a61e 100644
--- a/examples/network/http_server_simplistic_commented.py
+++ b/examples/network/http_server_simplistic_commented.py
@@ -8,10 +8,7 @@
# details, and use this code only for quick hacks, preferring
# http_server.py for "real thing".
#
-try:
- import usocket as socket
-except:
- import socket
+import socket
CONTENT = b"""\
diff --git a/examples/network/http_server_ssl.py b/examples/network/http_server_ssl.py
index 1116c71e996a9..7766fa7ea5661 100644
--- a/examples/network/http_server_ssl.py
+++ b/examples/network/http_server_ssl.py
@@ -1,10 +1,6 @@
-import ubinascii as binascii
-
-try:
- import usocket as socket
-except:
- import socket
-import ussl as ssl
+import binascii
+import socket
+import ssl
# This self-signed key/cert pair is randomly generated and to be used for
diff --git a/examples/rp2/pio_1hz.py b/examples/rp2/pio_1hz.py
index c18aa22fc0ece..84d761fa1434e 100644
--- a/examples/rp2/pio_1hz.py
+++ b/examples/rp2/pio_1hz.py
@@ -1,4 +1,5 @@
# Example using PIO to blink an LED and raise an IRQ at 1Hz.
+# Note: this does not work on Pico W because it uses Pin(25) for LED output.
import time
from machine import Pin
@@ -16,9 +17,10 @@ def blink_1hz():
nop() [29]
jmp(x_dec, "delay_high")
- # Cycles: 1 + 7 + 32 * (30 + 1) = 1000
+ # Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
+ nop()
set(pins, 0)
- set(x, 31) [6]
+ set(x, 31) [5]
label("delay_low")
nop() [29]
jmp(x_dec, "delay_low")
diff --git a/examples/rp2/pio_exec.py b/examples/rp2/pio_exec.py
index d8cbc33ef015a..ce39f2df84306 100644
--- a/examples/rp2/pio_exec.py
+++ b/examples/rp2/pio_exec.py
@@ -1,4 +1,5 @@
# Example using PIO to turn on an LED via an explicit exec.
+# Note: this does not work on Pico W because it uses Pin(25) for LED output.
#
# Demonstrates:
# - using set_init and set_base
@@ -8,6 +9,7 @@
from machine import Pin
import rp2
+
# Define an empty program that uses a single set pin.
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def prog():
diff --git a/examples/rp2/pio_uart_tx.py b/examples/rp2/pio_uart_tx.py
index 0f8c1260bd7da..5e4af8f6ccfdc 100644
--- a/examples/rp2/pio_uart_tx.py
+++ b/examples/rp2/pio_uart_tx.py
@@ -33,6 +33,7 @@ def uart_tx():
sm.active(1)
uarts.append(sm)
+
# We can print characters from each UART by pushing them to the TX FIFO
def pio_uart_print(sm, s):
for c in s:
diff --git a/examples/rp2/pwm_fade.py b/examples/rp2/pwm_fade.py
index 7264edaa293a1..5b7089c6b1add 100644
--- a/examples/rp2/pwm_fade.py
+++ b/examples/rp2/pwm_fade.py
@@ -1,4 +1,5 @@
# Example using PWM to fade an LED.
+# Note: this does not work on Pico W because it uses Pin(25) for LED output.
import time
from machine import Pin, PWM
diff --git a/examples/unix/machine_bios.py b/examples/unix/machine_bios.py
index 878f3fd8f3c58..40aae4ccefe6d 100644
--- a/examples/unix/machine_bios.py
+++ b/examples/unix/machine_bios.py
@@ -4,6 +4,6 @@
# It is expected to print 0xaa55, which is a signature at the start of
# Video BIOS.
-import umachine as machine
+import machine
print(hex(machine.mem16[0xC0000]))
diff --git a/examples/usercmodule/cexample/examplemodule.c b/examples/usercmodule/cexample/examplemodule.c
index 93a58be2ed280..9416613ba9520 100644
--- a/examples/usercmodule/cexample/examplemodule.c
+++ b/examples/usercmodule/cexample/examplemodule.c
@@ -1,6 +1,9 @@
// Include MicroPython API.
#include "py/runtime.h"
+// Used to get the time in the Timer class example.
+#include "py/mphal.h"
+
// This is the function which will be called from Python as cexample.add_ints(a, b).
STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
// Extract the ints from the micropython input objects.
@@ -13,7 +16,59 @@ STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
// Define a Python reference to the function above.
STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);
-// Define all properties of the module.
+// This structure represents Timer instance objects.
+typedef struct _example_Timer_obj_t {
+ // All objects start with the base.
+ mp_obj_base_t base;
+ // Everything below can be thought of as instance attributes, but they
+ // cannot be accessed by MicroPython code directly. In this example we
+ // store the time at which the object was created.
+ mp_uint_t start_time;
+} example_Timer_obj_t;
+
+// This is the Timer.time() method. After creating a Timer object, this
+// can be called to get the time elapsed since creating the Timer.
+STATIC mp_obj_t example_Timer_time(mp_obj_t self_in) {
+ // The first argument is self. It is cast to the *example_Timer_obj_t
+ // type so we can read its attributes.
+ example_Timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ // Get the elapsed time and return it as a MicroPython integer.
+ mp_uint_t elapsed = mp_hal_ticks_ms() - self->start_time;
+ return mp_obj_new_int_from_uint(elapsed);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(example_Timer_time_obj, example_Timer_time);
+
+// This represents Timer.__new__ and Timer.__init__, which is called when
+// the user instantiates a Timer object.
+STATIC mp_obj_t example_Timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ // Allocates the new object and sets the type.
+ example_Timer_obj_t *self = mp_obj_malloc(example_Timer_obj_t, type);
+
+ // Initializes the time for this Timer instance.
+ self->start_time = mp_hal_ticks_ms();
+
+ // The make_new function always returns self.
+ return MP_OBJ_FROM_PTR(self);
+}
+
+// This collects all methods and other static class attributes of the Timer.
+// The table structure is similar to the module table, as detailed below.
+STATIC const mp_rom_map_elem_t example_Timer_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&example_Timer_time_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_Timer_locals_dict, example_Timer_locals_dict_table);
+
+// This defines the type(Timer) object.
+MP_DEFINE_CONST_OBJ_TYPE(
+ example_type_Timer,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, example_Timer_make_new,
+ locals_dict, &example_Timer_locals_dict
+ );
+
+// Define all attributes of the module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
// All identifiers and strings are written as MP_QSTR_xxx and will be
@@ -21,6 +76,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);
STATIC const mp_rom_map_elem_t example_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) },
{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },
+ { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) },
};
STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);
diff --git a/examples/usercmodule/cexample/micropython.mk b/examples/usercmodule/cexample/micropython.mk
index dbfe3c5cbdb1f..d6801dac0ba5b 100644
--- a/examples/usercmodule/cexample/micropython.mk
+++ b/examples/usercmodule/cexample/micropython.mk
@@ -1,9 +1,8 @@
-EXAMPLE_MOD_DIR := $(USERMOD_DIR)
+CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
# Add all C files to SRC_USERMOD.
-SRC_USERMOD += $(EXAMPLE_MOD_DIR)/examplemodule.c
+SRC_USERMOD += $(CEXAMPLE_MOD_DIR)/examplemodule.c
# We can add our module folder to include paths if needed
# This is not actually needed in this example.
-CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
-CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
+CFLAGS_USERMOD += -I$(CEXAMPLE_MOD_DIR)
diff --git a/examples/usercmodule/cppexample/examplemodule.c b/examples/usercmodule/cppexample/examplemodule.c
index 5c84eccd7996f..96a1a74438845 100644
--- a/examples/usercmodule/cppexample/examplemodule.c
+++ b/examples/usercmodule/cppexample/examplemodule.c
@@ -4,7 +4,7 @@
// See example.cpp for the definition.
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc);
-// Define all properties of the module.
+// Define all attributes of the module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
// All identifiers and strings are written as MP_QSTR_xxx and will be
diff --git a/examples/usercmodule/subpackage/README.md b/examples/usercmodule/subpackage/README.md
new file mode 100644
index 0000000000000..c7f2ee53a2408
--- /dev/null
+++ b/examples/usercmodule/subpackage/README.md
@@ -0,0 +1 @@
+This is an example of a user C module that includes subpackages.
diff --git a/examples/usercmodule/subpackage/micropython.cmake b/examples/usercmodule/subpackage/micropython.cmake
new file mode 100644
index 0000000000000..a51e7a80613d3
--- /dev/null
+++ b/examples/usercmodule/subpackage/micropython.cmake
@@ -0,0 +1,19 @@
+# Create an INTERFACE library for our C module.
+add_library(usermod_subpackage_example INTERFACE)
+
+# Add our source files to the lib
+target_sources(usermod_subpackage_example INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
+)
+
+# Add the current directory as an include directory.
+target_include_directories(usermod_subpackage_example INTERFACE
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+
+target_compile_definitions(usermod_subpackage_example INTERFACE
+ MICROPY_MODULE_BUILTIN_SUBPACKAGES=1
+)
+
+# Link our INTERFACE library to the usermod target.
+target_link_libraries(usermod INTERFACE usermod_subpackage_example)
diff --git a/examples/usercmodule/subpackage/micropython.mk b/examples/usercmodule/subpackage/micropython.mk
new file mode 100644
index 0000000000000..99ebf13ec19ab
--- /dev/null
+++ b/examples/usercmodule/subpackage/micropython.mk
@@ -0,0 +1,10 @@
+SUBPACKAGE_EXAMPLE_MOD_DIR := $(USERMOD_DIR)
+
+# Add all C files to SRC_USERMOD.
+SRC_USERMOD += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/modexamplepackage.c
+
+# We can add our module folder to include paths if needed
+# This is not actually needed in this example.
+CFLAGS_USERMOD += -I$(SUBPACKAGE_EXAMPLE_MOD_DIR) -DMICROPY_MODULE_BUILTIN_SUBPACKAGES=1
+
+QSTR_DEFS += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/qstrdefsexamplepackage.h
diff --git a/examples/usercmodule/subpackage/modexamplepackage.c b/examples/usercmodule/subpackage/modexamplepackage.c
new file mode 100644
index 0000000000000..70e1e4005b30d
--- /dev/null
+++ b/examples/usercmodule/subpackage/modexamplepackage.c
@@ -0,0 +1,84 @@
+// Include MicroPython API.
+#include "py/runtime.h"
+
+// Define example_package.foo.bar.f()
+STATIC mp_obj_t example_package_foo_bar_f(void) {
+ mp_printf(&mp_plat_print, "example_package.foo.bar.f\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_bar_f_obj, example_package_foo_bar_f);
+
+// Define all attributes of the second-level sub-package (example_package.foo.bar).
+STATIC const mp_rom_map_elem_t example_package_foo_bar_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo_dot_bar) },
+ { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_bar_f_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_package_foo_bar_globals, example_package_foo_bar_globals_table);
+
+// Define example_package.foo.bar module object.
+const mp_obj_module_t example_package_foo_bar_user_cmodule = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&example_package_foo_bar_globals,
+};
+
+// Define example_package.foo.f()
+STATIC mp_obj_t example_package_foo_f(void) {
+ mp_printf(&mp_plat_print, "example_package.foo.f\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_f_obj, example_package_foo_f);
+
+// Define all attributes of the first-level sub-package (example_package.foo).
+STATIC const mp_rom_map_elem_t example_package_foo_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo) },
+ { MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&example_package_foo_bar_user_cmodule) },
+ { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_f_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_package_foo_globals, example_package_foo_globals_table);
+
+// Define example_package.foo module object.
+const mp_obj_module_t example_package_foo_user_cmodule = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&example_package_foo_globals,
+};
+
+// Define example_package.f()
+STATIC mp_obj_t example_package_f(void) {
+ mp_printf(&mp_plat_print, "example_package.f\n");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_f_obj, example_package_f);
+
+STATIC mp_obj_t example_package___init__(void) {
+ if (!MP_STATE_VM(example_package_initialised)) {
+ // __init__ for builtins is called each time the module is imported,
+ // so ensure that initialisation only happens once.
+ MP_STATE_VM(example_package_initialised) = true;
+ mp_printf(&mp_plat_print, "example_package.__init__\n");
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package___init___obj, example_package___init__);
+
+// The "initialised" state is stored on mp_state so that it is cleared on soft
+// reset.
+MP_REGISTER_ROOT_POINTER(int example_package_initialised);
+
+// Define all attributes of the top-level package (example_package).
+STATIC const mp_rom_map_elem_t example_package_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package) },
+ { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&example_package___init___obj) },
+ { MP_ROM_QSTR(MP_QSTR_foo), MP_ROM_PTR(&example_package_foo_user_cmodule) },
+ { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_f_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_package_globals, example_package_globals_table);
+
+// Define module object.
+const mp_obj_module_t example_package_user_cmodule = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&example_package_globals,
+};
+
+// Register the module to make it available in Python.
+// Note: subpackages should not be registered with MP_REGISTER_MODULE.
+MP_REGISTER_MODULE(MP_QSTR_example_package, example_package_user_cmodule);
diff --git a/examples/usercmodule/subpackage/qstrdefsexamplepackage.h b/examples/usercmodule/subpackage/qstrdefsexamplepackage.h
new file mode 100644
index 0000000000000..057ec5279d003
--- /dev/null
+++ b/examples/usercmodule/subpackage/qstrdefsexamplepackage.h
@@ -0,0 +1,2 @@
+Q(example_package.foo)
+Q(example_package.foo.bar)
diff --git a/extmod/asyncio/__init__.py b/extmod/asyncio/__init__.py
new file mode 100644
index 0000000000000..1f83750c5aafa
--- /dev/null
+++ b/extmod/asyncio/__init__.py
@@ -0,0 +1,31 @@
+# MicroPython asyncio module
+# MIT license; Copyright (c) 2019 Damien P. George
+
+from .core import *
+
+__version__ = (3, 0, 0)
+
+_attrs = {
+ "wait_for": "funcs",
+ "wait_for_ms": "funcs",
+ "gather": "funcs",
+ "Event": "event",
+ "ThreadSafeFlag": "event",
+ "Lock": "lock",
+ "open_connection": "stream",
+ "start_server": "stream",
+ "StreamReader": "stream",
+ "StreamWriter": "stream",
+}
+
+
+# Lazy loader, effectively does:
+# global attr
+# from .mod import attr
+def __getattr__(attr):
+ mod = _attrs.get(attr, None)
+ if mod is None:
+ raise AttributeError(attr)
+ value = getattr(__import__(mod, None, None, True, 1), attr)
+ globals()[attr] = value
+ return value
diff --git a/extmod/uasyncio/core.py b/extmod/asyncio/core.py
similarity index 99%
rename from extmod/uasyncio/core.py
rename to extmod/asyncio/core.py
index 10a310809c0e6..be5119ba6118a 100644
--- a/extmod/uasyncio/core.py
+++ b/extmod/asyncio/core.py
@@ -1,4 +1,4 @@
-# MicroPython uasyncio module
+# MicroPython asyncio module
# MIT license; Copyright (c) 2019 Damien P. George
from time import ticks_ms as ticks, ticks_diff, ticks_add
@@ -6,7 +6,7 @@
# Import TaskQueue and Task, preferring built-in C code over Python code
try:
- from _uasyncio import TaskQueue, Task
+ from _asyncio import TaskQueue, Task
except:
from .task import TaskQueue, Task
@@ -30,6 +30,7 @@ class TimeoutError(Exception):
################################################################################
# Sleep functions
+
# "Yield" once, then raise StopIteration
class SingletonGenerator:
def __init__(self):
@@ -132,6 +133,7 @@ def wait_io_event(self, dt):
################################################################################
# Main run loop
+
# Ensure the awaitable is a task
def _promote_to_task(aw):
return aw if isinstance(aw, Task) else create_task(aw)
diff --git a/extmod/uasyncio/event.py b/extmod/asyncio/event.py
similarity index 80%
rename from extmod/uasyncio/event.py
rename to extmod/asyncio/event.py
index c48904b9835c7..e0b41f7324244 100644
--- a/extmod/uasyncio/event.py
+++ b/extmod/asyncio/event.py
@@ -1,8 +1,9 @@
-# MicroPython uasyncio module
+# MicroPython asyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
from . import core
+
# Event class for primitive events that can be waited on, set, and cleared
class Event:
def __init__(self):
@@ -23,7 +24,8 @@ def set(self):
def clear(self):
self.state = False
- async def wait(self):
+ # async
+ def wait(self):
if not self.state:
# Event not set, put the calling task on the event's waiting queue
self.waiting.push(core.cur_task)
@@ -36,26 +38,29 @@ async def wait(self):
# MicroPython-extension: This can be set from outside the asyncio event loop,
# such as other threads, IRQs or scheduler context. Implementation is a stream
# that asyncio will poll until a flag is set.
-# Note: Unlike Event, this is self-clearing.
+# Note: Unlike Event, this is self-clearing after a wait().
try:
- import uio
+ import io
- class ThreadSafeFlag(uio.IOBase):
+ class ThreadSafeFlag(io.IOBase):
def __init__(self):
- self._flag = 0
+ self.state = 0
def ioctl(self, req, flags):
if req == 3: # MP_STREAM_POLL
- return self._flag * flags
+ return self.state * flags
return None
def set(self):
- self._flag = 1
+ self.state = 1
+
+ def clear(self):
+ self.state = 0
async def wait(self):
- if not self._flag:
+ if not self.state:
yield core._io_queue.queue_read(self)
- self._flag = 0
+ self.state = 0
except ImportError:
pass
diff --git a/extmod/uasyncio/funcs.py b/extmod/asyncio/funcs.py
similarity index 96%
rename from extmod/uasyncio/funcs.py
rename to extmod/asyncio/funcs.py
index a1d38fbcbf975..599091dfbdc2b 100644
--- a/extmod/uasyncio/funcs.py
+++ b/extmod/asyncio/funcs.py
@@ -1,10 +1,10 @@
-# MicroPython uasyncio module
+# MicroPython asyncio module
# MIT license; Copyright (c) 2019-2022 Damien P. George
from . import core
-def _run(waiter, aw):
+async def _run(waiter, aw):
try:
result = await aw
status = True
@@ -61,7 +61,11 @@ def remove(t):
pass
-async def gather(*aws, return_exceptions=False):
+# async
+def gather(*aws, return_exceptions=False):
+ if not aws:
+ return []
+
def done(t, er):
# Sub-task "t" has finished, with exception "er".
nonlocal state
@@ -119,7 +123,7 @@ def done(t, er):
# Either this gather was cancelled, or one of the sub-tasks raised an exception with
# return_exceptions==False, so reraise the exception here.
- if state is not 0:
+ if state:
raise state
# Return the list of return values of each sub-task.
diff --git a/extmod/uasyncio/lock.py b/extmod/asyncio/lock.py
similarity index 96%
rename from extmod/uasyncio/lock.py
rename to extmod/asyncio/lock.py
index f50213d7c1862..0a46ac32619d0 100644
--- a/extmod/uasyncio/lock.py
+++ b/extmod/asyncio/lock.py
@@ -1,8 +1,9 @@
-# MicroPython uasyncio module
+# MicroPython asyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
from . import core
+
# Lock class for primitive mutex capability
class Lock:
def __init__(self):
@@ -28,7 +29,8 @@ def release(self):
# No Task waiting so unlock
self.state = 0
- async def acquire(self):
+ # async
+ def acquire(self):
if self.state != 0:
# Lock unavailable, put the calling Task on the waiting queue
self.waiting.push(core.cur_task)
diff --git a/extmod/asyncio/manifest.py b/extmod/asyncio/manifest.py
new file mode 100644
index 0000000000000..e8dc7643250ac
--- /dev/null
+++ b/extmod/asyncio/manifest.py
@@ -0,0 +1,18 @@
+# This list of package files doesn't include task.py because that's provided
+# by the C module.
+package(
+ "asyncio",
+ (
+ "__init__.py",
+ "core.py",
+ "event.py",
+ "funcs.py",
+ "lock.py",
+ "stream.py",
+ ),
+ base_path="..",
+ opt=3,
+)
+
+# Backwards-compatible uasyncio module.
+module("uasyncio.py", opt=3)
diff --git a/extmod/uasyncio/stream.py b/extmod/asyncio/stream.py
similarity index 92%
rename from extmod/uasyncio/stream.py
rename to extmod/asyncio/stream.py
index 785e43555ddd9..c47c48cf09823 100644
--- a/extmod/uasyncio/stream.py
+++ b/extmod/asyncio/stream.py
@@ -1,4 +1,4 @@
-# MicroPython uasyncio module
+# MicroPython asyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
from . import core
@@ -26,7 +26,8 @@ async def wait_closed(self):
# TODO yield?
self.s.close()
- async def read(self, n=-1):
+ # async
+ def read(self, n=-1):
r = b""
while True:
yield core._io_queue.queue_read(self.s)
@@ -38,11 +39,13 @@ async def read(self, n=-1):
return r
r += r2
- async def readinto(self, buf):
+ # async
+ def readinto(self, buf):
yield core._io_queue.queue_read(self.s)
return self.s.readinto(buf)
- async def readexactly(self, n):
+ # async
+ def readexactly(self, n):
r = b""
while n:
yield core._io_queue.queue_read(self.s)
@@ -54,7 +57,8 @@ async def readexactly(self, n):
n -= len(r2)
return r
- async def readline(self):
+ # async
+ def readline(self):
l = b""
while True:
yield core._io_queue.queue_read(self.s)
@@ -73,10 +77,11 @@ def write(self, buf):
buf = buf[ret:]
self.out_buf += buf
- async def drain(self):
+ # async
+ def drain(self):
if not self.out_buf:
# Drain must always yield, so a tight loop of write+drain can't block the scheduler.
- return await core.sleep_ms(0)
+ return (yield from core.sleep_ms(0))
mv = memoryview(self.out_buf)
off = 0
while off < len(mv):
@@ -93,9 +98,11 @@ async def drain(self):
# Create a TCP stream connection to a remote host
-async def open_connection(host, port):
- from uerrno import EINPROGRESS
- import usocket as socket
+#
+# async
+def open_connection(host, port):
+ from errno import EINPROGRESS
+ import socket
ai = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0] # TODO this is blocking!
s = socket.socket(ai[0], ai[1], ai[2])
@@ -147,7 +154,7 @@ async def _serve(self, s, cb):
# Helper function to start a TCP stream server, running as a new task
# TODO could use an accept-callback on socket read activity instead of creating a task
async def start_server(cb, host, port, backlog=5):
- import usocket as socket
+ import socket
# Create and bind server socket.
host = socket.getaddrinfo(host, port)[0] # TODO this is blocking!
diff --git a/extmod/uasyncio/task.py b/extmod/asyncio/task.py
similarity index 99%
rename from extmod/uasyncio/task.py
rename to extmod/asyncio/task.py
index 4ead2a1308437..30be2170eb0a7 100644
--- a/extmod/uasyncio/task.py
+++ b/extmod/asyncio/task.py
@@ -1,4 +1,4 @@
-# MicroPython uasyncio module
+# MicroPython asyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
# This file contains the core TaskQueue based on a pairing heap, and the core Task class.
diff --git a/extmod/asyncio/uasyncio.py b/extmod/asyncio/uasyncio.py
new file mode 100644
index 0000000000000..67e6ddcfa36dd
--- /dev/null
+++ b/extmod/asyncio/uasyncio.py
@@ -0,0 +1,8 @@
+# This module just allows `import uasyncio` to work. It lazy-loads from
+# `asyncio` without duplicating its globals dict.
+
+
+def __getattr__(attr):
+ import asyncio
+
+ return getattr(asyncio, attr)
diff --git a/extmod/axtls-include/axtls_os_port.h b/extmod/axtls-include/axtls_os_port.h
index ef2683acfc701..057642f9741b7 100644
--- a/extmod/axtls-include/axtls_os_port.h
+++ b/extmod/axtls-include/axtls_os_port.h
@@ -26,7 +26,11 @@
#ifndef AXTLS_OS_PORT_H
#define AXTLS_OS_PORT_H
+#ifndef __ets__
+#include
+#endif
#include
+#include
#include "py/stream.h"
#include "lib/crypto-algorithms/sha256.h"
diff --git a/extmod/btstack/btstack.cmake b/extmod/btstack/btstack.cmake
new file mode 100644
index 0000000000000..dd416fcbfbd33
--- /dev/null
+++ b/extmod/btstack/btstack.cmake
@@ -0,0 +1,60 @@
+set(BTSTACK_LIB_DIR "${MICROPY_DIR}/lib/btstack")
+set(BTSTACK_EXTMOD_DIR "${MICROPY_DIR}/extmod/btstack")
+
+add_library(micropy_extmod_btstack INTERFACE)
+
+target_include_directories(micropy_extmod_btstack INTERFACE
+ ${MICROPY_DIR}/
+ ${MICROPY_PORT_DIR}/
+ ${BTSTACK_EXTMOD_DIR}/
+ ${BTSTACK_LIB_DIR}/src
+ ${BTSTACK_LIB_DIR}/3rd-party/bluedroid/decoder/include
+ ${BTSTACK_LIB_DIR}/3rd-party/bluedroid/encoder/include
+ ${BTSTACK_LIB_DIR}/3rd-party/md5
+ ${BTSTACK_LIB_DIR}/3rd-party/yxml
+)
+
+target_sources(micropy_extmod_btstack INTERFACE
+ ${BTSTACK_LIB_DIR}/platform/embedded/hci_dump_embedded_stdout.c
+ ${BTSTACK_LIB_DIR}/src/ad_parser.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/ancs_client.c
+ ${BTSTACK_LIB_DIR}/src/ble/att_db.c
+ ${BTSTACK_LIB_DIR}/src/ble/att_db_util.c
+ ${BTSTACK_LIB_DIR}/src/ble/att_dispatch.c
+ ${BTSTACK_LIB_DIR}/src/ble/att_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/battery_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/cycling_power_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/cycling_speed_and_cadence_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/device_information_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/heart_rate_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/hids_device.c
+ ${BTSTACK_LIB_DIR}/src/mesh/gatt-service/mesh_provisioning_service_server.c
+ ${BTSTACK_LIB_DIR}/src/mesh/gatt-service/mesh_proxy_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/nordic_spp_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt-service/ublox_spp_service_server.c
+ ${BTSTACK_LIB_DIR}/src/ble/gatt_client.c
+ ${BTSTACK_LIB_DIR}/src/ble/le_device_db_memory.c
+ ${BTSTACK_LIB_DIR}/src/ble/sm.c
+ ${BTSTACK_LIB_DIR}/src/btstack_audio.c
+ ${BTSTACK_LIB_DIR}/src/btstack_base64_decoder.c
+ ${BTSTACK_LIB_DIR}/src/btstack_crypto.c
+ ${BTSTACK_LIB_DIR}/src/btstack_hid_parser.c
+ ${BTSTACK_LIB_DIR}/src/btstack_linked_list.c
+ ${BTSTACK_LIB_DIR}/src/btstack_memory.c
+ ${BTSTACK_LIB_DIR}/src/btstack_memory_pool.c
+ ${BTSTACK_LIB_DIR}/src/btstack_resample.c
+ ${BTSTACK_LIB_DIR}/src/btstack_ring_buffer.c
+ ${BTSTACK_LIB_DIR}/src/btstack_run_loop.c
+ ${BTSTACK_LIB_DIR}/src/btstack_run_loop_base.c
+ ${BTSTACK_LIB_DIR}/src/btstack_slip.c
+ ${BTSTACK_LIB_DIR}/src/btstack_tlv.c
+ ${BTSTACK_LIB_DIR}/src/btstack_tlv_none.c
+ ${BTSTACK_LIB_DIR}/src/btstack_util.c
+ ${BTSTACK_LIB_DIR}/src/hci.c
+ ${BTSTACK_LIB_DIR}/src/hci_cmd.c
+ ${BTSTACK_LIB_DIR}/src/hci_dump.c
+ ${BTSTACK_LIB_DIR}/src/hci_transport_em9304_spi.c
+ ${BTSTACK_LIB_DIR}/src/hci_transport_h4.c
+ ${BTSTACK_LIB_DIR}/src/l2cap.c
+ ${BTSTACK_LIB_DIR}/src/l2cap_signaling.c
+)
diff --git a/extmod/btstack/btstack.mk b/extmod/btstack/btstack.mk
index 7ecc230003175..281d032ae1108 100644
--- a/extmod/btstack/btstack.mk
+++ b/extmod/btstack/btstack.mk
@@ -2,17 +2,22 @@
ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+GIT_SUBMODULES += lib/btstack
+
MICROPY_BLUETOOTH_BTSTACK_USB ?= 0
+MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1
+MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE ?= '"extmod/btstack/btstack_config_common.h"'
BTSTACK_EXTMOD_DIR = extmod/btstack
-EXTMOD_SRC_C += extmod/btstack/modbluetooth_btstack.c
+SRC_EXTMOD_C += $(BTSTACK_EXTMOD_DIR)/modbluetooth_btstack.c
INC += -I$(TOP)/$(BTSTACK_EXTMOD_DIR)
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK=1
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE=$(MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE)
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
BTSTACK_DIR = $(TOP)/lib/btstack
@@ -27,44 +32,51 @@ INC += -I$(BTSTACK_DIR)/3rd-party/bluedroid/encoder/include
INC += -I$(BTSTACK_DIR)/3rd-party/md5
INC += -I$(BTSTACK_DIR)/3rd-party/yxml
-SRC_BTSTACK = \
+SRC_BTSTACK_C = \
$(addprefix lib/btstack/src/, $(SRC_FILES)) \
$(addprefix lib/btstack/src/ble/, $(filter-out %_tlv.c, $(SRC_BLE_FILES))) \
+ lib/btstack/platform/embedded/hci_dump_embedded_stdout.c \
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
- $(error Cannot specifiy both MICROPY_BLUETOOTH_BTSTACK_USB and MICROPY_BLUETOOTH_BTSTACK_H4)
+ $(error Cannot enable both MICROPY_BLUETOOTH_BTSTACK_USB and MICROPY_BLUETOOTH_BTSTACK_H4)
+endif
+endif
+
+ifneq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
+ifneq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
+ $(error Must enable one of MICROPY_BLUETOOTH_BTSTACK_USB or MICROPY_BLUETOOTH_BTSTACK_H4)
endif
endif
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
-SRC_BTSTACK += \
+SRC_BTSTACK_C += \
lib/btstack/platform/libusb/hci_transport_h2_libusb.c
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK_USB=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_USB=1
-CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
-LDFLAGS += $(shell pkg-config libusb-1.0 --libs)
+CFLAGS_THIRDPARTY += $(shell pkg-config libusb-1.0 --cflags)
+LDFLAGS_THIRDPARTY += $(shell pkg-config libusb-1.0 --libs)
endif
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
-SRC_BTSTACK += \
+SRC_BTSTACK_C += \
lib/btstack/src/hci_transport_h4.c \
lib/btstack/chipset/zephyr/btstack_chipset_zephyr.c
-EXTMOD_SRC_C += \
+SRC_BTSTACK_C += \
extmod/btstack/btstack_hci_uart.c \
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK_H4=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_H4=1
endif
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_ENABLE_CLASSIC),1)
include $(BTSTACK_DIR)/src/classic/Makefile.inc
-SRC_BTSTACK += \
+SRC_BTSTACK_C += \
$(addprefix lib/btstack/src/classic/, $(SRC_CLASSIC_FILES))
endif
-LIB_SRC_C += $(SRC_BTSTACK)
+SRC_THIRDPARTY_C += $(SRC_BTSTACK_C)
# Suppress some warnings.
BTSTACK_WARNING_CFLAGS = -Wno-old-style-definition -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-fallthrough
diff --git a/extmod/btstack/btstack_config.h b/extmod/btstack/btstack_config.h
index e56a84f94a16d..84f0dab2bdb42 100644
--- a/extmod/btstack/btstack_config.h
+++ b/extmod/btstack/btstack_config.h
@@ -1,48 +1,6 @@
#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
#define MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
-// BTstack features that can be enabled
-#define ENABLE_BLE
-#define ENABLE_LE_PERIPHERAL
-#define ENABLE_LE_CENTRAL
-// #define ENABLE_CLASSIC
-#define ENABLE_LE_DATA_CHANNELS
-// #define ENABLE_LOG_INFO
-// #define ENABLE_LOG_DEBUG
-#define ENABLE_LOG_ERROR
-
-// BTstack configuration. buffers, sizes, ...
-#define HCI_ACL_PAYLOAD_SIZE 1021
-#define MAX_NR_GATT_CLIENTS 1
-#define MAX_NR_HCI_CONNECTIONS 1
-#define MAX_NR_L2CAP_SERVICES 3
-#define MAX_NR_L2CAP_CHANNELS 3
-#define MAX_NR_RFCOMM_MULTIPLEXERS 1
-#define MAX_NR_RFCOMM_SERVICES 1
-#define MAX_NR_RFCOMM_CHANNELS 1
-#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
-#define MAX_NR_BNEP_SERVICES 1
-#define MAX_NR_BNEP_CHANNELS 1
-#define MAX_NR_HFP_CONNECTIONS 1
-#define MAX_NR_WHITELIST_ENTRIES 1
-#define MAX_NR_SM_LOOKUP_ENTRIES 3
-#define MAX_NR_SERVICE_RECORD_ITEMS 1
-#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
-#define MAX_NR_AVDTP_CONNECTIONS 1
-#define MAX_NR_AVRCP_CONNECTIONS 1
-
-#define MAX_NR_LE_DEVICE_DB_ENTRIES 4
-
-// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
-// #define NVM_NUM_DEVICE_DB_ENTRIES 16
-
-// We don't give btstack a malloc, so use a fixed-size ATT DB.
-#define MAX_ATT_DB_SIZE 512
-
-// BTstack HAL configuration
-#define HAVE_EMBEDDED_TIME_MS
-
-// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
-#define HCI_RESET_RESEND_TIMEOUT_MS 1000
+#include MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE
#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
diff --git a/extmod/btstack/btstack_config_common.h b/extmod/btstack/btstack_config_common.h
new file mode 100644
index 0000000000000..0f616f7505e68
--- /dev/null
+++ b/extmod/btstack/btstack_config_common.h
@@ -0,0 +1,49 @@
+#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_COMMON_H
+#define MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_COMMON_H
+
+// BTstack features that can be enabled
+#define ENABLE_BLE
+#define ENABLE_LE_PERIPHERAL
+#define ENABLE_LE_CENTRAL
+// #define ENABLE_CLASSIC
+#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
+#define ENABLE_PRINTF_HEXDUMP
+// #define ENABLE_LOG_INFO
+// #define ENABLE_LOG_DEBUG
+#define ENABLE_LOG_ERROR
+
+// BTstack configuration. buffers, sizes, ...
+#define HCI_ACL_PAYLOAD_SIZE 1021
+#define MAX_NR_GATT_CLIENTS 1
+#define MAX_NR_HCI_CONNECTIONS 1
+#define MAX_NR_L2CAP_SERVICES 3
+#define MAX_NR_L2CAP_CHANNELS 3
+#define MAX_NR_RFCOMM_MULTIPLEXERS 1
+#define MAX_NR_RFCOMM_SERVICES 1
+#define MAX_NR_RFCOMM_CHANNELS 1
+#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
+#define MAX_NR_BNEP_SERVICES 1
+#define MAX_NR_BNEP_CHANNELS 1
+#define MAX_NR_HFP_CONNECTIONS 1
+#define MAX_NR_WHITELIST_ENTRIES 1
+#define MAX_NR_SM_LOOKUP_ENTRIES 3
+#define MAX_NR_SERVICE_RECORD_ITEMS 1
+#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
+#define MAX_NR_AVDTP_CONNECTIONS 1
+#define MAX_NR_AVRCP_CONNECTIONS 1
+
+#define MAX_NR_LE_DEVICE_DB_ENTRIES 4
+
+// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
+// #define NVM_NUM_DEVICE_DB_ENTRIES 16
+
+// We don't give btstack a malloc, so use a fixed-size ATT DB.
+#define MAX_ATT_DB_SIZE 512
+
+// BTstack HAL configuration
+#define HAVE_EMBEDDED_TIME_MS
+
+// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
+#define HCI_RESET_RESEND_TIMEOUT_MS 1000
+
+#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_COMMON_H
diff --git a/extmod/btstack/btstack_hci_uart.c b/extmod/btstack/btstack_hci_uart.c
index 83e865b71d2d3..f945efc762cbf 100644
--- a/extmod/btstack/btstack_hci_uart.c
+++ b/extmod/btstack/btstack_hci_uart.c
@@ -159,6 +159,12 @@ const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block = {
&btstack_uart_get_supported_sleep_modes,
&btstack_uart_set_sleep,
&btstack_uart_set_wakeup_handler,
+
+ // The following are needed for H5 mode only.
+ NULL, // set_frame_received
+ NULL, // set_frame_sent,
+ NULL, // receive_frame,
+ NULL, // send_frame,
};
void mp_bluetooth_btstack_hci_uart_process(void) {
diff --git a/extmod/btstack/btstack_hci_uart.h b/extmod/btstack/btstack_hci_uart.h
index 8011e587dee3f..74983808ec28d 100644
--- a/extmod/btstack/btstack_hci_uart.h
+++ b/extmod/btstack/btstack_hci_uart.h
@@ -28,7 +28,7 @@
#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H
#define MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H
-#include "lib/btstack/src/btstack.h"
+#include "lib/btstack/src/btstack_uart_block.h"
// --- Used by the port to create the HCI transport ---------------------------
extern const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block;
diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c
index e56e488b1c284..0c15e9343159d 100644
--- a/extmod/btstack/modbluetooth_btstack.c
+++ b/extmod/btstack/modbluetooth_btstack.c
@@ -93,156 +93,57 @@ STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(uint16_t uuid16, const uint8_t *uu
}
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
-// Notes on supporting background ops (e.g. an attempt to gatts_notify while
-// an existing notification is in progress):
-
-// GATTS Notify/Indicate (att_server_notify/indicate)
-// * When available, copies buffer immediately.
-// * Otherwise fails with BTSTACK_ACL_BUFFERS_FULL
-// * Use att_server_request_to_send_notification/indication to get callback
-// * Takes btstack_context_callback_registration_t (and takes ownership) and conn_handle.
-// * Callback is invoked with just the context member of the btstack_context_callback_registration_t
-
-// GATTC Write without response (gatt_client_write_value_of_characteristic_without_response)
-// * When available, copies buffer immediately.
-// * Otherwise, fails with GATT_CLIENT_BUSY.
-// * Use gatt_client_request_can_write_without_response_event to get callback
-// * Takes btstack_packet_handler_t (function pointer) and conn_handle
-// * Callback is invoked, use gatt_event_can_write_without_response_get_handle to get the conn_handle (no other context)
-// * There can only be one pending gatt_client_request_can_write_without_response_event (otherwise we fail with EALREADY).
-
-// GATTC Write with response (gatt_client_write_value_of_characteristic)
-// * When peripheral is available, takes ownership of buffer.
-// * Otherwise, fails with GATT_CLIENT_IN_WRONG_STATE (we fail the operation).
-// * Raises GATT_EVENT_QUERY_COMPLETE to the supplied packet handler.
-
-// For notify/indicate/write-without-response that proceed immediately, nothing extra required.
-// For all other cases, buffer needs to be copied and protected from GC.
-// For notify/indicate:
-// * btstack_context_callback_registration_t:
-// * needs to be malloc'ed
-// * needs to be protected from GC
-// * context arg needs to point back to the callback registration so it can be freed and un-protected
-// For write-without-response
-// * only the conn_handle is available in the callback
-// * so we need a queue of conn_handle->(value_handle, copied buffer)
-
-// Pending operation types.
-enum {
- // Queued for sending when possible.
- MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY, // Waiting for context callback
- MP_BLUETOOTH_BTSTACK_PENDING_INDICATE, // Waiting for context callback
- MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE, // Waiting for conn handle
- // Hold buffer pointer until complete.
- MP_BLUETOOTH_BTSTACK_PENDING_WRITE, // Waiting for write done event
-};
-
-// Pending operation:
-// - Holds a GC reference to the copied outgoing buffer.
-// - Provides enough information for the callback handler to execute the desired operation.
-struct _mp_btstack_pending_op_t {
+#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+typedef struct _mp_btstack_active_connection_t {
btstack_linked_item_t *next; // Must be first field to match btstack_linked_item.
- // See enum above.
- uint16_t op_type;
-
- // For all op types.
uint16_t conn_handle;
- uint16_t value_handle;
-
- // For notify/indicate only.
- // context_registration.context will point back to this struct.
- btstack_context_callback_registration_t context_registration;
-
- // For notify/indicate/write-without-response, this is the actual buffer to send.
- // For write-with-response, just holding onto the buffer for GC ref.
- size_t len;
- uint8_t buf[];
-};
-// Must hold MICROPY_PY_BLUETOOTH_ENTER.
-STATIC void btstack_remove_pending_operation(mp_btstack_pending_op_t *pending_op, bool del) {
- bool removed = btstack_linked_list_remove(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops, (btstack_linked_item_t *)pending_op);
- assert(removed);
- (void)removed;
- if (del) {
- m_del_var(mp_btstack_pending_op_t, uint8_t, pending_op->len, pending_op);
- }
-}
-
-// Called in response to a gatts_notify/indicate being unable to complete, which then calls
-// att_server_request_to_send_notification.
-// We now have an opportunity to re-try the operation with an empty ACL buffer.
-STATIC void btstack_notify_indicate_ready_handler(void *context) {
- MICROPY_PY_BLUETOOTH_ENTER
- mp_btstack_pending_op_t *pending_op = (mp_btstack_pending_op_t *)context;
- DEBUG_printf("btstack_notify_indicate_ready_handler op_type=%d conn_handle=%d value_handle=%d len=%zu\n", pending_op->op_type, pending_op->conn_handle, pending_op->value_handle, pending_op->len);
- if (pending_op->op_type == MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY) {
- int err = att_server_notify(pending_op->conn_handle, pending_op->value_handle, pending_op->buf, pending_op->len);
- DEBUG_printf("btstack_notify_indicate_ready_handler: sending notification err=%d\n", err);
- assert(err == ERROR_CODE_SUCCESS);
- (void)err;
- } else {
- assert(pending_op->op_type == MP_BLUETOOTH_BTSTACK_PENDING_INDICATE);
- int err = att_server_indicate(pending_op->conn_handle, pending_op->value_handle, NULL, 0);
- DEBUG_printf("btstack_notify_indicate_ready_handler: sending indication err=%d\n", err);
- assert(err == ERROR_CODE_SUCCESS);
- (void)err;
- }
- // Can't free the pending op as we're in IRQ context. Leave it for the GC.
- btstack_remove_pending_operation(pending_op, false /* del */);
- MICROPY_PY_BLUETOOTH_EXIT
-}
-
-// Register a pending background operation -- copies the buffer, and makes it known to the GC.
-STATIC mp_btstack_pending_op_t *btstack_enqueue_pending_operation(uint16_t op_type, uint16_t conn_handle, uint16_t value_handle, const uint8_t *buf, size_t len) {
- DEBUG_printf("btstack_enqueue_pending_operation op_type=%d conn_handle=%d value_handle=%d len=%zu\n", op_type, conn_handle, value_handle, len);
- mp_btstack_pending_op_t *pending_op = m_new_obj_var(mp_btstack_pending_op_t, uint8_t, len);
- pending_op->op_type = op_type;
- pending_op->conn_handle = conn_handle;
- pending_op->value_handle = value_handle;
- pending_op->len = len;
- memcpy(pending_op->buf, buf, len);
-
- if (op_type == MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY || op_type == MP_BLUETOOTH_BTSTACK_PENDING_INDICATE) {
- pending_op->context_registration.callback = &btstack_notify_indicate_ready_handler;
- pending_op->context_registration.context = pending_op;
- }
-
- MICROPY_PY_BLUETOOTH_ENTER
- bool added = btstack_linked_list_add(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops, (btstack_linked_item_t *)pending_op);
- assert(added);
+ // Read/write.
+ uint16_t pending_value_handle;
+
+ // Write only. Buffer must be retained until the operation completes.
+ uint8_t *pending_write_value;
+ size_t pending_write_value_len;
+} mp_btstack_active_connection_t;
+
+STATIC mp_btstack_active_connection_t *create_active_connection(uint16_t conn_handle) {
+ DEBUG_printf("create_active_connection: conn_handle=%d\n", conn_handle);
+ mp_btstack_active_connection_t *conn = m_new(mp_btstack_active_connection_t, 1);
+ conn->conn_handle = conn_handle;
+ conn->pending_value_handle = 0xffff;
+ conn->pending_write_value = NULL;
+ conn->pending_write_value_len = 0;
+ bool added = btstack_linked_list_add(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->active_connections, (btstack_linked_item_t *)conn);
(void)added;
- MICROPY_PY_BLUETOOTH_EXIT
-
- return pending_op;
+ assert(added);
+ return conn;
}
-#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
-
-// Cleans up a pending op of the specified type for this conn_handle (and if specified, value_handle).
-// Used by MP_BLUETOOTH_BTSTACK_PENDING_WRITE and MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE.
-// At the moment, both will set value_handle=0xffff as the events do not know their value_handle.
-// TODO: Can we make btstack give us the value_handle for regular write (with response) so that we
-// know for sure that we're using the correct entry.
-STATIC mp_btstack_pending_op_t *btstack_finish_pending_operation(uint16_t op_type, uint16_t conn_handle, uint16_t value_handle, bool del) {
- MICROPY_PY_BLUETOOTH_ENTER
- DEBUG_printf("btstack_finish_pending_operation op_type=%d conn_handle=%d value_handle=%d\n", op_type, conn_handle, value_handle);
+STATIC mp_btstack_active_connection_t *find_active_connection(uint16_t conn_handle) {
+ DEBUG_printf("find_active_connection: conn_handle=%d\n", conn_handle);
btstack_linked_list_iterator_t it;
- btstack_linked_list_iterator_init(&it, &MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops);
+ btstack_linked_list_iterator_init(&it, &MP_STATE_PORT(bluetooth_btstack_root_pointers)->active_connections);
+ mp_btstack_active_connection_t *conn = NULL;
while (btstack_linked_list_iterator_has_next(&it)) {
- mp_btstack_pending_op_t *pending_op = (mp_btstack_pending_op_t *)btstack_linked_list_iterator_next(&it);
-
- if (pending_op->op_type == op_type && pending_op->conn_handle == conn_handle && (value_handle == 0xffff || pending_op->value_handle == value_handle)) {
- DEBUG_printf("btstack_finish_pending_operation: found value_handle=%d len=%zu\n", pending_op->value_handle, pending_op->len);
- btstack_remove_pending_operation(pending_op, del);
- MICROPY_PY_BLUETOOTH_EXIT
- return del ? NULL : pending_op;
+ conn = (mp_btstack_active_connection_t *)btstack_linked_list_iterator_next(&it);
+ DEBUG_printf(" --> iter conn %d\n", conn->conn_handle);
+ if (conn->conn_handle == conn_handle) {
+ break;
}
}
- DEBUG_printf("btstack_finish_pending_operation: not found\n");
- MICROPY_PY_BLUETOOTH_EXIT
- return NULL;
+ return conn;
+}
+
+STATIC void remove_active_connection(uint16_t conn_handle) {
+ DEBUG_printf("remove_active_connection: conn_handle=%d\n", conn_handle);
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (conn) {
+ bool removed = btstack_linked_list_remove(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->active_connections, (btstack_linked_item_t *)conn);
+ (void)removed;
+ assert(removed);
+ m_del(mp_btstack_active_connection_t, conn, 1);
+ }
}
#endif
@@ -271,12 +172,14 @@ STATIC void btstack_packet_handler_att_server(uint8_t packet_type, uint16_t chan
uint8_t status = att_event_handle_value_indication_complete_get_status(packet);
mp_bluetooth_gatts_on_indicate_complete(conn_handle, value_handle, status);
} else if (event_type == ATT_EVENT_MTU_EXCHANGE_COMPLETE) {
+ DEBUG_printf(" --> att mtu exchange complete\n");
// This is triggered in peripheral mode, when exchange initiated by us or remote.
uint16_t conn_handle = att_event_mtu_exchange_complete_get_handle(packet);
uint16_t mtu = att_event_mtu_exchange_complete_get_MTU(packet);
mp_bluetooth_gatts_on_mtu_exchanged(conn_handle, mtu);
} else if (event_type == HCI_EVENT_LE_META || event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
// Ignore, duplicated by att_server.c.
+ DEBUG_printf(" --> hci att server event type: le_meta/disconnection (0x%02x)\n", event_type);
} else {
DEBUG_printf(" --> hci att server event type: unknown (0x%02x)\n", event_type);
}
@@ -290,8 +193,10 @@ STATIC bool controller_static_addr_available = false;
STATIC const uint8_t read_static_address_command_complete_prefix[] = { 0x0e, 0x1b, 0x01, 0x09, 0xfc };
#endif
-STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t irq) {
- DEBUG_printf("btstack_packet_handler(packet_type=%u, packet=%p)\n", packet_type, packet);
+STATIC void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ DEBUG_printf("btstack_packet_handler_generic(packet_type=%u, packet=%p)\n", packet_type, packet);
if (packet_type != HCI_EVENT_PACKET) {
return;
}
@@ -314,6 +219,9 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
// Slave role.
irq_event = MP_BLUETOOTH_IRQ_CENTRAL_CONNECT;
}
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ create_active_connection(conn_handle);
+ #endif
mp_bluetooth_gap_on_connected_disconnected(irq_event, conn_handle, addr_type, addr);
break;
}
@@ -368,7 +276,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
event_type == SM_EVENT_PAIRING_COMPLETE ||
// event_type == GAP_EVENT_DEDICATED_BONDING_COMPLETED || // No conn_handle
event_type == HCI_EVENT_ENCRYPTION_CHANGE) {
- DEBUG_printf(" --> enc/auth/pair/bond change\n", );
+ DEBUG_printf(" --> enc/auth/pair/bond change\n");
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
uint16_t conn_handle;
switch (event_type) {
@@ -407,6 +315,9 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
}
uint8_t addr[6] = {0};
mp_bluetooth_gap_on_connected_disconnected(irq_event, conn_handle, 0xff, addr);
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ remove_active_connection(conn_handle);
+ #endif
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
} else if (event_type == GAP_EVENT_ADVERTISING_REPORT) {
DEBUG_printf(" --> gap advertising report\n");
@@ -420,51 +331,12 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
mp_bluetooth_gap_on_scan_result(address_type, address, adv_event_type, rssi, data, length);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
- } else if (event_type == GATT_EVENT_QUERY_COMPLETE) {
- uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
- uint16_t status = gatt_event_query_complete_get_att_status(packet);
- DEBUG_printf(" --> gatt query complete irq=%d conn_handle=%d status=%d\n", irq, conn_handle, status);
- if (irq == MP_BLUETOOTH_IRQ_GATTC_READ_DONE || irq == MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE) {
- // TODO there is no value_handle available to pass here.
- // TODO try and get this implemented in btstack.
- mp_bluetooth_gattc_on_read_write_status(irq, conn_handle, 0xffff, status);
- // Unref the saved buffer for the write operation on this conn_handle.
- if (irq == MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE) {
- btstack_finish_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE, conn_handle, 0xffff, false /* del */);
- }
- } else if (irq == MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE ||
- irq == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE ||
- irq == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE) {
- mp_bluetooth_gattc_on_discover_complete(irq, conn_handle, status);
- }
- } else if (event_type == GATT_EVENT_SERVICE_QUERY_RESULT) {
- DEBUG_printf(" --> gatt service query result\n");
- uint16_t conn_handle = gatt_event_service_query_result_get_handle(packet);
- gatt_client_service_t service;
- gatt_event_service_query_result_get_service(packet, &service);
- mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(service.uuid16, service.uuid128);
- mp_bluetooth_gattc_on_primary_service_result(conn_handle, service.start_group_handle, service.end_group_handle, &service_uuid);
- } else if (event_type == GATT_EVENT_CHARACTERISTIC_QUERY_RESULT) {
- DEBUG_printf(" --> gatt characteristic query result\n");
- uint16_t conn_handle = gatt_event_characteristic_query_result_get_handle(packet);
- gatt_client_characteristic_t characteristic;
- gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
- mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(characteristic.uuid16, characteristic.uuid128);
- mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.start_handle, characteristic.value_handle, characteristic.properties, &characteristic_uuid);
- } else if (event_type == GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT) {
- DEBUG_printf(" --> gatt descriptor query result\n");
- uint16_t conn_handle = gatt_event_all_characteristic_descriptors_query_result_get_handle(packet);
- gatt_client_characteristic_descriptor_t descriptor;
- gatt_event_all_characteristic_descriptors_query_result_get_characteristic_descriptor(packet, &descriptor);
- mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(descriptor.uuid16, descriptor.uuid128);
- mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor.handle, &descriptor_uuid);
- } else if (event_type == GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT) {
- DEBUG_printf(" --> gatt characteristic value query result\n");
- uint16_t conn_handle = gatt_event_characteristic_value_query_result_get_handle(packet);
- uint16_t value_handle = gatt_event_characteristic_value_query_result_get_value_handle(packet);
- uint16_t len = gatt_event_characteristic_value_query_result_get_value_length(packet);
- const uint8_t *data = gatt_event_characteristic_value_query_result_get_value(packet);
- mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, value_handle, &data, &len, 1);
+ } else if (event_type == GATT_EVENT_MTU) {
+ // This is triggered in central mode.
+ DEBUG_printf(" --> gatt event mtu\n");
+ uint16_t conn_handle = gatt_event_mtu_get_handle(packet);
+ uint16_t mtu = gatt_event_mtu_get_MTU(packet);
+ mp_bluetooth_gatts_on_mtu_exchanged(conn_handle, mtu);
} else if (event_type == GATT_EVENT_NOTIFICATION) {
DEBUG_printf(" --> gatt notification\n");
uint16_t conn_handle = gatt_event_notification_get_handle(packet);
@@ -482,28 +354,24 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
} else if (event_type == GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE) {
uint16_t conn_handle = gatt_event_can_write_without_response_get_handle(packet);
DEBUG_printf(" --> gatt can write without response %d\n", conn_handle);
- mp_btstack_pending_op_t *pending_op = btstack_finish_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE, conn_handle, 0xffff, false /* !del */);
- if (pending_op) {
- DEBUG_printf(" --> ready for value_handle=%d len=%zu\n", pending_op->value_handle, pending_op->len);
- gatt_client_write_value_of_characteristic_without_response(pending_op->conn_handle, pending_op->value_handle, pending_op->len, (uint8_t *)pending_op->buf);
- // Note: Can't "del" the pending_op from IRQ context. Leave it for the GC.
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn || conn->pending_value_handle == 0xffff || !conn->pending_write_value) {
+ return;
}
-
+ DEBUG_printf(" --> ready for value_handle=%d len=%lu\n", conn->pending_value_handle, conn->pending_write_value_len);
+ int err = gatt_client_write_value_of_characteristic_without_response(conn_handle, conn->pending_value_handle, conn->pending_write_value_len, conn->pending_write_value);
+ (void)err;
+ assert(err == ERROR_CODE_SUCCESS);
+ conn->pending_value_handle = 0xffff;
+ m_del(uint8_t, conn->pending_write_value, conn->pending_write_value_len);
+ conn->pending_write_value = NULL;
+ conn->pending_write_value_len = 0;
#endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
} else {
DEBUG_printf(" --> hci event type: unknown (0x%02x)\n", event_type);
}
}
-// Because the packet handler callbacks don't support an argument, we use a specific
-// handler when we need to provide additional state to the handler (in the "irq" parameter).
-// This is the generic handler for when you don't need extra state.
-STATIC void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
- (void)channel;
- (void)size;
- btstack_packet_handler(packet_type, packet, 0);
-}
-
STATIC btstack_packet_callback_registration_t hci_event_callback_registration = {
.callback = &btstack_packet_handler_generic
};
@@ -513,35 +381,121 @@ STATIC btstack_packet_callback_registration_t hci_event_callback_registration =
STATIC void btstack_packet_handler_discover_services(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void)channel;
(void)size;
- btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_SERVICE_QUERY_RESULT) {
+ DEBUG_printf(" --> gatt service query result\n");
+ uint16_t conn_handle = gatt_event_service_query_result_get_handle(packet);
+ gatt_client_service_t service;
+ gatt_event_service_query_result_get_service(packet, &service);
+ mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(service.uuid16, service.uuid128);
+ mp_bluetooth_gattc_on_primary_service_result(conn_handle, service.start_group_handle, service.end_group_handle, &service_uuid);
+ } else if (event_type == GATT_EVENT_QUERY_COMPLETE) {
+ uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
+ uint16_t status = gatt_event_query_complete_get_att_status(packet);
+ DEBUG_printf(" --> gatt query services complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE, conn_handle, status);
+ }
}
// For when the handler is being used for characteristic discovery.
STATIC void btstack_packet_handler_discover_characteristics(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void)channel;
(void)size;
- btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_CHARACTERISTIC_QUERY_RESULT) {
+ DEBUG_printf(" --> gatt characteristic query result\n");
+ uint16_t conn_handle = gatt_event_characteristic_query_result_get_handle(packet);
+ gatt_client_characteristic_t characteristic;
+ gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
+ mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(characteristic.uuid16, characteristic.uuid128);
+ mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.value_handle, characteristic.end_handle, characteristic.properties, &characteristic_uuid);
+ } else if (event_type == GATT_EVENT_QUERY_COMPLETE) {
+ uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
+ uint16_t status = gatt_event_query_complete_get_att_status(packet);
+ DEBUG_printf(" --> gatt query characteristics complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE, conn_handle, status);
+ }
}
// For when the handler is being used for descriptor discovery.
STATIC void btstack_packet_handler_discover_descriptors(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void)channel;
(void)size;
- btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT) {
+ DEBUG_printf(" --> gatt descriptor query result\n");
+ uint16_t conn_handle = gatt_event_all_characteristic_descriptors_query_result_get_handle(packet);
+ gatt_client_characteristic_descriptor_t descriptor;
+ gatt_event_all_characteristic_descriptors_query_result_get_characteristic_descriptor(packet, &descriptor);
+ mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(descriptor.uuid16, descriptor.uuid128);
+ mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor.handle, &descriptor_uuid);
+ } else if (event_type == GATT_EVENT_QUERY_COMPLETE) {
+ uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
+ uint16_t status = gatt_event_query_complete_get_att_status(packet);
+ DEBUG_printf(" --> gatt query descriptors complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE, conn_handle, status);
+ }
}
// For when the handler is being used for a read query.
STATIC void btstack_packet_handler_read(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void)channel;
(void)size;
- btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_READ_DONE);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_QUERY_COMPLETE) {
+ uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
+ uint16_t status = gatt_event_query_complete_get_att_status(packet);
+ DEBUG_printf(" --> gatt query read complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ return;
+ }
+ mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_READ_DONE, conn_handle, conn->pending_value_handle, status);
+ conn->pending_value_handle = 0xffff;
+ } else if (event_type == GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT) {
+ DEBUG_printf(" --> gatt characteristic value query result\n");
+ uint16_t conn_handle = gatt_event_characteristic_value_query_result_get_handle(packet);
+ uint16_t value_handle = gatt_event_characteristic_value_query_result_get_value_handle(packet);
+ uint16_t len = gatt_event_characteristic_value_query_result_get_value_length(packet);
+ const uint8_t *data = gatt_event_characteristic_value_query_result_get_value(packet);
+ mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, value_handle, &data, &len, 1);
+ }
}
// For when the handler is being used for write-with-response.
STATIC void btstack_packet_handler_write_with_response(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
(void)channel;
(void)size;
- btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_QUERY_COMPLETE) {
+ uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
+ uint16_t status = gatt_event_query_complete_get_att_status(packet);
+ DEBUG_printf(" --> gatt query write complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ return;
+ }
+ mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE, conn_handle, conn->pending_value_handle, status);
+ conn->pending_value_handle = 0xffff;
+ m_del(uint8_t, conn->pending_write_value, conn->pending_write_value_len);
+ conn->pending_write_value = NULL;
+ conn->pending_write_value_len = 0;
+ }
}
#endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
@@ -590,8 +544,6 @@ STATIC void set_random_address(void) {
DEBUG_printf("set_random_address: Generating static address using mp_hal_get_mac\n");
mp_hal_get_mac(MP_HAL_MAC_BDADDR, static_addr);
- // Mark it as STATIC (not RPA or NRPA).
- static_addr[0] |= 0xc0;
#else
@@ -604,6 +556,8 @@ STATIC void set_random_address(void) {
}
#endif // MICROPY_BLUETOOTH_USE_MP_HAL_GET_MAC_STATIC_ADDRESS
+ // Mark it as STATIC (not RPA or NRPA).
+ static_addr[0] |= 0xc0;
DEBUG_printf("set_random_address: Address generated.\n");
gap_random_address_set(static_addr);
@@ -625,6 +579,19 @@ STATIC void set_random_address(void) {
DEBUG_printf("set_random_address: Address loaded by controller\n");
}
+STATIC void deinit_stack(void) {
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
+
+ // Deinitialise BTstack components.
+ sm_deinit();
+ l2cap_deinit();
+ hci_deinit();
+ btstack_memory_deinit();
+ btstack_run_loop_deinit();
+
+ MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL;
+}
+
int mp_bluetooth_init(void) {
DEBUG_printf("mp_bluetooth_init\n");
@@ -702,8 +669,8 @@ int mp_bluetooth_init(void) {
// Attempt a shutdown (may not do anything).
mp_bluetooth_btstack_port_deinit();
- // Clean up.
- MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL;
+ // Clean up BTstack.
+ deinit_stack();
return timeout ? MP_ETIMEDOUT : MP_EINVAL;
}
@@ -726,6 +693,13 @@ int mp_bluetooth_init(void) {
gatt_client_listen_for_characteristic_value_updates(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->notification, &btstack_packet_handler_generic, GATT_CLIENT_ANY_CONNECTION, NULL);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ // Always include at least the standard GAP and GATT default services. A
+ // peripheral (likely a server) will almost always override this with its
+ // own services, but a central should get the default services, e.g. so
+ // the remote end can find out its GAP name.
+ mp_bluetooth_gatts_register_service_begin(false);
+ mp_bluetooth_gatts_register_service_end();
+
return 0;
}
@@ -757,8 +731,8 @@ void mp_bluetooth_deinit(void) {
}
btstack_run_loop_remove_timer(&btstack_init_deinit_timeout);
- mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
- MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL;
+ // Clean up BTstack.
+ deinit_stack();
DEBUG_printf("mp_bluetooth_deinit: complete\n");
}
@@ -836,7 +810,7 @@ void mp_bluetooth_set_io_capability(uint8_t capability) {
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) {
- uint8_t *value = NULL;
+ const uint8_t *value = NULL;
size_t value_len = 0;
mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, BTSTACK_GAP_DEVICE_NAME_HANDLE, &value, &value_len);
*buf = value;
@@ -909,14 +883,14 @@ int mp_bluetooth_gatts_register_service_begin(bool append) {
if (!append) {
// This will reset the DB.
- // Becase the DB is statically allocated, there's no problem with just re-initing it.
+ // Because the DB is statically allocated, there's no problem with just re-initing it.
// Note this would be a memory leak if we enabled HAVE_MALLOC (there's no API to free the existing db).
att_db_util_init();
att_db_util_add_service_uuid16(GAP_SERVICE_UUID);
uint16_t handle = att_db_util_add_characteristic_uuid16(GAP_DEVICE_NAME_UUID, ATT_PROPERTY_READ | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0);
- assert(handle == BTSTACK_GAP_DEVICE_NAME_HANDLE);
(void)handle;
+ assert(handle == BTSTACK_GAP_DEVICE_NAME_HANDLE);
att_db_util_add_service_uuid16(0x1801);
att_db_util_add_characteristic_uuid16(0x2a05, ATT_PROPERTY_READ, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0);
@@ -968,7 +942,11 @@ STATIC int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_h
entry->data_len = MIN(entry->data_alloc, buffer_size + append_offset);
memcpy(entry->data + append_offset, buffer, entry->data_len - append_offset);
- mp_bluetooth_gatts_on_write(connection_handle, att_handle);
+ uint16_t handle_uuid = att_uuid_for_handle(att_handle);
+ if (handle_uuid != GATT_CLIENT_CHARACTERISTICS_CONFIGURATION) {
+ // Suppress the Python callback for writes to the CCCD.
+ mp_bluetooth_gatts_on_write(connection_handle, att_handle);
+ }
return 0;
}
@@ -1020,7 +998,7 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
size_t handle_index = 0;
size_t descriptor_index = 0;
- static uint8_t cccb_buf[2] = {0};
+ static uint8_t cccd_buf[2] = {0};
for (size_t i = 0; i < num_characteristics; ++i) {
uint16_t props = (characteristic_flags[i] & 0x7f) | ATT_PROPERTY_DYNAMIC;
@@ -1036,11 +1014,11 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
return MP_EINVAL;
}
mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index], MP_BLUETOOTH_DEFAULT_ATTR_LEN);
- // If a NOTIFY or INDICATE characteristic is added, then we need to manage a value for the CCCB.
+ // If a NOTIFY or INDICATE characteristic is added, then we need to manage a value for the CCCD.
if (props & (ATT_PROPERTY_NOTIFY | ATT_PROPERTY_INDICATE)) {
- // btstack creates the CCCB as the next handle.
- mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, MP_BLUETOOTH_CCCB_LEN);
- int ret = mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, cccb_buf, sizeof(cccb_buf));
+ // btstack automatically creates the CCCD as the next handle if the notify or indicate properties are set.
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, MP_BLUETOOTH_CCCD_LEN);
+ int ret = mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, cccd_buf, sizeof(cccd_buf));
if (ret) {
return ret;
}
@@ -1077,7 +1055,7 @@ int mp_bluetooth_gatts_register_service_end(void) {
return 0;
}
-int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) {
+int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len) {
DEBUG_printf("mp_bluetooth_gatts_read\n");
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
@@ -1091,90 +1069,152 @@ int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
if (send_update) {
- return MP_EOPNOTSUPP;
+ DEBUG_printf(" --> send_update\n");
+ // If a characteristic has notify or indicate set, then btstack automatically creates the CCCD as the next handle.
+ // So if the next handle is a CCCD, then this characteristic must have had notify/indicate set.
+ uint16_t next_handle_uuid = att_uuid_for_handle(value_handle + 1);
+ if (next_handle_uuid != GATT_CLIENT_CHARACTERISTICS_CONFIGURATION) {
+ return MP_EINVAL;
+ }
+ DEBUG_printf(" --> got handle for cccd: %d\n", value_handle + 1);
+ }
+ int err = mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, value, value_len);
+ if (!send_update || err) {
+ return err;
}
- return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, value, value_len);
-}
-int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) {
- DEBUG_printf("mp_bluetooth_gatts_notify\n");
+ // Read the CCCD value. TODO: These should be per-connection.
+ const uint8_t *cccd;
+ size_t cccd_len;
+ err = mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle + 1, &cccd, &cccd_len);
+ if (cccd_len != 2 || err) {
+ return err;
+ }
- if (!mp_bluetooth_is_active()) {
- return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ // Notify/indicate all active connections.
+ btstack_linked_list_iterator_t it;
+ hci_connections_get_iterator(&it);
+ while (btstack_linked_list_iterator_has_next(&it)) {
+ hci_connection_t *connection = (hci_connection_t *)btstack_linked_list_iterator_next(&it);
+ if (cccd[0] & 1) {
+ err = mp_bluetooth_gatts_notify_indicate(connection->con_handle, value_handle, MP_BLUETOOTH_GATTS_OP_NOTIFY, value, value_len);
+ if (err) {
+ return err;
+ }
+ }
+ if (cccd[0] & 2) {
+ err = mp_bluetooth_gatts_notify_indicate(connection->con_handle, value_handle, MP_BLUETOOTH_GATTS_OP_INDICATE, value, value_len);
+ if (err) {
+ return err;
+ }
+ }
}
- // Note: btstack doesn't appear to support sending a notification without a value, so include the stored value.
- uint8_t *data = NULL;
- size_t len = 0;
- mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
- return mp_bluetooth_gatts_notify_send(conn_handle, value_handle, data, len);
+ return 0;
}
-int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len) {
- DEBUG_printf("mp_bluetooth_gatts_notify_send\n");
+#if !MICROPY_TRACKED_ALLOC
+#error "btstack requires MICROPY_TRACKED_ALLOC"
+#endif
- if (!mp_bluetooth_is_active()) {
- return ERRNO_BLUETOOTH_NOT_ACTIVE;
- }
+typedef struct {
+ btstack_context_callback_registration_t btstack_registration;
+ int gatts_op;
+ uint16_t conn_handle;
+ uint16_t value_handle;
+ size_t value_len;
+ uint8_t value[];
+} notify_indicate_pending_op_t;
- // Attempt to send immediately. If it succeeds, btstack will copy the buffer.
+// Called in response to a gatts_notify/indicate being unable to complete, which then calls
+// att_server_request_to_send_notification.
+STATIC void btstack_notify_indicate_ready_handler(void *context) {
MICROPY_PY_BLUETOOTH_ENTER
- int err = att_server_notify(conn_handle, value_handle, value, value_len);
- MICROPY_PY_BLUETOOTH_EXIT
-
- if (err == BTSTACK_ACL_BUFFERS_FULL) {
- DEBUG_printf("mp_bluetooth_gatts_notify_send: ACL buffer full, scheduling callback\n");
- // Schedule callback, making a copy of the buffer.
- mp_btstack_pending_op_t *pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY, conn_handle, value_handle, value, value_len);
-
- err = att_server_request_to_send_notification(&pending_op->context_registration, conn_handle);
-
- if (err != ERROR_CODE_SUCCESS) {
- // Failure. Unref and free the pending operation.
- btstack_remove_pending_operation(pending_op, true /* del */);
- }
-
- return 0;
- } else {
- return btstack_error_to_errno(err);
+ notify_indicate_pending_op_t *pending_op = (notify_indicate_pending_op_t *)context;
+ DEBUG_printf("btstack_notify_indicate_ready_handler gatts_op=%d conn_handle=%d value_handle=%d len=%lu\n", pending_op->gatts_op, pending_op->conn_handle, pending_op->value_handle, pending_op->value_len);
+ int err = ERROR_CODE_SUCCESS;
+ switch (pending_op->gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = att_server_notify(pending_op->conn_handle, pending_op->value_handle, pending_op->value, pending_op->value_len);
+ DEBUG_printf("btstack_notify_indicate_ready_handler: sending notification err=%d\n", err);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ err = att_server_indicate(pending_op->conn_handle, pending_op->value_handle, pending_op->value, pending_op->value_len);
+ DEBUG_printf("btstack_notify_indicate_ready_handler: sending indication err=%d\n", err);
+ break;
}
+ assert(err == ERROR_CODE_SUCCESS);
+ (void)err;
+ MICROPY_PY_BLUETOOTH_EXIT
+ m_tracked_free(pending_op);
}
-int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
- DEBUG_printf("mp_bluetooth_gatts_indicate\n");
+int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len) {
+ DEBUG_printf("mp_bluetooth_gatts_notify_indicate: gatts_op=%d\n", gatts_op);
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- uint8_t *data = NULL;
- size_t len = 0;
- mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
+ if (!value) {
+ // NULL value means "use DB value".
+ mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &value, &value_len);
+ }
- // Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
- // acknowledged (or timeout/error).
+ // Even if a lower MTU is negotiated, btstack allows sending a larger
+ // notification/indication. Truncate at the MTU-3 (to match NimBLE).
+ uint16_t current_mtu = att_server_get_mtu(conn_handle);
+ if (current_mtu) {
+ current_mtu -= 3;
+ value_len = MIN(value_len, current_mtu);
+ }
- // Attempt to send immediately, will copy buffer.
+ int err = ERROR_CODE_UNKNOWN_HCI_COMMAND;
+
+ // Attempt to send immediately. If it succeeds, btstack will copy the buffer.
MICROPY_PY_BLUETOOTH_ENTER
- int err = att_server_indicate(conn_handle, value_handle, data, len);
+ switch (gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = att_server_notify(conn_handle, value_handle, value, value_len);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ // Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
+ // acknowledged (or timeout/error).
+ err = att_server_indicate(conn_handle, value_handle, value, value_len);
+ break;
+ }
MICROPY_PY_BLUETOOTH_EXIT
- if (err == BTSTACK_ACL_BUFFERS_FULL) {
- DEBUG_printf("mp_bluetooth_gatts_indicate: ACL buffer full, scheduling callback\n");
- // Schedule callback, making a copy of the buffer.
- mp_btstack_pending_op_t *pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_INDICATE, conn_handle, value_handle, data, len);
-
- err = att_server_request_to_send_indication(&pending_op->context_registration, conn_handle);
+ if (err == BTSTACK_ACL_BUFFERS_FULL || err == ATT_HANDLE_VALUE_INDICATION_IN_PROGRESS) {
+ DEBUG_printf("mp_bluetooth_gatts_notify_indicate: ACL buffer full / indication in progress, scheduling callback\n");
+
+ // Copy the value and ask btstack to let us know when it can be sent.
+ notify_indicate_pending_op_t *pending_op = m_tracked_calloc(1, sizeof(notify_indicate_pending_op_t) + value_len);
+ pending_op->btstack_registration.context = pending_op;
+ pending_op->btstack_registration.callback = &btstack_notify_indicate_ready_handler;
+ pending_op->gatts_op = gatts_op;
+ pending_op->conn_handle = conn_handle;
+ pending_op->value_handle = value_handle;
+ pending_op->value_len = value_len;
+ memcpy(pending_op->value, value, value_len);
+
+ MICROPY_PY_BLUETOOTH_ENTER
+ switch (gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = att_server_request_to_send_notification(&pending_op->btstack_registration, conn_handle);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ err = att_server_request_to_send_indication(&pending_op->btstack_registration, conn_handle);
+ break;
+ }
+ MICROPY_PY_BLUETOOTH_EXIT
if (err != ERROR_CODE_SUCCESS) {
- // Failure. Unref and free the pending operation.
- btstack_remove_pending_operation(pending_op, true /* del */);
+ m_tracked_free(pending_op);
}
-
- return 0;
- } else {
- return btstack_error_to_errno(err);
}
+
+ return btstack_error_to_errno(err);
}
int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {
@@ -1358,9 +1398,9 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start
}
gatt_client_characteristic_t characteristic = {
- // Only start/end handles needed for gatt_client_discover_characteristic_descriptors.
- .start_handle = start_handle,
- .value_handle = 0,
+ // Only value/end handles needed for gatt_client_discover_characteristic_descriptors.
+ .start_handle = 0,
+ .value_handle = start_handle,
.end_handle = end_handle,
.properties = 0,
.uuid16 = 0,
@@ -1374,58 +1414,99 @@ int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) {
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- return btstack_error_to_errno(gatt_client_read_value_of_characteristic_using_value_handle(&btstack_packet_handler_read, conn_handle, value_handle));
+
+ // There can only be a single pending GATT client operation per connection.
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ DEBUG_printf(" --> no active connection %d\n", conn_handle);
+ return MP_ENOTCONN;
+ }
+ if (conn->pending_value_handle != 0xffff) {
+ // There's either a read in progress, a write-with-response in progress, or a pending can-write-without-response request outstanding.
+ DEBUG_printf("--> busy\n");
+ return MP_EALREADY;
+ }
+ conn->pending_value_handle = value_handle;
+ int err = gatt_client_read_value_of_characteristic_using_value_handle(&btstack_packet_handler_read, conn_handle, value_handle);
+ if (err != ERROR_CODE_SUCCESS) {
+ DEBUG_printf("--> can't send read %d\n", err);
+ conn->pending_value_handle = 0xffff;
+ }
+ return btstack_error_to_errno(err);
}
-int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) {
+int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len, unsigned int mode) {
DEBUG_printf("mp_bluetooth_gattc_write\n");
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- // We should be distinguishing between gatt_client_write_value_of_characteristic vs
+ // Note: We should be distinguishing between gatt_client_write_value_of_characteristic vs
// gatt_client_write_characteristic_descriptor_using_descriptor_handle.
// However both are implemented using send_gatt_write_attribute_value_request under the hood,
// and we get the exact same event to the packet handler.
// Same story for the "without response" version.
int err;
- mp_btstack_pending_op_t *pending_op = NULL;
if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) {
- // If possible, this will send immediately, copying the buffer directly to the ACL buffer.
- err = gatt_client_write_value_of_characteristic_without_response(conn_handle, value_handle, *value_len, (uint8_t *)value);
- if (err == GATT_CLIENT_BUSY) {
- DEBUG_printf("mp_bluetooth_gattc_write: client busy\n");
- // Can't send right now, need to take a copy of the buffer and add it to the queue.
- pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE, conn_handle, value_handle, value, *value_len);
- // Notify when this conn_handle can write.
- err = gatt_client_request_can_write_without_response_event(&btstack_packet_handler_generic, conn_handle);
- } else {
- DEBUG_printf("mp_bluetooth_gattc_write: other failure: %d\n", err);
+ // Simplest case -- if the write can be dispatched directly, then the buffer is copied directly to the ACL buffer.
+ err = gatt_client_write_value_of_characteristic_without_response(conn_handle, value_handle, value_len, (uint8_t *)value);
+ if (err != GATT_CLIENT_BUSY) {
+ DEBUG_printf("--> can't send write-without-response %d\n", err);
+ return btstack_error_to_errno(err);
}
+ }
+
+ // There can only be a single pending read/write request per connection.
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ DEBUG_printf(" --> no active connection %d\n", conn_handle);
+ return MP_ENOTCONN;
+ }
+ if (conn->pending_value_handle != 0xffff) {
+ // There's either a read in progress, a write-with-response in progress, or a pending can-write-without-response request outstanding.
+ DEBUG_printf(" --> busy\n");
+ return MP_EALREADY;
+ }
+ conn->pending_value_handle = value_handle;
+ conn->pending_write_value_len = value_len;
+ conn->pending_write_value = m_new(uint8_t, value_len);
+ memcpy(conn->pending_write_value, value, value_len);
+
+ if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) {
+ DEBUG_printf(" --> client busy\n");
+ // Raise the GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE event when
+ // write-without-response will succeed. The only way this fails is if
+ // there's an outstanding request (unlike for the server-equivalent,
+ // att_server_request_to_send_notification, which has a queue) but
+ // we've already checked that there isn't one.
+ err = gatt_client_request_can_write_without_response_event(&btstack_packet_handler_generic, conn_handle);
} else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) {
- // Pending operation copies the value buffer and keeps a GC reference
- // until the response comes back (there is always a response).
- pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE, conn_handle, value_handle, value, *value_len);
- err = gatt_client_write_value_of_characteristic(&btstack_packet_handler_write_with_response, conn_handle, value_handle, pending_op->len, pending_op->buf);
+ // Attempt to write immediately. This can fail if there's another
+ // client operation in progress (e.g. discover).
+ err = gatt_client_write_value_of_characteristic(&btstack_packet_handler_write_with_response, conn_handle, value_handle, value_len, conn->pending_write_value);
} else {
return MP_EINVAL;
}
- if (pending_op && err != ERROR_CODE_SUCCESS) {
- // Failure. Unref and free the pending operation.
- btstack_remove_pending_operation(pending_op, true /* del */);
+ if (err != ERROR_CODE_SUCCESS) {
+ DEBUG_printf("--> write failed %d\n", err);
+ // We knew that there was no read/write in progress, but some other
+ // client operation is in progress, so release the pending state.
+ m_del(uint8_t, conn->pending_write_value, value_len);
+ conn->pending_write_value_len = 0;
+ conn->pending_value_handle = 0xffff;
}
return btstack_error_to_errno(err);
}
int mp_bluetooth_gattc_exchange_mtu(uint16_t conn_handle) {
- DEBUG_printf("mp_bluetooth_exchange_mtu: conn_handle=%d mtu=%d\n", conn_handle, l2cap_max_le_mtu());
+ DEBUG_printf("mp_bluetooth_gattc_exchange_mtu: conn_handle=%d mtu=%d\n", conn_handle, l2cap_max_le_mtu());
- gatt_client_send_mtu_negotiation(&btstack_packet_handler_att_server, conn_handle);
+ gatt_client_send_mtu_negotiation(&btstack_packet_handler_generic, conn_handle);
return 0;
}
@@ -1460,4 +1541,6 @@ int mp_bluetooth_l2cap_recvinto(uint16_t conn_handle, uint16_t cid, uint8_t *buf
#endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
+MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers);
+
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
diff --git a/extmod/btstack/modbluetooth_btstack.h b/extmod/btstack/modbluetooth_btstack.h
index 7890bbfae2c4a..7f4a1820737ad 100644
--- a/extmod/btstack/modbluetooth_btstack.h
+++ b/extmod/btstack/modbluetooth_btstack.h
@@ -33,8 +33,6 @@
#include "lib/btstack/src/btstack.h"
-typedef struct _mp_btstack_pending_op_t mp_btstack_pending_op_t;
-
typedef struct _mp_bluetooth_btstack_root_pointers_t {
// This stores both the advertising data and the scan response data, concatenated together.
uint8_t *adv_data;
@@ -44,11 +42,12 @@ typedef struct _mp_bluetooth_btstack_root_pointers_t {
// Characteristic (and descriptor) value storage.
mp_gatts_db_t gatts_db;
- btstack_linked_list_t pending_ops;
-
- #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
// Registration for notify/indicate events.
gatt_client_notification_t notification;
+
+ // Active connections (only used for GATT clients).
+ btstack_linked_list_t active_connections;
#endif
} mp_bluetooth_btstack_root_pointers_t;
diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake
index 8fe83a0ada347..67f33cf91f89b 100644
--- a/extmod/extmod.cmake
+++ b/extmod/extmod.cmake
@@ -6,6 +6,7 @@ set(MICROPY_OOFATFS_DIR "${MICROPY_DIR}/lib/oofatfs")
set(MICROPY_SOURCE_EXTMOD
${MICROPY_DIR}/shared/libc/abort_.c
${MICROPY_DIR}/shared/libc/printf.c
+ ${MICROPY_EXTMOD_DIR}/btstack/modbluetooth_btstack.c
${MICROPY_EXTMOD_DIR}/machine_bitstream.c
${MICROPY_EXTMOD_DIR}/machine_i2c.c
${MICROPY_EXTMOD_DIR}/machine_mem.c
@@ -18,27 +19,30 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/modlwip.c
${MICROPY_EXTMOD_DIR}/modnetwork.c
${MICROPY_EXTMOD_DIR}/modonewire.c
- ${MICROPY_EXTMOD_DIR}/moduasyncio.c
- ${MICROPY_EXTMOD_DIR}/modubinascii.c
- ${MICROPY_EXTMOD_DIR}/moducryptolib.c
+ ${MICROPY_EXTMOD_DIR}/modasyncio.c
+ ${MICROPY_EXTMOD_DIR}/modbinascii.c
+ ${MICROPY_EXTMOD_DIR}/modcryptolib.c
${MICROPY_EXTMOD_DIR}/moductypes.c
- ${MICROPY_EXTMOD_DIR}/moduhashlib.c
- ${MICROPY_EXTMOD_DIR}/moduheapq.c
- ${MICROPY_EXTMOD_DIR}/modujson.c
- ${MICROPY_EXTMOD_DIR}/moduos.c
- ${MICROPY_EXTMOD_DIR}/moduplatform.c
- ${MICROPY_EXTMOD_DIR}/modurandom.c
- ${MICROPY_EXTMOD_DIR}/modure.c
- ${MICROPY_EXTMOD_DIR}/moduselect.c
- ${MICROPY_EXTMOD_DIR}/modusocket.c
- ${MICROPY_EXTMOD_DIR}/modussl_axtls.c
- ${MICROPY_EXTMOD_DIR}/modussl_mbedtls.c
- ${MICROPY_EXTMOD_DIR}/modutimeq.c
- ${MICROPY_EXTMOD_DIR}/moduwebsocket.c
- ${MICROPY_EXTMOD_DIR}/moduzlib.c
+ ${MICROPY_EXTMOD_DIR}/modhashlib.c
+ ${MICROPY_EXTMOD_DIR}/modheapq.c
+ ${MICROPY_EXTMOD_DIR}/modjson.c
+ ${MICROPY_EXTMOD_DIR}/modos.c
+ ${MICROPY_EXTMOD_DIR}/modplatform.c
+ ${MICROPY_EXTMOD_DIR}/modrandom.c
+ ${MICROPY_EXTMOD_DIR}/modre.c
+ ${MICROPY_EXTMOD_DIR}/modselect.c
+ ${MICROPY_EXTMOD_DIR}/modsocket.c
+ ${MICROPY_EXTMOD_DIR}/modssl_axtls.c
+ ${MICROPY_EXTMOD_DIR}/modssl_mbedtls.c
+ ${MICROPY_EXTMOD_DIR}/modtime.c
+ ${MICROPY_EXTMOD_DIR}/modwebsocket.c
+ ${MICROPY_EXTMOD_DIR}/modzlib.c
${MICROPY_EXTMOD_DIR}/modwebrepl.c
- ${MICROPY_EXTMOD_DIR}/uos_dupterm.c
- ${MICROPY_EXTMOD_DIR}/utime_mphal.c
+ ${MICROPY_EXTMOD_DIR}/network_cyw43.c
+ ${MICROPY_EXTMOD_DIR}/network_lwip.c
+ ${MICROPY_EXTMOD_DIR}/network_ninaw10.c
+ ${MICROPY_EXTMOD_DIR}/network_wiznet5k.c
+ ${MICROPY_EXTMOD_DIR}/os_dupterm.c
${MICROPY_EXTMOD_DIR}/vfs.c
${MICROPY_EXTMOD_DIR}/vfs_blockdev.c
${MICROPY_EXTMOD_DIR}/vfs_fat.c
@@ -93,6 +97,7 @@ if(MICROPY_PY_BTREE)
)
list(APPEND MICROPY_DEF_CORE
+ MICROPY_PY_BTREE=1
__DBINTERFACE_PRIVATE=1
"virt_fd_t=void*"
)
@@ -114,6 +119,7 @@ if(MICROPY_SSL_MBEDTLS)
)
target_sources(micropy_lib_mbedtls INTERFACE
+ ${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c
${MICROPY_LIB_MBEDTLS_DIR}/library/aes.c
${MICROPY_LIB_MBEDTLS_DIR}/library/aesni.c
${MICROPY_LIB_MBEDTLS_DIR}/library/arc4.c
@@ -141,7 +147,6 @@ if(MICROPY_SSL_MBEDTLS)
${MICROPY_LIB_MBEDTLS_DIR}/library/ecp_curves.c
${MICROPY_LIB_MBEDTLS_DIR}/library/entropy.c
${MICROPY_LIB_MBEDTLS_DIR}/library/entropy_poll.c
- ${MICROPY_LIB_MBEDTLS_DIR}/library/error.c
${MICROPY_LIB_MBEDTLS_DIR}/library/gcm.c
${MICROPY_LIB_MBEDTLS_DIR}/library/havege.c
${MICROPY_LIB_MBEDTLS_DIR}/library/hmac_drbg.c
@@ -149,7 +154,6 @@ if(MICROPY_SSL_MBEDTLS)
${MICROPY_LIB_MBEDTLS_DIR}/library/md4.c
${MICROPY_LIB_MBEDTLS_DIR}/library/md5.c
${MICROPY_LIB_MBEDTLS_DIR}/library/md.c
- ${MICROPY_LIB_MBEDTLS_DIR}/library/md_wrap.c
${MICROPY_LIB_MBEDTLS_DIR}/library/oid.c
${MICROPY_LIB_MBEDTLS_DIR}/library/padlock.c
${MICROPY_LIB_MBEDTLS_DIR}/library/pem.c
@@ -174,9 +178,11 @@ if(MICROPY_SSL_MBEDTLS)
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_cli.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_cookie.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_srv.c
+ ${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_msg.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_ticket.c
${MICROPY_LIB_MBEDTLS_DIR}/library/ssl_tls.c
${MICROPY_LIB_MBEDTLS_DIR}/library/timing.c
+ ${MICROPY_LIB_MBEDTLS_DIR}/library/constant_time.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509_create.c
${MICROPY_LIB_MBEDTLS_DIR}/library/x509_crl.c
@@ -187,8 +193,12 @@ if(MICROPY_SSL_MBEDTLS)
${MICROPY_LIB_MBEDTLS_DIR}/library/xtea.c
)
+ if(NOT MBEDTLS_CONFIG_FILE)
+ set(MBEDTLS_CONFIG_FILE "${MICROPY_PORT_DIR}/mbedtls/mbedtls_config.h")
+ endif()
+
target_compile_definitions(micropy_lib_mbedtls INTERFACE
- MBEDTLS_CONFIG_FILE="${MICROPY_PORT_DIR}/mbedtls/mbedtls_config.h"
+ MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}"
)
list(APPEND MICROPY_INC_CORE
diff --git a/extmod/extmod.mk b/extmod/extmod.mk
index 93b2a11766cf1..41d200fce4954 100644
--- a/extmod/extmod.mk
+++ b/extmod/extmod.mk
@@ -1,55 +1,67 @@
# This makefile fragment adds the source code files for the core extmod modules
# and provides rules to build 3rd-party components for extmod modules.
-PY_EXTMOD_O_BASENAME = \
- extmod/moduasyncio.o \
- extmod/moductypes.o \
- extmod/modujson.o \
- extmod/moduos.o \
- extmod/modure.o \
- extmod/moduzlib.o \
- extmod/moduheapq.o \
- extmod/modutimeq.o \
- extmod/moduhashlib.o \
- extmod/moducryptolib.o \
- extmod/modubinascii.o \
- extmod/virtpin.o \
- extmod/machine_bitstream.o \
- extmod/machine_mem.o \
- extmod/machine_pinbase.o \
- extmod/machine_signal.o \
- extmod/machine_pulse.o \
- extmod/machine_pwm.o \
- extmod/machine_i2c.o \
- extmod/machine_spi.o \
- extmod/modbluetooth.o \
- extmod/modlwip.o \
- extmod/modussl_axtls.o \
- extmod/modussl_mbedtls.o \
- extmod/moduplatform.o\
- extmod/modurandom.o \
- extmod/moduselect.o \
- extmod/moduwebsocket.o \
- extmod/modwebrepl.o \
- extmod/modframebuf.o \
- extmod/vfs.o \
- extmod/vfs_blockdev.o \
- extmod/vfs_reader.o \
- extmod/vfs_posix.o \
- extmod/vfs_posix_file.o \
- extmod/vfs_fat.o \
- extmod/vfs_fat_diskio.o \
- extmod/vfs_fat_file.o \
- extmod/vfs_lfs.o \
- extmod/utime_mphal.o \
- extmod/uos_dupterm.o \
- shared/libc/abort_.o \
- shared/libc/printf.o \
+SRC_EXTMOD_C += \
+ extmod/machine_bitstream.c \
+ extmod/machine_i2c.c \
+ extmod/machine_mem.c \
+ extmod/machine_pinbase.c \
+ extmod/machine_pulse.c \
+ extmod/machine_pwm.c \
+ extmod/machine_signal.c \
+ extmod/machine_spi.c \
+ extmod/machine_timer.c \
+ extmod/modasyncio.c \
+ extmod/modbinascii.c \
+ extmod/modbluetooth.c \
+ extmod/modbtree.c \
+ extmod/modcryptolib.c \
+ extmod/modframebuf.c \
+ extmod/modhashlib.c \
+ extmod/modheapq.c \
+ extmod/modjson.c \
+ extmod/modlwip.c \
+ extmod/modnetwork.c \
+ extmod/modonewire.c \
+ extmod/modos.c \
+ extmod/modplatform.c\
+ extmod/modrandom.c \
+ extmod/modre.c \
+ extmod/modselect.c \
+ extmod/modsocket.c \
+ extmod/modssl_axtls.c \
+ extmod/modssl_mbedtls.c \
+ extmod/modtime.c \
+ extmod/moductypes.c \
+ extmod/modwebrepl.c \
+ extmod/modwebsocket.c \
+ extmod/modzlib.c \
+ extmod/network_cyw43.c \
+ extmod/network_lwip.c \
+ extmod/network_ninaw10.c \
+ extmod/network_wiznet5k.c \
+ extmod/os_dupterm.c \
+ extmod/vfs.c \
+ extmod/vfs_blockdev.c \
+ extmod/vfs_fat.c \
+ extmod/vfs_fat_diskio.c \
+ extmod/vfs_fat_file.c \
+ extmod/vfs_lfs.c \
+ extmod/vfs_posix.c \
+ extmod/vfs_posix_file.c \
+ extmod/vfs_reader.c \
+ extmod/virtpin.c \
+ shared/libc/abort_.c \
+ shared/libc/printf.c \
-PY_EXTMOD_O = $(addprefix $(BUILD)/, $(PY_EXTMOD_O_BASENAME))
+SRC_THIRDPARTY_C += \
-PY_O += $(PY_EXTMOD_O)
-SRC_QSTR += $(PY_EXTMOD_O_BASENAME:.o=.c)
+PY_O += $(addprefix $(BUILD)/, $(SRC_EXTMOD_C:.c=.o))
+PY_O += $(addprefix $(BUILD)/, $(SRC_THIRDPARTY_C:.c=.o))
+SRC_QSTR += $(SRC_EXTMOD_C)
+
+CFLAGS += $(CFLAGS_EXTMOD) $(CFLAGS_THIRDPARTY)
+LDFLAGS += $(LDFLAGS_EXTMOD) $(LDFLAGS_THIRDPARTY)
################################################################################
# VFS FAT FS
@@ -57,11 +69,11 @@ SRC_QSTR += $(PY_EXTMOD_O_BASENAME:.o=.c)
OOFATFS_DIR = lib/oofatfs
# this sets the config file for FatFs
-CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\"
+CFLAGS_THIRDPARTY += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\"
ifeq ($(MICROPY_VFS_FAT),1)
-CFLAGS_MOD += -DMICROPY_VFS_FAT=1
-SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\
+CFLAGS_EXTMOD += -DMICROPY_VFS_FAT=1
+SRC_THIRDPARTY_C += $(addprefix $(OOFATFS_DIR)/,\
ff.c \
ffunicode.c \
)
@@ -73,18 +85,18 @@ endif
LITTLEFS_DIR = lib/littlefs
ifeq ($(MICROPY_VFS_LFS1),1)
-CFLAGS_MOD += -DMICROPY_VFS_LFS1=1
-CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT
-SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
+CFLAGS_EXTMOD += -DMICROPY_VFS_LFS1=1
+CFLAGS_THIRDPARTY += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT
+SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\
lfs1.c \
lfs1_util.c \
)
endif
ifeq ($(MICROPY_VFS_LFS2),1)
-CFLAGS_MOD += -DMICROPY_VFS_LFS2=1
-CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT
-SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
+CFLAGS_EXTMOD += -DMICROPY_VFS_LFS2=1
+CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT
+SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\
lfs2.c \
lfs2_util.c \
)
@@ -95,13 +107,14 @@ endif
################################################################################
# ussl
-ifeq ($(MICROPY_PY_USSL),1)
-CFLAGS_MOD += -DMICROPY_PY_USSL=1
+ifeq ($(MICROPY_PY_SSL),1)
+CFLAGS_EXTMOD += -DMICROPY_PY_SSL=1
ifeq ($(MICROPY_SSL_AXTLS),1)
-CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include
AXTLS_DIR = lib/axtls
+GIT_SUBMODULES += $(AXTLS_DIR)
+CFLAGS_EXTMOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include
$(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition -Dmp_stream_errno=errno $(AXTLS_DEFS_EXTRA)
-SRC_MOD += $(addprefix $(AXTLS_DIR)/,\
+SRC_THIRDPARTY_C += $(addprefix $(AXTLS_DIR)/,\
ssl/asn1.c \
ssl/loader.c \
ssl/tls1.c \
@@ -118,8 +131,12 @@ SRC_MOD += $(addprefix $(AXTLS_DIR)/,\
)
else ifeq ($(MICROPY_SSL_MBEDTLS),1)
MBEDTLS_DIR = lib/mbedtls
-CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include
-SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\
+MBEDTLS_CONFIG_FILE ?= \"mbedtls/mbedtls_config.h\"
+GIT_SUBMODULES += $(MBEDTLS_DIR)
+CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE)
+CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include
+SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c
+SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\
aes.c \
aesni.c \
arc4.c \
@@ -147,7 +164,6 @@ SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\
ecp_curves.c \
entropy.c \
entropy_poll.c \
- error.c \
gcm.c \
havege.c \
hmac_drbg.c \
@@ -155,7 +171,6 @@ SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\
md4.c \
md5.c \
md.c \
- md_wrap.c \
oid.c \
padlock.c \
pem.c \
@@ -180,9 +195,11 @@ SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\
ssl_cli.c \
ssl_cookie.c \
ssl_srv.c \
+ ssl_msg.c \
ssl_ticket.c \
ssl_tls.c \
timing.c \
+ constant_time.c \
x509.c \
x509_create.c \
x509_crl.c \
@@ -199,13 +216,14 @@ endif
# lwip
ifeq ($(MICROPY_PY_LWIP),1)
+GIT_SUBMODULES += lib/lwip
# A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include)
LWIP_DIR = lib/lwip/src
INC += -I$(TOP)/$(LWIP_DIR)/include
-CFLAGS_MOD += -DMICROPY_PY_LWIP=1
-$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address
-SRC_MOD += shared/netutils/netutils.c
-SRC_MOD += $(addprefix $(LWIP_DIR)/,\
+CFLAGS_EXTMOD += -DMICROPY_PY_LWIP=1
+$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address
+SRC_THIRDPARTY_C += shared/netutils/netutils.c
+SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
apps/mdns/mdns.c \
core/def.c \
core/dns.c \
@@ -244,8 +262,8 @@ SRC_MOD += $(addprefix $(LWIP_DIR)/,\
netif/ethernet.c \
)
ifeq ($(MICROPY_PY_LWIP_SLIP),1)
-CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1
-SRC_MOD += $(LWIP_DIR)/netif/slipif.c
+CFLAGS_EXTMOD += -DMICROPY_PY_LWIP_SLIP=1
+SRC_THIRDPARTY_C += $(LWIP_DIR)/netif/slipif.c
endif
endif
@@ -256,8 +274,7 @@ ifeq ($(MICROPY_PY_BTREE),1)
BTREE_DIR = lib/berkeley-db-1.xx
BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA)
INC += -I$(TOP)/$(BTREE_DIR)/PORT/include
-SRC_MOD += extmod/modbtree.c
-SRC_MOD += $(addprefix $(BTREE_DIR)/,\
+SRC_THIRDPARTY_C += $(addprefix $(BTREE_DIR)/,\
btree/bt_close.c \
btree/bt_conv.c \
btree/bt_debug.c \
@@ -273,10 +290,79 @@ SRC_MOD += $(addprefix $(BTREE_DIR)/,\
btree/bt_utils.c \
mpool/mpool.c \
)
-CFLAGS_MOD += -DMICROPY_PY_BTREE=1
+CFLAGS_EXTMOD += -DMICROPY_PY_BTREE=1
# we need to suppress certain warnings to get berkeley-db to compile cleanly
# and we have separate BTREE_DEFS so the definitions don't interfere with other source code
-$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
+$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter -Wno-deprecated-non-prototype -Wno-unknown-warning-option $(BTREE_DEFS)
$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS)
endif
+################################################################################
+# networking
+
+ifeq ($(MICROPY_PY_NETWORK_CYW43),1)
+CYW43_DIR = lib/cyw43-driver
+GIT_SUBMODULES += $(CYW43_DIR)
+CFLAGS_EXTMOD += -DMICROPY_PY_NETWORK_CYW43=1
+SRC_THIRDPARTY_C += $(addprefix $(CYW43_DIR)/src/,\
+ cyw43_ctrl.c \
+ cyw43_lwip.c \
+ cyw43_ll.c \
+ cyw43_sdio.c \
+ cyw43_stats.c \
+ )
+ifeq ($(MICROPY_PY_BLUETOOTH),1)
+DRIVERS_SRC_C += drivers/cyw43/cywbt.c
+endif
+
+$(BUILD)/$(CYW43_DIR)/src/cyw43_%.o: CFLAGS += -std=c11
+endif # MICROPY_PY_NETWORK_CYW43
+
+ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),)
+ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0)
+WIZNET5K_DIR=lib/wiznet5k
+GIT_SUBMODULES += lib/wiznet5k
+INC += -I$(TOP)/$(WIZNET5K_DIR) -I$(TOP)/$(WIZNET5K_DIR)/Ethernet
+CFLAGS += -DMICROPY_PY_NETWORK_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K)
+CFLAGS_THIRDPARTY += -DWIZCHIP_PREFIXED_EXPORTS=1
+ifeq ($(MICROPY_PY_LWIP),1)
+# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket
+CFLAGS_THIRDPARTY += -DWIZCHIP_USE_MAX_BUFFER
+endif
+SRC_THIRDPARTY_C += $(addprefix $(WIZNET5K_DIR)/,\
+ Ethernet/W$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \
+ Ethernet/wizchip_conf.c \
+ Ethernet/socket.c \
+ Internet/DNS/dns.c \
+ Internet/DHCP/dhcp.c \
+ )
+endif
+endif
+
+################################################################################
+# bluetooth
+
+ifeq ($(MICROPY_PY_BLUETOOTH),1)
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH=1
+
+ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
+ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+$(error Cannot enable both NimBLE and BTstack at the same time)
+endif
+endif
+
+ifneq ($(MICROPY_BLUETOOTH_NIMBLE),1)
+ifneq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+$(error Must enable one of MICROPY_BLUETOOTH_NIMBLE or MICROPY_BLUETOOTH_BTSTACK)
+endif
+endif
+
+ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
+include $(TOP)/extmod/nimble/nimble.mk
+endif
+
+ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+include $(TOP)/extmod/btstack/btstack.mk
+endif
+
+endif
diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c
index 452f07a2ebdb8..3563b3243c36f 100644
--- a/extmod/machine_i2c.c
+++ b/extmod/machine_i2c.c
@@ -273,7 +273,7 @@ int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n
}
}
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
int ret = i2c_p->transfer_single(self, addr, len, buf, flags);
if (n > 1) {
@@ -292,14 +292,14 @@ int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n
}
STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
mp_machine_i2c_buf_t buf = {.len = len, .buf = dest};
unsigned int flags = MP_MACHINE_I2C_FLAG_READ | (stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
return i2c_p->transfer(self, addr, 1, &buf, flags);
}
STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t *)src};
unsigned int flags = stop ? MP_MACHINE_I2C_FLAG_STOP : 0;
return i2c_p->transfer(self, addr, 1, &buf, flags);
@@ -310,7 +310,7 @@ STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint
STATIC mp_obj_t machine_i2c_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->init == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -328,6 +328,9 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
if (ret == 0) {
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
}
+ #ifdef MICROPY_EVENT_POLL_HOOK
+ MICROPY_EVENT_POLL_HOOK
+ #endif
}
return list;
}
@@ -335,7 +338,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->start == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -349,7 +352,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->stop == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -363,7 +366,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);
STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) {
mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->read == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -387,7 +390,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_
STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->write == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -417,7 +420,7 @@ STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
if (ret < 0) {
mp_raise_OSError(-ret);
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
@@ -483,7 +486,7 @@ STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
}
// Do the I2C transfer
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
mp_local_free(bufs);
@@ -516,7 +519,7 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
// The I2C transfer function may support the MP_MACHINE_I2C_FLAG_WRITE1 option
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->transfer_supports_write1) {
// Create partial write and read buffers
mp_machine_i2c_buf_t bufs[2] = {
@@ -553,7 +556,7 @@ STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t
};
// Do I2C transfer
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP);
}
@@ -581,7 +584,7 @@ STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args
mp_raise_OSError(-ret);
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
@@ -727,13 +730,14 @@ STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
.transfer = mp_machine_soft_i2c_transfer,
};
-const mp_obj_type_t mp_machine_soft_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_SoftI2C,
- .print = mp_machine_soft_i2c_print,
- .make_new = mp_machine_soft_i2c_make_new,
- .protocol = &mp_machine_soft_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_machine_soft_i2c_type,
+ MP_QSTR_SoftI2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_machine_soft_i2c_make_new,
+ print, mp_machine_soft_i2c_print,
+ protocol, &mp_machine_soft_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_SOFTI2C
diff --git a/extmod/machine_i2c.h b/extmod/machine_i2c.h
index a3363d4c341c5..600145bfedf4e 100644
--- a/extmod/machine_i2c.h
+++ b/extmod/machine_i2c.h
@@ -38,7 +38,7 @@
--n_args; \
++all_args; \
} \
- return mp_machine_soft_i2c_type.make_new(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
+ return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
} \
} while (0)
diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c
index 73e2f7fd1fcb0..f27356e028365 100644
--- a/extmod/machine_mem.c
+++ b/extmod/machine_mem.c
@@ -101,12 +101,13 @@ STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va
}
}
-const mp_obj_type_t machine_mem_type = {
- { &mp_type_type },
- .name = MP_QSTR_mem,
- .print = machine_mem_print,
- .subscr = machine_mem_subscr,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_mem_type,
+ MP_QSTR_mem,
+ MP_TYPE_FLAG_NONE,
+ print, machine_mem_print,
+ subscr, machine_mem_subscr
+ );
const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};
const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};
diff --git a/extmod/machine_pinbase.c b/extmod/machine_pinbase.c
index 070c5cde9d3ac..8607e6ed3de99 100644
--- a/extmod/machine_pinbase.c
+++ b/extmod/machine_pinbase.c
@@ -77,11 +77,12 @@ STATIC const mp_pin_p_t pinbase_pin_p = {
.ioctl = pinbase_ioctl,
};
-const mp_obj_type_t machine_pinbase_type = {
- { &mp_type_type },
- .name = MP_QSTR_PinBase,
- .make_new = pinbase_make_new,
- .protocol = &pinbase_pin_p,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pinbase_type,
+ MP_QSTR_PinBase,
+ MP_TYPE_FLAG_NONE,
+ make_new, pinbase_make_new,
+ protocol, &pinbase_pin_p
+ );
#endif // MICROPY_PY_MACHINE
diff --git a/extmod/machine_pwm.c b/extmod/machine_pwm.c
index ddf49c1358a5d..8a633b37939d4 100644
--- a/extmod/machine_pwm.c
+++ b/extmod/machine_pwm.c
@@ -34,13 +34,11 @@
#include MICROPY_PY_MACHINE_PWM_INCLUDEFILE
#endif
-#if MICROPY_PY_MACHINE_PWM_INIT
STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_machine_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init);
-#endif
// PWM.deinit()
STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self_in) {
@@ -82,8 +80,6 @@ STATIC mp_obj_t machine_pwm_duty(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_obj, 1, 2, machine_pwm_duty);
#endif
-#if MICROPY_PY_MACHINE_PWM_DUTY_U16_NS
-
// PWM.duty_u16([value])
STATIC mp_obj_t machine_pwm_duty_u16(size_t n_args, const mp_obj_t *args) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
@@ -114,30 +110,25 @@ STATIC mp_obj_t machine_pwm_duty_ns(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_ns_obj, 1, 2, machine_pwm_duty_ns);
-#endif
-
STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
- #if MICROPY_PY_MACHINE_PWM_INIT
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pwm_init_obj) },
- #endif
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_pwm_freq_obj) },
#if MICROPY_PY_MACHINE_PWM_DUTY
{ MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&machine_pwm_duty_obj) },
#endif
- #if MICROPY_PY_MACHINE_PWM_DUTY_U16_NS
{ MP_ROM_QSTR(MP_QSTR_duty_u16), MP_ROM_PTR(&machine_pwm_duty_u16_obj) },
{ MP_ROM_QSTR(MP_QSTR_duty_ns), MP_ROM_PTR(&machine_pwm_duty_ns_obj) },
- #endif
};
STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table);
-const mp_obj_type_t machine_pwm_type = {
- { &mp_type_type },
- .name = MP_QSTR_PWM,
- .print = mp_machine_pwm_print,
- .make_new = mp_machine_pwm_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_pwm_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pwm_type,
+ MP_QSTR_PWM,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_machine_pwm_make_new,
+ print, mp_machine_pwm_print,
+ locals_dict, &machine_pwm_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_PWM
diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c
index cf7550a2e084a..7922ed70771e9 100644
--- a/extmod/machine_signal.c
+++ b/extmod/machine_signal.c
@@ -51,7 +51,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
if (n_args > 0 && mp_obj_is_obj(args[0])) {
mp_obj_base_t *pin_base = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
- pin_p = (mp_pin_p_t *)pin_base->type->protocol;
+ pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT_OR_NULL(pin_base->type, protocol);
}
if (pin_p == NULL) {
@@ -172,13 +172,14 @@ STATIC const mp_pin_p_t signal_pin_p = {
.ioctl = signal_ioctl,
};
-const mp_obj_type_t machine_signal_type = {
- { &mp_type_type },
- .name = MP_QSTR_Signal,
- .make_new = signal_make_new,
- .call = signal_call,
- .protocol = &signal_pin_p,
- .locals_dict = (void *)&signal_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_signal_type,
+ MP_QSTR_Signal,
+ MP_TYPE_FLAG_NONE,
+ make_new, signal_make_new,
+ call, signal_call,
+ protocol, &signal_pin_p,
+ locals_dict, &signal_locals_dict
+ );
#endif // MICROPY_PY_MACHINE
diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c
index f160f97d04b4f..8c4d91a3cf632 100644
--- a/extmod/machine_spi.c
+++ b/extmod/machine_spi.c
@@ -28,6 +28,9 @@
#include
#include "py/runtime.h"
+
+#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
+
#include "extmod/machine_spi.h"
// if a port didn't define MSB/LSB constants then provide them
@@ -39,11 +42,9 @@
/******************************************************************************/
// MicroPython bindings for generic machine.SPI
-#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
-
STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol;
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
spi_p->init(s, n_args - 1, args + 1, kw_args);
return mp_const_none;
}
@@ -51,7 +52,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init);
STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) {
mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(self);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol;
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
if (spi_p->deinit != NULL) {
spi_p->deinit(s);
}
@@ -61,7 +62,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit);
STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) {
mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(self);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol;
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
spi_p->transfer(s, len, src, dest);
}
@@ -70,7 +71,7 @@ STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len);
mp_machine_spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
@@ -251,13 +252,14 @@ const mp_machine_spi_p_t mp_machine_soft_spi_p = {
.transfer = mp_machine_soft_spi_transfer,
};
-const mp_obj_type_t mp_machine_soft_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SoftSPI,
- .print = mp_machine_soft_spi_print,
- .make_new = mp_machine_soft_spi_make_new,
- .protocol = &mp_machine_soft_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_machine_soft_spi_type,
+ MP_QSTR_SoftSPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_machine_soft_spi_make_new,
+ print, mp_machine_soft_spi_print,
+ protocol, &mp_machine_soft_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_SOFTSPI
diff --git a/extmod/machine_spi.h b/extmod/machine_spi.h
index ca92c719a8b5a..93ee8d00ca32b 100644
--- a/extmod/machine_spi.h
+++ b/extmod/machine_spi.h
@@ -39,7 +39,7 @@
--n_args; \
++all_args; \
} \
- return mp_machine_soft_spi_type.make_new(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
+ return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
} \
} while (0)
diff --git a/extmod/machine_timer.c b/extmod/machine_timer.c
new file mode 100644
index 0000000000000..68702cb74f605
--- /dev/null
+++ b/extmod/machine_timer.c
@@ -0,0 +1,151 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_MACHINE_TIMER
+
+#include "shared/runtime/softtimer.h"
+
+typedef soft_timer_entry_t machine_timer_obj_t;
+
+const mp_obj_type_t machine_timer_type;
+
+STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ qstr mode = self->mode == SOFT_TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC;
+ mp_printf(print, "Timer(mode=%q, period=%u)", mode, self->delta_ms);
+}
+
+STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SOFT_TIMER_MODE_PERIODIC} },
+ { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
+ { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ };
+
+ // Parse args
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ self->mode = args[ARG_mode].u_int;
+
+ uint64_t delta_ms = self->delta_ms;
+ if (args[ARG_freq].u_obj != mp_const_none) {
+ // Frequency specified in Hz
+ #if MICROPY_PY_BUILTINS_FLOAT
+ delta_ms = (uint32_t)(MICROPY_FLOAT_CONST(1000.0) / mp_obj_get_float(args[ARG_freq].u_obj));
+ #else
+ delta_ms = 1000 / mp_obj_get_int(args[ARG_freq].u_obj);
+ #endif
+ } else if (args[ARG_period].u_int != 0xffffffff) {
+ // Period specified
+ delta_ms = (uint64_t)args[ARG_period].u_int * 1000 / args[ARG_tick_hz].u_int;
+ }
+
+ if (delta_ms < 1) {
+ delta_ms = 1;
+ } else if (delta_ms >= 0x40000000) {
+ mp_raise_ValueError(MP_ERROR_TEXT("period too large"));
+ }
+ self->delta_ms = (uint32_t)delta_ms;
+
+ if (args[ARG_callback].u_obj != MP_OBJ_NULL) {
+ self->py_callback = args[ARG_callback].u_obj;
+ }
+
+ if (self->py_callback != mp_const_none) {
+ soft_timer_insert(self, self->delta_ms);
+ }
+
+ return mp_const_none;
+}
+
+STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
+ self->pairheap.base.type = &machine_timer_type;
+ self->flags = SOFT_TIMER_FLAG_PY_CALLBACK | SOFT_TIMER_FLAG_GC_ALLOCATED;
+ self->delta_ms = 1000;
+ self->py_callback = mp_const_none;
+
+ // Get timer id (only soft timer (-1) supported at the moment)
+ mp_int_t id = -1;
+ if (n_args > 0) {
+ id = mp_obj_get_int(args[0]);
+ --n_args;
+ ++args;
+ }
+ if (id != -1) {
+ mp_raise_ValueError(MP_ERROR_TEXT("Timer doesn't exist"));
+ }
+
+ if (n_args > 0 || n_kw > 0) {
+ // Start the timer
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ machine_timer_init_helper(self, n_args, args, &kw_args);
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ soft_timer_remove(self);
+ return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
+
+STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
+ machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ soft_timer_remove(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
+
+STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(SOFT_TIMER_MODE_ONE_SHOT) },
+ { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(SOFT_TIMER_MODE_PERIODIC) },
+};
+STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_timer_make_new,
+ print, machine_timer_print,
+ locals_dict, &machine_timer_locals_dict
+ );
+
+#endif // MICROPY_PY_MACHINE_TIMER
diff --git a/extmod/mbedtls/mbedtls_config_common.h b/extmod/mbedtls/mbedtls_config_common.h
new file mode 100644
index 0000000000000..bfbc6f7ba298f
--- /dev/null
+++ b/extmod/mbedtls/mbedtls_config_common.h
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2022 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_MBEDTLS_CONFIG_COMMON_H
+#define MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
+
+// If you want to debug MBEDTLS uncomment the following and
+// pass "3" to mbedtls_debug_set_threshold in socket_new.
+// #define MBEDTLS_DEBUG_C
+
+// Set mbedtls configuration.
+#define MBEDTLS_DEPRECATED_REMOVED
+#define MBEDTLS_AES_ROM_TABLES
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED // enabling this currently breaks ssl_data.py test
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_PKCS1_V15
+#define MBEDTLS_SHA256_SMALLER
+#define MBEDTLS_SSL_PROTO_TLS1
+#define MBEDTLS_SSL_PROTO_TLS1_1
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_SERVER_NAME_INDICATION
+
+// Use a smaller output buffer to reduce size of SSL context.
+#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384)
+#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN)
+#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096)
+
+// Enable mbedtls modules.
+#define MBEDTLS_AES_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_MD_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS5_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_RSA_C
+#define MBEDTLS_SHA1_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
+#define MBEDTLS_X509_CRT_PARSE_C
+#define MBEDTLS_X509_USE_C
+
+// A port may enable this option to select additional bare-metal configuration.
+#if MICROPY_MBEDTLS_CONFIG_BARE_METAL
+
+// Bare-metal mbedtls configuration.
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+// Bare-metal memory allocation hooks.
+#include
+#include
+void *m_tracked_calloc(size_t nmemb, size_t size);
+void m_tracked_free(void *ptr);
+#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc
+#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free
+#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
+
+#endif
+
+// Include mbedtls configuration checker.
+#include "mbedtls/check_config.h"
+
+#endif // MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
diff --git a/extmod/misc.h b/extmod/misc.h
index a9392aa10b7b3..80e5b59a08ee1 100644
--- a/extmod/misc.h
+++ b/extmod/misc.h
@@ -32,17 +32,17 @@
#include
#include "py/runtime.h"
-MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
-bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream);
-void mp_uos_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached);
-uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags);
-int mp_uos_dupterm_rx_chr(void);
-void mp_uos_dupterm_tx_strn(const char *str, size_t len);
-void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
+bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream);
+void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached);
+uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags);
+int mp_os_dupterm_rx_chr(void);
+void mp_os_dupterm_tx_strn(const char *str, size_t len);
+void mp_os_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
#else
-#define mp_uos_dupterm_tx_strn(s, l)
+#define mp_os_dupterm_tx_strn(s, l)
#endif
#endif // MICROPY_INCLUDED_EXTMOD_MISC_H
diff --git a/extmod/modasyncio.c b/extmod/modasyncio.c
new file mode 100644
index 0000000000000..a6a54eba8765a
--- /dev/null
+++ b/extmod/modasyncio.c
@@ -0,0 +1,321 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 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 "py/runtime.h"
+#include "py/smallint.h"
+#include "py/pairheap.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_ASYNCIO
+
+// Used when task cannot be guaranteed to be non-NULL.
+#define TASK_PAIRHEAP(task) ((task) ? &(task)->pairheap : NULL)
+
+#define TASK_STATE_RUNNING_NOT_WAITED_ON (mp_const_true)
+#define TASK_STATE_DONE_NOT_WAITED_ON (mp_const_none)
+#define TASK_STATE_DONE_WAS_WAITED_ON (mp_const_false)
+
+#define TASK_IS_DONE(task) ( \
+ (task)->state == TASK_STATE_DONE_NOT_WAITED_ON \
+ || (task)->state == TASK_STATE_DONE_WAS_WAITED_ON)
+
+typedef struct _mp_obj_task_t {
+ mp_pairheap_t pairheap;
+ mp_obj_t coro;
+ mp_obj_t data;
+ mp_obj_t state;
+ mp_obj_t ph_key;
+} mp_obj_task_t;
+
+typedef struct _mp_obj_task_queue_t {
+ mp_obj_base_t base;
+ mp_obj_task_t *heap;
+} mp_obj_task_queue_t;
+
+STATIC const mp_obj_type_t task_queue_type;
+STATIC const mp_obj_type_t task_type;
+
+STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
+
+/******************************************************************************/
+// Ticks for task ordering in pairing heap
+
+STATIC mp_obj_t ticks(void) {
+ return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
+}
+
+STATIC mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) {
+ mp_uint_t t0 = MP_OBJ_SMALL_INT_VALUE(t0_in);
+ mp_uint_t t1 = MP_OBJ_SMALL_INT_VALUE(t1_in);
+ mp_int_t diff = ((t1 - t0 + MICROPY_PY_TIME_TICKS_PERIOD / 2) & (MICROPY_PY_TIME_TICKS_PERIOD - 1))
+ - MICROPY_PY_TIME_TICKS_PERIOD / 2;
+ return diff;
+}
+
+STATIC int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
+ mp_obj_task_t *t1 = (mp_obj_task_t *)n1;
+ mp_obj_task_t *t2 = (mp_obj_task_t *)n2;
+ return MP_OBJ_SMALL_INT_VALUE(ticks_diff(t1->ph_key, t2->ph_key)) < 0;
+}
+
+/******************************************************************************/
+// TaskQueue class
+
+STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ (void)args;
+ mp_arg_check_num(n_args, n_kw, 0, 0, false);
+ mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type);
+ self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt);
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t task_queue_peek(mp_obj_t self_in) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->heap == NULL) {
+ return mp_const_none;
+ } else {
+ return MP_OBJ_FROM_PTR(self->heap);
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek);
+
+STATIC mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_obj_task_t *task = MP_OBJ_TO_PTR(args[1]);
+ task->data = mp_const_none;
+ if (n_args == 2) {
+ task->ph_key = ticks();
+ } else {
+ assert(mp_obj_is_small_int(args[2]));
+ task->ph_key = args[2];
+ }
+ self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push);
+
+STATIC mp_obj_t task_queue_pop(mp_obj_t self_in) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_task_t *head = (mp_obj_task_t *)mp_pairheap_peek(task_lt, &self->heap->pairheap);
+ if (head == NULL) {
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
+ }
+ self->heap = (mp_obj_task_t *)mp_pairheap_pop(task_lt, &self->heap->pairheap);
+ return MP_OBJ_FROM_PTR(head);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_obj, task_queue_pop);
+
+STATIC mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_task_t *task = MP_OBJ_TO_PTR(task_in);
+ self->heap = (mp_obj_task_t *)mp_pairheap_delete(task_lt, &self->heap->pairheap, &task->pairheap);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(task_queue_remove_obj, task_queue_remove);
+
+STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&task_queue_peek_obj) },
+ { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&task_queue_push_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&task_queue_pop_obj) },
+ { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ task_queue_type,
+ MP_QSTR_TaskQueue,
+ MP_TYPE_FLAG_NONE,
+ make_new, task_queue_make_new,
+ locals_dict, &task_queue_locals_dict
+ );
+
+/******************************************************************************/
+// Task class
+
+// This is the core asyncio context with cur_task, _task_queue and CancelledError.
+STATIC mp_obj_t asyncio_context = MP_OBJ_NULL;
+
+STATIC mp_obj_t task_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, 1, 2, false);
+ mp_obj_task_t *self = m_new_obj(mp_obj_task_t);
+ self->pairheap.base.type = type;
+ mp_pairheap_init_node(task_lt, &self->pairheap);
+ self->coro = args[0];
+ self->data = mp_const_none;
+ self->state = TASK_STATE_RUNNING_NOT_WAITED_ON;
+ self->ph_key = MP_OBJ_NEW_SMALL_INT(0);
+ if (n_args == 2) {
+ asyncio_context = args[1];
+ }
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t task_done(mp_obj_t self_in) {
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(TASK_IS_DONE(self));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_done_obj, task_done);
+
+STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ // Check if task is already finished.
+ if (TASK_IS_DONE(self)) {
+ return mp_const_false;
+ }
+ // Can't cancel self (not supported yet).
+ mp_obj_t cur_task = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
+ if (self_in == cur_task) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't cancel self"));
+ }
+ // If Task waits on another task then forward the cancel to the one it's waiting on.
+ while (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(self->data)), MP_OBJ_FROM_PTR(&task_type))) {
+ self = MP_OBJ_TO_PTR(self->data);
+ }
+
+ mp_obj_t _task_queue = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR__task_queue));
+
+ // Reschedule Task as a cancelled task.
+ mp_obj_t dest[3];
+ mp_load_method_maybe(self->data, MP_QSTR_remove, dest);
+ if (dest[0] != MP_OBJ_NULL) {
+ // Not on the main running queue, remove the task from the queue it's on.
+ dest[2] = MP_OBJ_FROM_PTR(self);
+ mp_call_method_n_kw(1, 0, dest);
+ // _task_queue.push(self)
+ dest[0] = _task_queue;
+ dest[1] = MP_OBJ_FROM_PTR(self);
+ task_queue_push(2, dest);
+ } else if (ticks_diff(self->ph_key, ticks()) > 0) {
+ // On the main running queue but scheduled in the future, so bring it forward to now.
+ // _task_queue.remove(self)
+ task_queue_remove(_task_queue, MP_OBJ_FROM_PTR(self));
+ // _task_queue.push(self)
+ dest[0] = _task_queue;
+ dest[1] = MP_OBJ_FROM_PTR(self);
+ task_queue_push(2, dest);
+ }
+
+ self->data = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError));
+
+ return mp_const_true;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel);
+
+STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ if (dest[0] == MP_OBJ_NULL) {
+ // Load
+ if (attr == MP_QSTR_coro) {
+ dest[0] = self->coro;
+ } else if (attr == MP_QSTR_data) {
+ dest[0] = self->data;
+ } else if (attr == MP_QSTR_state) {
+ dest[0] = self->state;
+ } else if (attr == MP_QSTR_done) {
+ dest[0] = MP_OBJ_FROM_PTR(&task_done_obj);
+ dest[1] = self_in;
+ } else if (attr == MP_QSTR_cancel) {
+ dest[0] = MP_OBJ_FROM_PTR(&task_cancel_obj);
+ dest[1] = self_in;
+ } else if (attr == MP_QSTR_ph_key) {
+ dest[0] = self->ph_key;
+ }
+ } else if (dest[1] != MP_OBJ_NULL) {
+ // Store
+ if (attr == MP_QSTR_data) {
+ self->data = dest[1];
+ dest[0] = MP_OBJ_NULL;
+ } else if (attr == MP_QSTR_state) {
+ self->state = dest[1];
+ dest[0] = MP_OBJ_NULL;
+ }
+ }
+}
+
+STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
+ (void)iter_buf;
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ if (TASK_IS_DONE(self)) {
+ // Signal that the completed-task has been await'ed on.
+ self->state = TASK_STATE_DONE_WAS_WAITED_ON;
+ } else if (self->state == TASK_STATE_RUNNING_NOT_WAITED_ON) {
+ // Allocate the waiting queue.
+ self->state = task_queue_make_new(&task_queue_type, 0, 0, NULL);
+ } else if (mp_obj_get_type(self->state) != &task_queue_type) {
+ // Task has state used for another purpose, so can't also wait on it.
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't wait"));
+ }
+ return self_in;
+}
+
+STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ if (TASK_IS_DONE(self)) {
+ // Task finished, raise return value to caller so it can continue.
+ nlr_raise(self->data);
+ } else {
+ // Put calling task on waiting queue.
+ mp_obj_t cur_task = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
+ mp_obj_t args[2] = { self->state, cur_task };
+ task_queue_push(2, args);
+ // Set calling task's data to this task that it waits on, to double-link it.
+ ((mp_obj_task_t *)MP_OBJ_TO_PTR(cur_task))->data = self_in;
+ }
+ return mp_const_none;
+}
+
+STATIC const mp_getiter_iternext_custom_t task_getiter_iternext = {
+ .getiter = task_getiter,
+ .iternext = task_iternext,
+};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ task_type,
+ MP_QSTR_Task,
+ MP_TYPE_FLAG_ITER_IS_CUSTOM,
+ make_new, task_make_new,
+ attr, task_attr,
+ iter, &task_getiter_iternext
+ );
+
+/******************************************************************************/
+// C-level asyncio module
+
+STATIC const mp_rom_map_elem_t mp_module_asyncio_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__asyncio) },
+ { MP_ROM_QSTR(MP_QSTR_TaskQueue), MP_ROM_PTR(&task_queue_type) },
+ { MP_ROM_QSTR(MP_QSTR_Task), MP_ROM_PTR(&task_type) },
+};
+STATIC MP_DEFINE_CONST_DICT(mp_module_asyncio_globals, mp_module_asyncio_globals_table);
+
+const mp_obj_module_t mp_module_asyncio = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_asyncio_globals,
+};
+
+MP_REGISTER_MODULE(MP_QSTR__asyncio, mp_module_asyncio);
+
+#endif // MICROPY_PY_ASYNCIO
diff --git a/extmod/modbinascii.c b/extmod/modbinascii.c
new file mode 100644
index 0000000000000..183cd3fc1789b
--- /dev/null
+++ b/extmod/modbinascii.c
@@ -0,0 +1,208 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * 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/runtime.h"
+#include "py/binary.h"
+#include "py/objstr.h"
+
+#if MICROPY_PY_BINASCII
+
+#if MICROPY_PY_BUILTINS_BYTES_HEX
+STATIC mp_obj_t bytes_hex_as_bytes(size_t n_args, const mp_obj_t *args) {
+ return mp_obj_bytes_hex(n_args, args, &mp_type_bytes);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_bytes_obj, 1, 2, bytes_hex_as_bytes);
+
+STATIC mp_obj_t bytes_fromhex_bytes(mp_obj_t data) {
+ return mp_obj_bytes_fromhex(MP_OBJ_FROM_PTR(&mp_type_bytes), data);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bytes_fromhex_obj, bytes_fromhex_bytes);
+#endif
+
+// If ch is a character in the base64 alphabet, and is not a pad character, then
+// the corresponding integer between 0 and 63, inclusively, is returned.
+// Otherwise, -1 is returned.
+static int mod_binascii_sextet(byte ch) {
+ if (ch >= 'A' && ch <= 'Z') {
+ return ch - 'A';
+ } else if (ch >= 'a' && ch <= 'z') {
+ return ch - 'a' + 26;
+ } else if (ch >= '0' && ch <= '9') {
+ return ch - '0' + 52;
+ } else if (ch == '+') {
+ return 62;
+ } else if (ch == '/') {
+ return 63;
+ } else {
+ return -1;
+ }
+}
+
+STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
+ byte *in = bufinfo.buf;
+
+ vstr_t vstr;
+ vstr_init(&vstr, (bufinfo.len * 3) / 4 + 1); // Potentially over-allocate
+ byte *out = (byte *)vstr.buf;
+
+ uint shift = 0;
+ int nbits = 0; // Number of meaningful bits in shift
+ bool hadpad = false; // Had a pad character since last valid character
+ for (size_t i = 0; i < bufinfo.len; i++) {
+ if (in[i] == '=') {
+ if ((nbits == 2) || ((nbits == 4) && hadpad)) {
+ nbits = 0;
+ break;
+ }
+ hadpad = true;
+ }
+
+ int sextet = mod_binascii_sextet(in[i]);
+ if (sextet == -1) {
+ continue;
+ }
+ hadpad = false;
+ shift = (shift << 6) | sextet;
+ nbits += 6;
+
+ if (nbits >= 8) {
+ nbits -= 8;
+ out[vstr.len++] = (shift >> nbits) & 0xFF;
+ }
+ }
+
+ if (nbits) {
+ mp_raise_ValueError(MP_ERROR_TEXT("incorrect padding"));
+ }
+
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
+
+STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_newline };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_newline, MP_ARG_BOOL, {.u_bool = true} },
+ };
+
+ 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);
+ uint8_t newline = args[ARG_newline].u_bool;
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(pos_args[0], &bufinfo, MP_BUFFER_READ);
+
+ vstr_t vstr;
+ vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + newline);
+
+ // First pass, we convert input buffer to numeric base 64 values
+ byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
+ mp_uint_t i;
+ for (i = bufinfo.len; i >= 3; i -= 3) {
+ *out++ = (in[0] & 0xFC) >> 2;
+ *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4;
+ *out++ = (in[1] & 0x0F) << 2 | (in[2] & 0xC0) >> 6;
+ *out++ = in[2] & 0x3F;
+ in += 3;
+ }
+ if (i != 0) {
+ *out++ = (in[0] & 0xFC) >> 2;
+ if (i == 2) {
+ *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4;
+ *out++ = (in[1] & 0x0F) << 2;
+ } else {
+ *out++ = (in[0] & 0x03) << 4;
+ *out++ = 64;
+ }
+ *out = 64;
+ }
+
+ // Second pass, we convert number base 64 values to actual base64 ascii encoding
+ out = (byte *)vstr.buf;
+ for (mp_uint_t j = vstr.len - newline; j--;) {
+ if (*out < 26) {
+ *out += 'A';
+ } else if (*out < 52) {
+ *out += 'a' - 26;
+ } else if (*out < 62) {
+ *out += '0' - 52;
+ } else if (*out == 62) {
+ *out = '+';
+ } else if (*out == 63) {
+ *out = '/';
+ } else {
+ *out = '=';
+ }
+ out++;
+ }
+ if (newline) {
+ *out = '\n';
+ }
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64);
+
+#if MICROPY_PY_BINASCII_CRC32
+#include "lib/uzlib/tinf.h"
+
+STATIC mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
+ uint32_t crc = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 0;
+ crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
+ return mp_obj_new_int_from_uint(crc ^ 0xffffffff);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32);
+#endif
+
+STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_binascii) },
+ #if MICROPY_PY_BUILTINS_BYTES_HEX
+ { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&bytes_hex_as_bytes_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&bytes_fromhex_obj) },
+ #endif
+ { MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },
+ { MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) },
+ #if MICROPY_PY_BINASCII_CRC32
+ { MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) },
+ #endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);
+
+const mp_obj_module_t mp_module_binascii = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_binascii_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_binascii, mp_module_binascii);
+
+#endif // MICROPY_PY_BINASCII
diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c
index 6bdea1616f050..7b13f9556c4fe 100644
--- a/extmod/modbluetooth.c
+++ b/extmod/modbluetooth.c
@@ -34,6 +34,7 @@
#include "py/objarray.h"
#include "py/qstr.h"
#include "py/runtime.h"
+#include "py/stackctrl.h"
#include "extmod/modbluetooth.h"
#include
@@ -51,6 +52,9 @@
#error pairing and bonding require synchronous modbluetooth events
#endif
+// NimBLE can have fragmented data for GATTC events, so requires reassembly.
+#define MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY MICROPY_BLUETOOTH_NIMBLE
+
#define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000
#define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5
@@ -239,16 +243,16 @@ STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid)
#endif // !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
-const mp_obj_type_t mp_type_bluetooth_uuid = {
- { &mp_type_type },
- .name = MP_QSTR_UUID,
- .make_new = bluetooth_uuid_make_new,
- .unary_op = bluetooth_uuid_unary_op,
- .binary_op = bluetooth_uuid_binary_op,
- .locals_dict = NULL,
- .print = bluetooth_uuid_print,
- .buffer_p = { .get_buffer = bluetooth_uuid_get_buffer },
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_bluetooth_uuid,
+ MP_QSTR_UUID,
+ MP_TYPE_FLAG_NONE,
+ make_new, bluetooth_uuid_make_new,
+ unary_op, bluetooth_uuid_unary_op,
+ binary_op, bluetooth_uuid_binary_op,
+ print, bluetooth_uuid_print,
+ buffer, bluetooth_uuid_get_buffer
+ );
// ----------------------------------------------------------------------------
// Bluetooth object: General
@@ -528,43 +532,41 @@ STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t character
// Optional third element, iterable of descriptors.
if (characteristic_len >= 3) {
- mp_obj_t descriptors_len_in = mp_obj_len(characteristic_items[2]);
- num_descriptors[characteristic_index] = mp_obj_get_int(descriptors_len_in);
+ mp_int_t n = mp_obj_get_int(mp_obj_len(characteristic_items[2]));
+ if (n) {
+ num_descriptors[characteristic_index] = n;
+
+ // Grow the flattened uuids and flags arrays with this many more descriptors.
+ descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
+ descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
+
+ // Also grow the handles array.
+ *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]);
+
+ mp_obj_iter_buf_t iter_buf_desc;
+ mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc);
+ mp_obj_t descriptor_obj;
+
+ // Extract out descriptors for this characteristic.
+ while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) {
+ // (uuid, flags,)
+ mp_obj_t *descriptor_items;
+ mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items);
+ mp_obj_t desc_uuid_obj = descriptor_items[0];
+ if (!mp_obj_is_type(desc_uuid_obj, &mp_type_bluetooth_uuid)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid descriptor UUID"));
+ }
- if (num_descriptors[characteristic_index] == 0) {
- continue;
- }
+ descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj);
+ descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]);
+ ++descriptor_index;
- // Grow the flattened uuids and flags arrays with this many more descriptors.
- descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
- descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
-
- // Also grow the handles array.
- *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]);
-
- mp_obj_iter_buf_t iter_buf_desc;
- mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc);
- mp_obj_t descriptor_obj;
-
- // Extract out descriptors for this characteristic.
- while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) {
- // (uuid, flags,)
- mp_obj_t *descriptor_items;
- mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items);
- mp_obj_t desc_uuid_obj = descriptor_items[0];
- if (!mp_obj_is_type(desc_uuid_obj, &mp_type_bluetooth_uuid)) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid descriptor UUID"));
+ (*handles)[handle_index++] = 0xffff;
}
- descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj);
- descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]);
- ++descriptor_index;
-
- (*handles)[handle_index++] = 0xffff;
+ // Reflect that we've grown the handles array.
+ *num_handles += num_descriptors[characteristic_index];
}
-
- // Reflect that we've grown the handles array.
- *num_handles += num_descriptors[characteristic_index];
}
characteristic_uuids[characteristic_index] = MP_OBJ_TO_PTR(uuid_obj);
@@ -731,7 +733,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_passkey_obj, 4, 4,
STATIC mp_obj_t bluetooth_ble_gatts_read(mp_obj_t self_in, mp_obj_t value_handle_in) {
(void)self_in;
size_t len = 0;
- uint8_t *buf;
+ const uint8_t *buf;
mp_bluetooth_gatts_read(mp_obj_get_int(value_handle_in), &buf, &len);
return mp_obj_new_bytes(buf, len);
}
@@ -749,32 +751,30 @@ STATIC mp_obj_t bluetooth_ble_gatts_write(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_write_obj, 3, 4, bluetooth_ble_gatts_write);
-STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t bluetooth_ble_gatts_notify_indicate(size_t n_args, const mp_obj_t *args, int gatts_op) {
mp_int_t conn_handle = mp_obj_get_int(args[1]);
mp_int_t value_handle = mp_obj_get_int(args[2]);
+ const uint8_t *value = NULL;
+ size_t value_len = 0;
if (n_args == 4 && args[3] != mp_const_none) {
mp_buffer_info_t bufinfo = {0};
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
- int err = mp_bluetooth_gatts_notify_send(conn_handle, value_handle, bufinfo.buf, bufinfo.len);
- bluetooth_handle_errno(err);
- return mp_const_none;
- } else {
- int err = mp_bluetooth_gatts_notify(conn_handle, value_handle);
- return bluetooth_handle_errno(err);
+ value = bufinfo.buf;
+ value_len = bufinfo.len;
}
+ return bluetooth_handle_errno(mp_bluetooth_gatts_notify_indicate(conn_handle, value_handle, gatts_op, value, value_len));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify);
-STATIC mp_obj_t bluetooth_ble_gatts_indicate(mp_obj_t self_in, mp_obj_t conn_handle_in, mp_obj_t value_handle_in) {
- (void)self_in;
- mp_int_t conn_handle = mp_obj_get_int(conn_handle_in);
- mp_int_t value_handle = mp_obj_get_int(value_handle_in);
+STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) {
+ return bluetooth_ble_gatts_notify_indicate(n_args, args, MP_BLUETOOTH_GATTS_OP_NOTIFY);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify);
- int err = mp_bluetooth_gatts_indicate(conn_handle, value_handle);
- return bluetooth_handle_errno(err);
+STATIC mp_obj_t bluetooth_ble_gatts_indicate(size_t n_args, const mp_obj_t *args) {
+ return bluetooth_ble_gatts_notify_indicate(n_args, args, MP_BLUETOOTH_GATTS_OP_INDICATE);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(bluetooth_ble_gatts_indicate_obj, bluetooth_ble_gatts_indicate);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_indicate_obj, 3, 4, bluetooth_ble_gatts_indicate);
STATIC mp_obj_t bluetooth_ble_gatts_set_buffer(size_t n_args, const mp_obj_t *args) {
mp_int_t value_handle = mp_obj_get_int(args[1]);
@@ -841,12 +841,11 @@ STATIC mp_obj_t bluetooth_ble_gattc_write(size_t n_args, const mp_obj_t *args) {
mp_obj_t data = args[3];
mp_buffer_info_t bufinfo = {0};
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
- size_t len = bufinfo.len;
unsigned int mode = MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE;
if (n_args == 5) {
mode = mp_obj_get_int(args[4]);
}
- return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, &len, mode));
+ return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, bufinfo.len, mode));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_write_obj, 4, 5, bluetooth_ble_gattc_write);
@@ -977,15 +976,16 @@ STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(bluetooth_ble_locals_dict, bluetooth_ble_locals_dict_table);
-STATIC const mp_obj_type_t mp_type_bluetooth_ble = {
- { &mp_type_type },
- .name = MP_QSTR_BLE,
- .make_new = bluetooth_ble_make_new,
- .locals_dict = (void *)&bluetooth_ble_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_bluetooth_ble,
+ MP_QSTR_BLE,
+ MP_TYPE_FLAG_NONE,
+ make_new, bluetooth_ble_make_new,
+ locals_dict, &bluetooth_ble_locals_dict
+ );
STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluetooth) },
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bluetooth) },
{ MP_ROM_QSTR(MP_QSTR_BLE), MP_ROM_PTR(&mp_type_bluetooth_ble) },
{ MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&mp_type_bluetooth_uuid) },
@@ -999,12 +999,16 @@ STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = {
STATIC MP_DEFINE_CONST_DICT(mp_module_bluetooth_globals, mp_module_bluetooth_globals_table);
-const mp_obj_module_t mp_module_ubluetooth = {
+const mp_obj_module_t mp_module_bluetooth = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_bluetooth_globals,
};
-MP_REGISTER_MODULE(MP_QSTR_ubluetooth, mp_module_ubluetooth);
+// This module should not be extensible (as it is not a CPython standard
+// library nor is it necessary to override from the filesystem), however it
+// has previously been known as `ubluetooth`, so by making it extensible the
+// `ubluetooth` alias will continue to work.
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_bluetooth, mp_module_bluetooth);
// Helpers
@@ -1102,7 +1106,7 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
// conn_handle, start_handle, end_handle, uuid
ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, &o->irq_data_uuid, NULL);
} else if (event == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT) {
- // conn_handle, def_handle, value_handle, properties, uuid
+ // conn_handle, end_handle, value_handle, properties, uuid
ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, &o->irq_data_uuid, NULL);
} else if (event == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT) {
// conn_handle, handle, uuid
@@ -1135,15 +1139,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv
#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
-STATIC mp_obj_t invoke_irq_handler(uint16_t event,
+STATIC mp_obj_t invoke_irq_handler_run(uint16_t event,
const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
const uint8_t *addr,
const mp_obj_bluetooth_uuid_t *uuid,
- const uint8_t **data, size_t *data_len, size_t n_data) {
- mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
- if (o->irq_handler == mp_const_none) {
- return mp_const_none;
- }
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
mp_obj_array_t mv_addr;
mp_obj_array_t mv_data[2];
@@ -1168,6 +1168,34 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(uuid);
}
#endif
+
+ #if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY
+ void *buf_to_free = NULL;
+ uint16_t buf_to_free_len = 0;
+ if (event == MP_BLUETOOTH_IRQ_GATTC_NOTIFY || event == MP_BLUETOOTH_IRQ_GATTC_INDICATE || event == MP_BLUETOOTH_IRQ_GATTC_READ_RESULT) {
+ if (n_data > 1) {
+ // Fragmented buffer, need to combine into a new heap-allocated buffer
+ // in order to pass to Python.
+ // Only gattc_on_data_available calls this code, so data and data_len are writable.
+ uint16_t total_len = 0;
+ for (size_t i = 0; i < n_data; ++i) {
+ total_len += data_len[i];
+ }
+ uint8_t *buf = m_new(uint8_t, total_len);
+ uint8_t *p = buf;
+ for (size_t i = 0; i < n_data; ++i) {
+ memcpy(p, data[i], data_len[i]);
+ p += data_len[i];
+ }
+ data[0] = buf;
+ data_len[0] = total_len;
+ n_data = 1;
+ buf_to_free = buf;
+ buf_to_free_len = total_len;
+ }
+ }
+ #endif
+
for (size_t i = 0; i < n_data; ++i) {
if (data[i]) {
mp_obj_memoryview_init(&mv_data[i], 'B', 0, data_len[i], (void *)data[i]);
@@ -1176,15 +1204,111 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
data_tuple->items[data_tuple->len++] = mp_const_none;
}
}
+
assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN);
+ mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
mp_obj_t result = mp_call_function_2(o->irq_handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple));
+ #if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY
+ if (buf_to_free != NULL) {
+ m_del(uint8_t, (uint8_t *)buf_to_free, buf_to_free_len);
+ }
+ #endif
+
mp_local_free(data_tuple);
return result;
}
+STATIC mp_obj_t invoke_irq_handler_run_protected(uint16_t event,
+ const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
+ const uint8_t *addr,
+ const mp_obj_bluetooth_uuid_t *uuid,
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
+
+ mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
+ if (o->irq_handler == mp_const_none) {
+ return mp_const_none;
+ }
+
+ mp_obj_t result = mp_const_none;
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
+ nlr_pop();
+ } else {
+ // Uncaught exception, print it out.
+ mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n");
+ mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val));
+
+ // Disable the BLE IRQ handler.
+ o->irq_handler = mp_const_none;
+ }
+
+ return result;
+}
+
+#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK
+
+// On some systems the BLE event callbacks may occur on a system thread which is not
+// a MicroPython thread. In such cases the callback must set up relevant MicroPython
+// state and obtain the GIL, to synchronised with the rest of the runtime.
+
+#if MICROPY_ENABLE_PYSTACK
+#error not supported
+#endif
+
+STATIC mp_obj_t invoke_irq_handler(uint16_t event,
+ const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
+ const uint8_t *addr,
+ const mp_obj_bluetooth_uuid_t *uuid,
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
+
+ // This code may run on an existing MicroPython thread, or a non-MicroPython thread
+ // that's not using the mp_thread_get_state() value. In the former case the state
+ // must be restored once this callback finishes.
+ mp_state_thread_t *ts_orig = mp_thread_get_state();
+
+ mp_state_thread_t ts;
+ if (ts_orig == NULL) {
+ mp_thread_set_state(&ts);
+ mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
+ mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE - 1024);
+ ts.gc_lock_depth = 0;
+ ts.mp_pending_exception = MP_OBJ_NULL;
+ mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context
+ mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context
+ MP_THREAD_GIL_ENTER();
+ }
+
+ mp_sched_lock();
+ mp_obj_t result = invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
+ mp_sched_unlock();
+
+ if (ts_orig == NULL) {
+ MP_THREAD_GIL_EXIT();
+ mp_thread_set_state(ts_orig);
+ }
+
+ return result;
+}
+
+#else
+
+// BLE event callbacks are called directly from the MicroPython runtime, so additional
+// synchronisation is not needed, and BLE event handlers can be called directly.
+
+STATIC mp_obj_t invoke_irq_handler(uint16_t event,
+ const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
+ const uint8_t *addr,
+ const mp_obj_bluetooth_uuid_t *uuid,
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
+ return invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
+}
+
+#endif
+
#define NULL_NUMERIC NULL
#define NULL_ADDR NULL
#define NULL_UUID NULL
@@ -1207,7 +1331,7 @@ void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypte
invoke_irq_handler(MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE, args, 5, 0, NULL_ADDR, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
}
-bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len) {
+bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, uint16_t key_len, const uint8_t **value, size_t *value_len) {
mp_int_t args[] = {type, index};
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GET_SECRET, args, 2, 0, NULL_ADDR, NULL_UUID, &key, &key_len, 1);
if (result == mp_const_none) {
@@ -1223,7 +1347,7 @@ bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *
bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len) {
mp_int_t args[] = { type };
const uint8_t *data[] = {key, value};
- size_t data_len[] = {key_len, value_len};
+ uint16_t data_len[] = {key_len, value_len};
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_SET_SECRET, args, 1, 0, NULL_ADDR, NULL_UUID, data, data_len, 2);
return mp_obj_is_true(result);
}
@@ -1294,7 +1418,7 @@ void mp_bluetooth_gap_on_scan_complete(void) {
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_DONE, NULL_NUMERIC, 0, 0, NULL_ADDR, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
}
-void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) {
+void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len) {
mp_int_t args[] = {addr_type, adv_type, rssi};
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_RESULT, args, 1, 2, addr, NULL_UUID, &data, &data_len, 1);
}
@@ -1306,8 +1430,9 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, args, 3, 0, NULL_ADDR, service_uuid, NULL_DATA, NULL_DATA_LEN, 0);
}
-void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
- mp_int_t args[] = {conn_handle, def_handle, value_handle, properties};
+void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
+ // Note: "end_handle" replaces "def_handle" from the original version of this event.
+ mp_int_t args[] = {conn_handle, end_handle, value_handle, properties};
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, args, 4, 0, NULL_ADDR, characteristic_uuid, NULL_DATA, NULL_DATA_LEN, 0);
}
@@ -1322,35 +1447,8 @@ void mp_bluetooth_gattc_on_discover_complete(uint8_t event, uint16_t conn_handle
}
void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t **data, uint16_t *data_len, size_t num) {
- const uint8_t *combined_data;
- size_t total_len;
-
- if (num > 1) {
- // Fragmented buffer, need to combine into a new heap-allocated buffer
- // in order to pass to Python.
- total_len = 0;
- for (size_t i = 0; i < num; ++i) {
- total_len += data_len[i];
- }
- uint8_t *buf = m_new(uint8_t, total_len);
- uint8_t *p = buf;
- for (size_t i = 0; i < num; ++i) {
- memcpy(p, data[i], data_len[i]);
- p += data_len[i];
- }
- combined_data = buf;
- } else {
- // Single buffer, use directly.
- combined_data = *data;
- total_len = *data_len;
- }
-
mp_int_t args[] = {conn_handle, value_handle};
- invoke_irq_handler(event, args, 2, 0, NULL_ADDR, NULL_UUID, &combined_data, &total_len, 1);
-
- if (num > 1) {
- m_del(uint8_t, (uint8_t *)combined_data, total_len);
- }
+ invoke_irq_handler(event, args, 2, 0, NULL_ADDR, NULL_UUID, data, data_len, num);
}
void mp_bluetooth_gattc_on_read_write_status(uint8_t event, uint16_t conn_handle, uint16_t value_handle, uint16_t status) {
@@ -1482,7 +1580,7 @@ void mp_bluetooth_gap_on_scan_complete(void) {
schedule_ringbuf(atomic_state);
}
-void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) {
+void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
data_len = MIN(o->irq_data_data_alloc, data_len);
@@ -1519,12 +1617,13 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t
schedule_ringbuf(atomic_state);
}
-void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
+void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT)) {
ringbuf_put16(&o->ringbuf, conn_handle);
- ringbuf_put16(&o->ringbuf, def_handle);
+ // Note: "end_handle" replaces "def_handle" from the original version of this event.
+ ringbuf_put16(&o->ringbuf, end_handle);
ringbuf_put16(&o->ringbuf, value_handle);
ringbuf_put(&o->ringbuf, properties);
ringbuf_put_uuid(&o->ringbuf, characteristic_uuid);
@@ -1620,7 +1719,7 @@ mp_bluetooth_gatts_db_entry_t *mp_bluetooth_gatts_db_lookup(mp_gatts_db_t db, ui
return MP_OBJ_TO_PTR(elem->value);
}
-int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, uint8_t **value, size_t *value_len) {
+int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, const uint8_t **value, size_t *value_len) {
MICROPY_PY_BLUETOOTH_ENTER
mp_bluetooth_gatts_db_entry_t *entry = mp_bluetooth_gatts_db_lookup(db, handle);
if (entry) {
@@ -1675,4 +1774,6 @@ int mp_bluetooth_gatts_db_resize(mp_gatts_db_t db, uint16_t handle, size_t len,
return entry ? 0 : MP_EINVAL;
}
+MP_REGISTER_ROOT_POINTER(mp_obj_t bluetooth);
+
#endif // MICROPY_PY_BLUETOOTH
diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h
index 52053045f852c..630a2705231e2 100644
--- a/extmod/modbluetooth.h
+++ b/extmod/modbluetooth.h
@@ -84,7 +84,7 @@
#define MP_BLUETOOTH_DEFAULT_ATTR_LEN (20)
#endif
-#define MP_BLUETOOTH_CCCB_LEN (2)
+#define MP_BLUETOOTH_CCCD_LEN (2)
// Advertisement packet lengths
#define MP_BLUETOOTH_GAP_ADV_MAX_LEN (32)
@@ -186,6 +186,10 @@
#define MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY (3)
#define MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON (4)
+// These are the ops for mp_bluetooth_gatts_notify_indicate.
+#define MP_BLUETOOTH_GATTS_OP_NOTIFY (1)
+#define MP_BLUETOOTH_GATTS_OP_INDICATE (2)
+
/*
These aren't included in the module for space reasons, but can be used
in your Python code if necessary.
@@ -333,15 +337,11 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
int mp_bluetooth_gatts_register_service_end(void);
// Read the value from the local gatts db (likely this has been written by a central).
-int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len);
+int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len);
// Write a value to the local gatts db (ready to be queried by a central). Optionally send notifications/indications.
int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len, bool send_update);
-// Notify the central that it should do a read.
-int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle);
-// Notify the central, including a data payload. (Note: does not set the gatts db value).
-int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len);
-// Indicate the central.
-int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle);
+// Send a notification/indication to the central, optionally with custom payload (otherwise the DB value is used).
+int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len);
// Resize and enable/disable append-mode on a value.
// Append-mode means that remote writes will append and local reads will clear after reading.
@@ -391,7 +391,7 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start
int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle);
// Write the value to the remote peripheral.
-int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode);
+int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len, unsigned int mode);
// Initiate MTU exchange for a specific connection using the preferred MTU.
int mp_bluetooth_gattc_exchange_mtu(uint16_t conn_handle);
@@ -426,7 +426,7 @@ void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypte
// For get, if key is NULL, then the implementation must return the index'th matching key. Otherwise it should return a specific key.
// For set, if value is NULL, then delete.
// The "type" is stack-specific, but could also be used to implement versioning.
-bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len);
+bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, uint16_t key_len, const uint8_t **value, size_t *value_len);
bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len);
// Call this when a passkey verification needs to be processed.
@@ -451,7 +451,7 @@ void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value);
void mp_bluetooth_gap_on_scan_complete(void);
// Notify modbluetooth of a scan result.
-void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len);
+void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
@@ -459,7 +459,7 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uin
void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid);
// Notify modbluetooth that a characteristic was found (either by discover-all-on-service, or discover-by-uuid-on-service).
-void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid);
+void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid);
// Notify modbluetooth that a descriptor was found.
void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid);
@@ -508,7 +508,7 @@ STATIC inline void mp_bluetooth_gatts_db_reset(mp_gatts_db_t db) {
void mp_bluetooth_gatts_db_create_entry(mp_gatts_db_t db, uint16_t handle, size_t len);
mp_bluetooth_gatts_db_entry_t *mp_bluetooth_gatts_db_lookup(mp_gatts_db_t db, uint16_t handle);
-int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, uint8_t **value, size_t *value_len);
+int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, const uint8_t **value, size_t *value_len);
int mp_bluetooth_gatts_db_write(mp_gatts_db_t db, uint16_t handle, const uint8_t *value, size_t value_len);
int mp_bluetooth_gatts_db_resize(mp_gatts_db_t db, uint16_t handle, size_t len, bool append);
diff --git a/extmod/modbtree.c b/extmod/modbtree.c
index 7a1daacb41669..9b2d184a1ee79 100644
--- a/extmod/modbtree.c
+++ b/extmod/modbtree.c
@@ -24,16 +24,39 @@
* THE SOFTWARE.
*/
-#include
-#include
-#include // for declaration of global errno variable
-#include
-
#include "py/runtime.h"
#include "py/stream.h"
#if MICROPY_PY_BTREE
+#include
+#include // for declaration of global errno variable
+#include
+
+// Undefine queue macros that will be defined in berkeley-db-1.xx headers
+// below, in case they clash with system ones defined in headers above.
+#undef LIST_HEAD
+#undef LIST_ENTRY
+#undef LIST_INIT
+#undef LIST_INSERT_AFTER
+#undef LIST_INSERT_HEAD
+#undef LIST_REMOVE
+#undef TAILQ_HEAD
+#undef TAILQ_ENTRY
+#undef TAILQ_INIT
+#undef TAILQ_INSERT_HEAD
+#undef TAILQ_INSERT_TAIL
+#undef TAILQ_INSERT_AFTER
+#undef TAILQ_REMOVE
+#undef CIRCLEQ_HEAD
+#undef CIRCLEQ_ENTRY
+#undef CIRCLEQ_INIT
+#undef CIRCLEQ_INSERT_AFTER
+#undef CIRCLEQ_INSERT_BEFORE
+#undef CIRCLEQ_INSERT_HEAD
+#undef CIRCLEQ_INSERT_TAIL
+#undef CIRCLEQ_REMOVE
+
#include
#include <../../btree/btree.h>
@@ -67,7 +90,7 @@ void __dbpanic(DB *db) {
}
STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
- mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, &btree_type);
+ mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type);
o->stream = stream;
o->db = db;
o->start_key = mp_const_none;
@@ -319,17 +342,22 @@ STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
-STATIC const mp_obj_type_t btree_type = {
- { &mp_type_type },
- // Save on qstr's, reuse same as for module
- .name = MP_QSTR_btree,
- .print = btree_print,
+STATIC const mp_getiter_iternext_custom_t btree_getiter_iternext = {
.getiter = btree_getiter,
.iternext = btree_iternext,
- .binary_op = btree_binary_op,
- .subscr = btree_subscr,
- .locals_dict = (void *)&btree_locals_dict,
};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ btree_type,
+ MP_QSTR_btree,
+ MP_TYPE_FLAG_ITER_IS_CUSTOM,
+ // Save on qstr's, reuse same as for module
+ print, btree_print,
+ iter, &btree_getiter_iternext,
+ binary_op, btree_binary_op,
+ subscr, btree_subscr,
+ locals_dict, &btree_locals_dict
+ );
#endif
STATIC const FILEVTABLE btree_stream_fvtable = {
diff --git a/extmod/modcryptolib.c b/extmod/modcryptolib.c
new file mode 100644
index 0000000000000..b33d8533fc5e6
--- /dev/null
+++ b/extmod/modcryptolib.c
@@ -0,0 +1,384 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017-2018 Paul Sokolovsky
+ * Copyright (c) 2018 Yonatan Goldschmidt
+ *
+ * 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_CRYPTOLIB
+
+#include
+#include
+
+#include "py/runtime.h"
+
+// This module implements crypto ciphers API, roughly following
+// https://www.python.org/dev/peps/pep-0272/ . Exact implementation
+// of PEP 272 can be made with a simple wrapper which adds all the
+// needed boilerplate.
+
+// values follow PEP 272
+enum {
+ UCRYPTOLIB_MODE_ECB = 1,
+ UCRYPTOLIB_MODE_CBC = 2,
+ UCRYPTOLIB_MODE_CTR = 6,
+};
+
+struct ctr_params {
+ // counter is the IV of the AES context.
+
+ size_t offset; // in encrypted_counter
+ // encrypted counter
+ uint8_t encrypted_counter[16];
+};
+
+#if MICROPY_SSL_AXTLS
+#include "lib/axtls/crypto/crypto.h"
+
+#define AES_CTX_IMPL AES_CTX
+#endif
+
+#if MICROPY_SSL_MBEDTLS
+#include
+
+// we can't run mbedtls AES key schedule until we know whether we're used for encrypt or decrypt.
+// therefore, we store the key & keysize and on the first call to encrypt/decrypt we override them
+// with the mbedtls_aes_context, as they are not longer required. (this is done to save space)
+struct mbedtls_aes_ctx_with_key {
+ union {
+ mbedtls_aes_context mbedtls_ctx;
+ struct {
+ uint8_t key[32];
+ uint8_t keysize;
+ } init_data;
+ } u;
+ unsigned char iv[16];
+};
+#define AES_CTX_IMPL struct mbedtls_aes_ctx_with_key
+#endif
+
+typedef struct _mp_obj_aes_t {
+ mp_obj_base_t base;
+ AES_CTX_IMPL ctx;
+ uint8_t block_mode : 6;
+#define AES_KEYTYPE_NONE 0
+#define AES_KEYTYPE_ENC 1
+#define AES_KEYTYPE_DEC 2
+ uint8_t key_type : 2;
+} mp_obj_aes_t;
+
+static inline bool is_ctr_mode(int block_mode) {
+ #if MICROPY_PY_CRYPTOLIB_CTR
+ return block_mode == UCRYPTOLIB_MODE_CTR;
+ #else
+ return false;
+ #endif
+}
+
+static inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) {
+ // ctr_params follows aes object struct
+ return (struct ctr_params *)&o[1];
+}
+
+#if MICROPY_SSL_AXTLS
+STATIC void aes_initial_set_key_impl(AES_CTX_IMPL *ctx, const uint8_t *key, size_t keysize, const uint8_t iv[16]) {
+ assert(16 == keysize || 32 == keysize);
+ AES_set_key(ctx, key, iv, (16 == keysize) ? AES_MODE_128 : AES_MODE_256);
+}
+
+STATIC void aes_final_set_key_impl(AES_CTX_IMPL *ctx, bool encrypt) {
+ if (!encrypt) {
+ AES_convert_key(ctx);
+ }
+}
+
+STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_t out[16], bool encrypt) {
+ memcpy(out, in, 16);
+ // We assume that out (vstr.buf or given output buffer) is uint32_t aligned
+ uint32_t *p = (uint32_t *)out;
+ // axTLS likes it weird and complicated with byteswaps
+ for (int i = 0; i < 4; i++) {
+ p[i] = MP_HTOBE32(p[i]);
+ }
+ if (encrypt) {
+ AES_encrypt(ctx, p);
+ } else {
+ AES_decrypt(ctx, p);
+ }
+ for (int i = 0; i < 4; i++) {
+ p[i] = MP_BE32TOH(p[i]);
+ }
+}
+
+STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, bool encrypt) {
+ if (encrypt) {
+ AES_cbc_encrypt(ctx, in, out, in_len);
+ } else {
+ AES_cbc_decrypt(ctx, in, out, in_len);
+ }
+}
+
+#if MICROPY_PY_CRYPTOLIB_CTR
+// axTLS doesn't have CTR support out of the box. This implements the counter part using the ECB primitive.
+STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) {
+ size_t n = ctr_params->offset;
+ uint8_t *const counter = ctx->iv;
+
+ while (in_len--) {
+ if (n == 0) {
+ aes_process_ecb_impl(ctx, counter, ctr_params->encrypted_counter, true);
+
+ // increment the 128-bit counter
+ for (int i = 15; i >= 0; --i) {
+ if (++counter[i] != 0) {
+ break;
+ }
+ }
+ }
+
+ *out++ = *in++ ^ ctr_params->encrypted_counter[n];
+ n = (n + 1) & 0xf;
+ }
+
+ ctr_params->offset = n;
+}
+#endif
+
+#endif
+
+#if MICROPY_SSL_MBEDTLS
+STATIC void aes_initial_set_key_impl(AES_CTX_IMPL *ctx, const uint8_t *key, size_t keysize, const uint8_t iv[16]) {
+ ctx->u.init_data.keysize = keysize;
+ memcpy(ctx->u.init_data.key, key, keysize);
+
+ if (NULL != iv) {
+ memcpy(ctx->iv, iv, sizeof(ctx->iv));
+ }
+}
+
+STATIC void aes_final_set_key_impl(AES_CTX_IMPL *ctx, bool encrypt) {
+ // first, copy key aside
+ uint8_t key[32];
+ uint8_t keysize = ctx->u.init_data.keysize;
+ memcpy(key, ctx->u.init_data.key, keysize);
+ // now, override key with the mbedtls context object
+ mbedtls_aes_init(&ctx->u.mbedtls_ctx);
+
+ // setkey call will succeed, we've already checked the keysize earlier.
+ assert(16 == keysize || 32 == keysize);
+ if (encrypt) {
+ mbedtls_aes_setkey_enc(&ctx->u.mbedtls_ctx, key, keysize * 8);
+ } else {
+ mbedtls_aes_setkey_dec(&ctx->u.mbedtls_ctx, key, keysize * 8);
+ }
+}
+
+STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_t out[16], bool encrypt) {
+ mbedtls_aes_crypt_ecb(&ctx->u.mbedtls_ctx, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, in, out);
+}
+
+STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, bool encrypt) {
+ mbedtls_aes_crypt_cbc(&ctx->u.mbedtls_ctx, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, in_len, ctx->iv, in, out);
+}
+
+#if MICROPY_PY_CRYPTOLIB_CTR
+STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) {
+ mbedtls_aes_crypt_ctr(&ctx->u.mbedtls_ctx, in_len, &ctr_params->offset, ctx->iv, ctr_params->encrypted_counter, in, out);
+}
+#endif
+
+#endif
+
+STATIC mp_obj_t cryptolib_aes_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, 2, 3, false);
+
+ const mp_int_t block_mode = mp_obj_get_int(args[1]);
+
+ switch (block_mode) {
+ case UCRYPTOLIB_MODE_ECB:
+ case UCRYPTOLIB_MODE_CBC:
+ #if MICROPY_PY_CRYPTOLIB_CTR
+ case UCRYPTOLIB_MODE_CTR:
+ #endif
+ break;
+
+ default:
+ mp_raise_ValueError(MP_ERROR_TEXT("mode"));
+ }
+
+ mp_obj_aes_t *o = mp_obj_malloc_var(mp_obj_aes_t, struct ctr_params, !!is_ctr_mode(block_mode), type);
+
+ o->block_mode = block_mode;
+ o->key_type = AES_KEYTYPE_NONE;
+
+ mp_buffer_info_t keyinfo;
+ mp_get_buffer_raise(args[0], &keyinfo, MP_BUFFER_READ);
+ if (32 != keyinfo.len && 16 != keyinfo.len) {
+ mp_raise_ValueError(MP_ERROR_TEXT("key"));
+ }
+
+ mp_buffer_info_t ivinfo;
+ ivinfo.buf = NULL;
+ if (n_args > 2 && args[2] != mp_const_none) {
+ mp_get_buffer_raise(args[2], &ivinfo, MP_BUFFER_READ);
+
+ if (16 != ivinfo.len) {
+ mp_raise_ValueError(MP_ERROR_TEXT("IV"));
+ }
+ } else if (o->block_mode == UCRYPTOLIB_MODE_CBC || is_ctr_mode(o->block_mode)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("IV"));
+ }
+
+ if (is_ctr_mode(block_mode)) {
+ ctr_params_from_aes(o)->offset = 0;
+ }
+
+ aes_initial_set_key_impl(&o->ctx, keyinfo.buf, keyinfo.len, ivinfo.buf);
+
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
+ mp_obj_aes_t *self = MP_OBJ_TO_PTR(args[0]);
+
+ mp_obj_t in_buf = args[1];
+ mp_obj_t out_buf = MP_OBJ_NULL;
+ if (n_args > 2) {
+ out_buf = args[2];
+ }
+
+ mp_buffer_info_t in_bufinfo;
+ mp_get_buffer_raise(in_buf, &in_bufinfo, MP_BUFFER_READ);
+
+ if (!is_ctr_mode(self->block_mode) && in_bufinfo.len % 16 != 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("blksize % 16"));
+ }
+
+ vstr_t vstr;
+ mp_buffer_info_t out_bufinfo;
+ uint8_t *out_buf_ptr;
+
+ if (out_buf != MP_OBJ_NULL) {
+ mp_get_buffer_raise(out_buf, &out_bufinfo, MP_BUFFER_WRITE);
+ if (out_bufinfo.len < in_bufinfo.len) {
+ mp_raise_ValueError(MP_ERROR_TEXT("output too small"));
+ }
+ out_buf_ptr = out_bufinfo.buf;
+ } else {
+ vstr_init_len(&vstr, in_bufinfo.len);
+ out_buf_ptr = (uint8_t *)vstr.buf;
+ }
+
+ if (AES_KEYTYPE_NONE == self->key_type) {
+ // always set key for encryption if CTR mode.
+ const bool encrypt_mode = encrypt || is_ctr_mode(self->block_mode);
+ aes_final_set_key_impl(&self->ctx, encrypt_mode);
+ self->key_type = encrypt ? AES_KEYTYPE_ENC : AES_KEYTYPE_DEC;
+ } else {
+ if ((encrypt && self->key_type == AES_KEYTYPE_DEC) ||
+ (!encrypt && self->key_type == AES_KEYTYPE_ENC)) {
+
+ mp_raise_ValueError(MP_ERROR_TEXT("can't encrypt & decrypt"));
+ }
+ }
+
+ switch (self->block_mode) {
+ case UCRYPTOLIB_MODE_ECB: {
+ uint8_t *in = in_bufinfo.buf, *out = out_buf_ptr;
+ uint8_t *top = in + in_bufinfo.len;
+ for (; in < top; in += 16, out += 16) {
+ aes_process_ecb_impl(&self->ctx, in, out, encrypt);
+ }
+ break;
+ }
+
+ case UCRYPTOLIB_MODE_CBC:
+ aes_process_cbc_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len, encrypt);
+ break;
+
+ #if MICROPY_PY_CRYPTOLIB_CTR
+ case UCRYPTOLIB_MODE_CTR:
+ aes_process_ctr_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len,
+ ctr_params_from_aes(self));
+ break;
+ #endif
+ }
+
+ if (out_buf != MP_OBJ_NULL) {
+ return out_buf;
+ }
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+
+STATIC mp_obj_t cryptolib_aes_encrypt(size_t n_args, const mp_obj_t *args) {
+ return aes_process(n_args, args, true);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(cryptolib_aes_encrypt_obj, 2, 3, cryptolib_aes_encrypt);
+
+STATIC mp_obj_t cryptolib_aes_decrypt(size_t n_args, const mp_obj_t *args) {
+ return aes_process(n_args, args, false);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(cryptolib_aes_decrypt_obj, 2, 3, cryptolib_aes_decrypt);
+
+STATIC const mp_rom_map_elem_t cryptolib_aes_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&cryptolib_aes_encrypt_obj) },
+ { MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&cryptolib_aes_decrypt_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(cryptolib_aes_locals_dict, cryptolib_aes_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ cryptolib_aes_type,
+ MP_QSTR_aes,
+ MP_TYPE_FLAG_NONE,
+ make_new, cryptolib_aes_make_new,
+ locals_dict, &cryptolib_aes_locals_dict
+ );
+
+STATIC const mp_rom_map_elem_t mp_module_cryptolib_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cryptolib) },
+ { MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&cryptolib_aes_type) },
+ #if MICROPY_PY_CRYPTOLIB_CONSTS
+ { MP_ROM_QSTR(MP_QSTR_MODE_ECB), MP_ROM_INT(UCRYPTOLIB_MODE_ECB) },
+ { MP_ROM_QSTR(MP_QSTR_MODE_CBC), MP_ROM_INT(UCRYPTOLIB_MODE_CBC) },
+ #if MICROPY_PY_CRYPTOLIB_CTR
+ { MP_ROM_QSTR(MP_QSTR_MODE_CTR), MP_ROM_INT(UCRYPTOLIB_MODE_CTR) },
+ #endif
+ #endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_cryptolib_globals, mp_module_cryptolib_globals_table);
+
+const mp_obj_module_t mp_module_cryptolib = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_cryptolib_globals,
+};
+
+// This module should not be extensible (as it is not a CPython standard
+// library nor is it necessary to override from the filesystem), however it
+// has previously been known as `ucryptolib`, so by making it extensible the
+// `ucryptolib` alias will continue to work.
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_cryptolib, mp_module_cryptolib);
+
+#endif // MICROPY_PY_CRYPTOLIB
diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c
index 5b6575d5a6503..87f7609dd8a85 100644
--- a/extmod/modframebuf.c
+++ b/extmod/modframebuf.c
@@ -28,6 +28,7 @@
#include
#include "py/runtime.h"
+#include "py/binary.h"
#if MICROPY_PY_FRAMEBUF
@@ -240,11 +241,17 @@ STATIC mp_framebuf_p_t formats[] = {
[FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
};
-static inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
+STATIC inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
formats[fb->format].setpixel(fb, x, y, col);
}
-static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
+STATIC void setpixel_checked(const mp_obj_framebuf_t *fb, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) {
+ if (mask && 0 <= x && x < fb->width && 0 <= y && y < fb->height) {
+ setpixel(fb, x, y, col);
+ }
+}
+
+STATIC inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
return formats[fb->format].getpixel(fb, x, y);
}
@@ -263,21 +270,21 @@ STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, u
formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col);
}
-STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
mp_arg_check_num(n_args, n_kw, 4, 5, false);
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type);
- o->buf_obj = args[0];
+ o->buf_obj = args_in[0];
mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
+ mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
- o->width = mp_obj_get_int(args[1]);
- o->height = mp_obj_get_int(args[2]);
- o->format = mp_obj_get_int(args[3]);
+ o->width = mp_obj_get_int(args_in[1]);
+ o->height = mp_obj_get_int(args_in[2]);
+ o->format = mp_obj_get_int(args_in[3]);
if (n_args >= 5) {
- o->stride = mp_obj_get_int(args[4]);
+ o->stride = mp_obj_get_int(args_in[4]);
} else {
o->stride = o->width;
}
@@ -305,6 +312,12 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
return MP_OBJ_FROM_PTR(o);
}
+STATIC void framebuf_args(const mp_obj_t *args_in, mp_int_t *args_out, int n) {
+ for (int i = 0; i < n; ++i) {
+ args_out[i] = mp_obj_get_int(args_in[i + 1]);
+ }
+}
+
STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
(void)flags;
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);
@@ -322,98 +335,75 @@ STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill);
-STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
-
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t width = mp_obj_get_int(args[3]);
- mp_int_t height = mp_obj_get_int(args[4]);
- mp_int_t col = mp_obj_get_int(args[5]);
-
- fill_rect(self, x, y, width, height, col);
-
+STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5]; // x, y, w, h, col
+ framebuf_args(args_in, args, 5);
+ fill_rect(self, args[0], args[1], args[2], args[3], args[4]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect);
-STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) {
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
+STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t x = mp_obj_get_int(args_in[1]);
+ mp_int_t y = mp_obj_get_int(args_in[2]);
if (0 <= x && x < self->width && 0 <= y && y < self->height) {
if (n_args == 3) {
// get
return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y));
} else {
// set
- setpixel(self, x, y, mp_obj_get_int(args[3]));
+ setpixel(self, x, y, mp_obj_get_int(args_in[3]));
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel);
-STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args_in) {
(void)n_args;
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t w = mp_obj_get_int(args[3]);
- mp_int_t col = mp_obj_get_int(args[4]);
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[4]; // x, y, w, col
+ framebuf_args(args_in, args, 4);
- fill_rect(self, x, y, w, 1, col);
+ fill_rect(self, args[0], args[1], args[2], 1, args[3]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline);
-STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args_in) {
(void)n_args;
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t h = mp_obj_get_int(args[3]);
- mp_int_t col = mp_obj_get_int(args[4]);
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[4]; // x, y, h, col
+ framebuf_args(args_in, args, 4);
- fill_rect(self, x, y, 1, h, col);
+ fill_rect(self, args[0], args[1], 1, args[2], args[3]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline);
-STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
-
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t w = mp_obj_get_int(args[3]);
- mp_int_t h = mp_obj_get_int(args[4]);
- mp_int_t col = mp_obj_get_int(args[5]);
-
- fill_rect(self, x, y, w, 1, col);
- fill_rect(self, x, y + h - 1, w, 1, col);
- fill_rect(self, x, y, 1, h, col);
- fill_rect(self, x + w - 1, y, 1, h, col);
-
+STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5]; // x, y, w, h, col
+ framebuf_args(args_in, args, 5);
+ if (n_args > 6 && mp_obj_is_true(args_in[6])) {
+ fill_rect(self, args[0], args[1], args[2], args[3], args[4]);
+ } else {
+ fill_rect(self, args[0], args[1], args[2], 1, args[4]);
+ fill_rect(self, args[0], args[1] + args[3] - 1, args[2], 1, args[4]);
+ fill_rect(self, args[0], args[1], 1, args[3], args[4]);
+ fill_rect(self, args[0] + args[2] - 1, args[1], 1, args[3], args[4]);
+ }
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect);
-
-STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
-
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x1 = mp_obj_get_int(args[1]);
- mp_int_t y1 = mp_obj_get_int(args[2]);
- mp_int_t x2 = mp_obj_get_int(args[3]);
- mp_int_t y2 = mp_obj_get_int(args[4]);
- mp_int_t col = mp_obj_get_int(args[5]);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 7, framebuf_rect);
+STATIC void line(const mp_obj_framebuf_t *fb, mp_int_t x1, mp_int_t y1, mp_int_t x2, mp_int_t y2, mp_int_t col) {
mp_int_t dx = x2 - x1;
mp_int_t sx;
if (dx > 0) {
@@ -452,12 +442,12 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
mp_int_t e = 2 * dy - dx;
for (mp_int_t i = 0; i < dx; ++i) {
if (steep) {
- if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) {
- setpixel(self, y1, x1, col);
+ if (0 <= y1 && y1 < fb->width && 0 <= x1 && x1 < fb->height) {
+ setpixel(fb, y1, x1, col);
}
} else {
- if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) {
- setpixel(self, x1, y1, col);
+ if (0 <= x1 && x1 < fb->width && 0 <= y1 && y1 < fb->height) {
+ setpixel(fb, x1, y1, col);
}
}
while (e >= 0) {
@@ -468,31 +458,250 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
e += 2 * dy;
}
- if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) {
- setpixel(self, x2, y2, col);
+ if (0 <= x2 && x2 < fb->width && 0 <= y2 && y2 < fb->height) {
+ setpixel(fb, x2, y2, col);
}
+}
+
+STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) {
+ (void)n_args;
+
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5]; // x1, y1, x2, y2, col
+ framebuf_args(args_in, args, 5);
+
+ line(self, args[0], args[1], args[2], args[3], args[4]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line);
-STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_obj_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf));
+// Q2 Q1
+// Q3 Q4
+#define ELLIPSE_MASK_FILL (0x10)
+#define ELLIPSE_MASK_ALL (0x0f)
+#define ELLIPSE_MASK_Q1 (0x01)
+#define ELLIPSE_MASK_Q2 (0x02)
+#define ELLIPSE_MASK_Q3 (0x04)
+#define ELLIPSE_MASK_Q4 (0x08)
+
+STATIC void draw_ellipse_points(const mp_obj_framebuf_t *fb, mp_int_t cx, mp_int_t cy, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) {
+ if (mask & ELLIPSE_MASK_FILL) {
+ if (mask & ELLIPSE_MASK_Q1) {
+ fill_rect(fb, cx, cy - y, x + 1, 1, col);
+ }
+ if (mask & ELLIPSE_MASK_Q2) {
+ fill_rect(fb, cx - x, cy - y, x + 1, 1, col);
+ }
+ if (mask & ELLIPSE_MASK_Q3) {
+ fill_rect(fb, cx - x, cy + y, x + 1, 1, col);
+ }
+ if (mask & ELLIPSE_MASK_Q4) {
+ fill_rect(fb, cx, cy + y, x + 1, 1, col);
+ }
+ } else {
+ setpixel_checked(fb, cx + x, cy - y, col, mask & ELLIPSE_MASK_Q1);
+ setpixel_checked(fb, cx - x, cy - y, col, mask & ELLIPSE_MASK_Q2);
+ setpixel_checked(fb, cx - x, cy + y, col, mask & ELLIPSE_MASK_Q3);
+ setpixel_checked(fb, cx + x, cy + y, col, mask & ELLIPSE_MASK_Q4);
+ }
+}
+
+STATIC mp_obj_t framebuf_ellipse(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5];
+ framebuf_args(args_in, args, 5); // cx, cy, xradius, yradius, col
+ mp_int_t mask = (n_args > 6 && mp_obj_is_true(args_in[6])) ? ELLIPSE_MASK_FILL : 0;
+ if (n_args > 7) {
+ mask |= mp_obj_get_int(args_in[7]) & ELLIPSE_MASK_ALL;
+ } else {
+ mask |= ELLIPSE_MASK_ALL;
+ }
+ mp_int_t two_asquare = 2 * args[2] * args[2];
+ mp_int_t two_bsquare = 2 * args[3] * args[3];
+ mp_int_t x = args[2];
+ mp_int_t y = 0;
+ mp_int_t xchange = args[3] * args[3] * (1 - 2 * args[2]);
+ mp_int_t ychange = args[2] * args[2];
+ mp_int_t ellipse_error = 0;
+ mp_int_t stoppingx = two_bsquare * args[2];
+ mp_int_t stoppingy = 0;
+ while (stoppingx >= stoppingy) { // 1st set of points, y' > -1
+ draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask);
+ y += 1;
+ stoppingy += two_asquare;
+ ellipse_error += ychange;
+ ychange += two_asquare;
+ if ((2 * ellipse_error + xchange) > 0) {
+ x -= 1;
+ stoppingx -= two_bsquare;
+ ellipse_error += xchange;
+ xchange += two_bsquare;
+ }
+ }
+ // 1st point set is done start the 2nd set of points
+ x = 0;
+ y = args[3];
+ xchange = args[3] * args[3];
+ ychange = args[2] * args[2] * (1 - 2 * args[3]);
+ ellipse_error = 0;
+ stoppingx = 0;
+ stoppingy = two_asquare * args[3];
+ while (stoppingx <= stoppingy) { // 2nd set of points, y' < -1
+ draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask);
+ x += 1;
+ stoppingx += two_bsquare;
+ ellipse_error += xchange;
+ xchange += two_bsquare;
+ if ((2 * ellipse_error + ychange) > 0) {
+ y -= 1;
+ stoppingy -= two_asquare;
+ ellipse_error += ychange;
+ ychange += two_asquare;
+ }
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_ellipse_obj, 6, 8, framebuf_ellipse);
+
+#if MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME
+// TODO: poly needs mp_binary_get_size & mp_binary_get_val_array which aren't
+// available in dynruntime.h yet.
+
+STATIC mp_int_t poly_int(mp_buffer_info_t *bufinfo, size_t index) {
+ return mp_obj_get_int(mp_binary_get_val_array(bufinfo->typecode, bufinfo->buf, index));
+}
+
+STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+
+ mp_int_t x = mp_obj_get_int(args_in[1]);
+ mp_int_t y = mp_obj_get_int(args_in[2]);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args_in[3], &bufinfo, MP_BUFFER_READ);
+ // If an odd number of values was given, this rounds down to multiple of two.
+ int n_poly = bufinfo.len / (mp_binary_get_size('@', bufinfo.typecode, NULL) * 2);
+
+ if (n_poly == 0) {
+ return mp_const_none;
+ }
+
+ mp_int_t col = mp_obj_get_int(args_in[4]);
+ bool fill = n_args > 5 && mp_obj_is_true(args_in[5]);
+
+ if (fill) {
+ // This implements an integer version of http://alienryderflex.com/polygon_fill/
+
+ // The idea is for each scan line, compute the sorted list of x
+ // coordinates where the scan line intersects the polygon edges,
+ // then fill between each resulting pair.
+
+ // Restrict just to the scan lines that include the vertical extent of
+ // this polygon.
+ mp_int_t y_min = INT_MAX, y_max = INT_MIN;
+ for (int i = 0; i < n_poly; i++) {
+ mp_int_t py = poly_int(&bufinfo, i * 2 + 1);
+ y_min = MIN(y_min, py);
+ y_max = MAX(y_max, py);
+ }
+
+ for (mp_int_t row = y_min; row <= y_max; row++) {
+ // Each node is the x coordinate where an edge crosses this scan line.
+ mp_int_t nodes[n_poly];
+ int n_nodes = 0;
+ mp_int_t px1 = poly_int(&bufinfo, 0);
+ mp_int_t py1 = poly_int(&bufinfo, 1);
+ int i = n_poly * 2 - 1;
+ do {
+ mp_int_t py2 = poly_int(&bufinfo, i--);
+ mp_int_t px2 = poly_int(&bufinfo, i--);
+
+ // Don't include the bottom pixel of a given edge to avoid
+ // duplicating the node with the start of the next edge. This
+ // will miss some pixels on the boundary, and in particular
+ // at a local minima or inflection point.
+ if (py1 != py2 && ((py1 > row && py2 <= row) || (py1 <= row && py2 > row))) {
+ mp_int_t node = (32 * px1 + 32 * (px2 - px1) * (row - py1) / (py2 - py1) + 16) / 32;
+ nodes[n_nodes++] = node;
+ } else if (row == MAX(py1, py2)) {
+ // At local-minima, try and manually fill in the pixels that get missed above.
+ if (py1 < py2) {
+ setpixel_checked(self, x + px2, y + py2, col, 1);
+ } else if (py2 < py1) {
+ setpixel_checked(self, x + px1, y + py1, col, 1);
+ } else {
+ // Even though this is a hline and would be faster to
+ // use fill_rect, use line() because it handles x2 <
+ // x1.
+ line(self, x + px1, y + py1, x + px2, y + py2, col);
+ }
+ }
+
+ px1 = px2;
+ py1 = py2;
+ } while (i >= 0);
+
+ if (!n_nodes) {
+ continue;
+ }
+
+ // Sort the nodes left-to-right (bubble-sort for code size).
+ i = 0;
+ while (i < n_nodes - 1) {
+ if (nodes[i] > nodes[i + 1]) {
+ mp_int_t swap = nodes[i];
+ nodes[i] = nodes[i + 1];
+ nodes[i + 1] = swap;
+ if (i) {
+ i--;
+ }
+ } else {
+ i++;
+ }
+ }
+
+ // Fill between each pair of nodes.
+ for (i = 0; i < n_nodes; i += 2) {
+ fill_rect(self, x + nodes[i], y + row, (nodes[i + 1] - nodes[i]) + 1, 1, col);
+ }
+ }
+ } else {
+ // Outline only.
+ mp_int_t px1 = poly_int(&bufinfo, 0);
+ mp_int_t py1 = poly_int(&bufinfo, 1);
+ int i = n_poly * 2 - 1;
+ do {
+ mp_int_t py2 = poly_int(&bufinfo, i--);
+ mp_int_t px2 = poly_int(&bufinfo, i--);
+ line(self, x + px1, y + py1, x + px2, y + py2, col);
+ px1 = px2;
+ py1 = py2;
+ } while (i >= 0);
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_poly_obj, 5, 6, framebuf_poly);
+#endif // MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME
+
+STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_obj_t source_in = mp_obj_cast_to_native_base(args_in[1], MP_OBJ_FROM_PTR(&mp_type_framebuf));
if (source_in == MP_OBJ_NULL) {
mp_raise_TypeError(NULL);
}
mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in);
- mp_int_t x = mp_obj_get_int(args[2]);
- mp_int_t y = mp_obj_get_int(args[3]);
+ mp_int_t x = mp_obj_get_int(args_in[2]);
+ mp_int_t y = mp_obj_get_int(args_in[3]);
mp_int_t key = -1;
if (n_args > 4) {
- key = mp_obj_get_int(args[4]);
+ key = mp_obj_get_int(args_in[4]);
}
mp_obj_framebuf_t *palette = NULL;
- if (n_args > 5 && args[5] != mp_const_none) {
- palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
+ if (n_args > 5 && args_in[5] != mp_const_none) {
+ palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args_in[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
}
if (
@@ -539,19 +748,31 @@ STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ys
if (xstep < 0) {
sx = 0;
xend = self->width + xstep;
+ if (xend <= 0) {
+ return mp_const_none;
+ }
dx = 1;
} else {
sx = self->width - 1;
xend = xstep - 1;
+ if (xend >= sx) {
+ return mp_const_none;
+ }
dx = -1;
}
if (ystep < 0) {
y = 0;
yend = self->height + ystep;
+ if (yend <= 0) {
+ return mp_const_none;
+ }
dy = 1;
} else {
y = self->height - 1;
yend = ystep - 1;
+ if (yend >= y) {
+ return mp_const_none;
+ }
dy = -1;
}
for (; y != yend; y += dy) {
@@ -563,15 +784,15 @@ STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ys
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll);
-STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args_in) {
// extract arguments
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- const char *str = mp_obj_str_get_str(args[1]);
- mp_int_t x0 = mp_obj_get_int(args[2]);
- mp_int_t y0 = mp_obj_get_int(args[3]);
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ const char *str = mp_obj_str_get_str(args_in[1]);
+ mp_int_t x0 = mp_obj_get_int(args_in[2]);
+ mp_int_t y0 = mp_obj_get_int(args_in[3]);
mp_int_t col = 1;
if (n_args >= 5) {
- col = mp_obj_get_int(args[4]);
+ col = mp_obj_get_int(args_in[4]);
}
// loop over chars
@@ -610,34 +831,39 @@ STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) },
{ MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) },
{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&framebuf_ellipse_obj) },
+ #if MICROPY_PY_ARRAY
+ { MP_ROM_QSTR(MP_QSTR_poly), MP_ROM_PTR(&framebuf_poly_obj) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) },
{ MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) },
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) },
};
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
-STATIC const mp_obj_type_t mp_type_framebuf = {
- { &mp_type_type },
- .name = MP_QSTR_FrameBuffer,
- .make_new = framebuf_make_new,
- .buffer_p = { .get_buffer = framebuf_get_buffer },
- .locals_dict = (mp_obj_dict_t *)&framebuf_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_framebuf,
+ MP_QSTR_FrameBuffer,
+ MP_TYPE_FLAG_NONE,
+ make_new, framebuf_make_new,
+ buffer, framebuf_get_buffer,
+ locals_dict, &framebuf_locals_dict
+ );
#endif
// this factory function is provided for backwards compatibility with old FrameBuffer1 class
-STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) {
- mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, &mp_type_framebuf);
+STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, (mp_obj_type_t *)&mp_type_framebuf);
mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
+ mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
- o->width = mp_obj_get_int(args[1]);
- o->height = mp_obj_get_int(args[2]);
+ o->width = mp_obj_get_int(args_in[1]);
+ o->height = mp_obj_get_int(args_in[2]);
o->format = FRAMEBUF_MVLSB;
if (n_args >= 4) {
- o->stride = mp_obj_get_int(args[3]);
+ o->stride = mp_obj_get_int(args_in[3]);
} else {
o->stride = o->width;
}
diff --git a/extmod/modhashlib.c b/extmod/modhashlib.c
new file mode 100644
index 0000000000000..4cdc23fddc6c6
--- /dev/null
+++ b/extmod/modhashlib.c
@@ -0,0 +1,379 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/runtime.h"
+
+#if MICROPY_PY_HASHLIB
+
+#if MICROPY_SSL_MBEDTLS
+#include "mbedtls/version.h"
+#endif
+
+#if MICROPY_PY_HASHLIB_SHA256
+
+#if MICROPY_SSL_MBEDTLS
+#include "mbedtls/sha256.h"
+#else
+#include "lib/crypto-algorithms/sha256.h"
+#endif
+
+#endif
+
+#if MICROPY_PY_HASHLIB_SHA1 || MICROPY_PY_HASHLIB_MD5
+
+#if MICROPY_SSL_AXTLS
+#include "lib/axtls/crypto/crypto.h"
+#endif
+
+#if MICROPY_SSL_MBEDTLS
+#include "mbedtls/md5.h"
+#include "mbedtls/sha1.h"
+#endif
+
+#endif
+
+typedef struct _mp_obj_hash_t {
+ mp_obj_base_t base;
+ bool final; // if set, update and digest raise an exception
+ uintptr_t state[0]; // must be aligned to a machine word
+} mp_obj_hash_t;
+
+static void hashlib_ensure_not_final(mp_obj_hash_t *self) {
+ if (self->final) {
+ mp_raise_ValueError(MP_ERROR_TEXT("hash is final"));
+ }
+}
+
+#if MICROPY_PY_HASHLIB_SHA256
+STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
+
+#if MICROPY_SSL_MBEDTLS
+
+#if MBEDTLS_VERSION_NUMBER < 0x02070000 || MBEDTLS_VERSION_NUMBER >= 0x03000000
+#define mbedtls_sha256_starts_ret mbedtls_sha256_starts
+#define mbedtls_sha256_update_ret mbedtls_sha256_update
+#define mbedtls_sha256_finish_ret mbedtls_sha256_finish
+#endif
+
+STATIC mp_obj_t hashlib_sha256_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, 1, false);
+ mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context), type);
+ o->final = false;
+ mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
+ mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
+ if (n_args == 1) {
+ hashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
+ }
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
+ mbedtls_sha256_update_ret((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
+ return mp_const_none;
+}
+
+STATIC mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ self->final = true;
+ vstr_t vstr;
+ vstr_init_len(&vstr, 32);
+ mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+
+#else
+
+#include "lib/crypto-algorithms/sha256.c"
+
+STATIC mp_obj_t hashlib_sha256_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, 1, false);
+ mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX), type);
+ o->final = false;
+ sha256_init((CRYAL_SHA256_CTX *)o->state);
+ if (n_args == 1) {
+ hashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
+ }
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
+ sha256_update((CRYAL_SHA256_CTX *)self->state, bufinfo.buf, bufinfo.len);
+ return mp_const_none;
+}
+
+STATIC mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ self->final = true;
+ vstr_t vstr;
+ vstr_init_len(&vstr, SHA256_BLOCK_SIZE);
+ sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf);
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+#endif
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha256_update_obj, hashlib_sha256_update);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha256_digest_obj, hashlib_sha256_digest);
+
+STATIC const mp_rom_map_elem_t hashlib_sha256_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_sha256_update_obj) },
+ { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_sha256_digest_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(hashlib_sha256_locals_dict, hashlib_sha256_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ hashlib_sha256_type,
+ MP_QSTR_sha256,
+ MP_TYPE_FLAG_NONE,
+ make_new, hashlib_sha256_make_new,
+ locals_dict, &hashlib_sha256_locals_dict
+ );
+#endif
+
+#if MICROPY_PY_HASHLIB_SHA1
+STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg);
+
+#if MICROPY_SSL_AXTLS
+STATIC mp_obj_t hashlib_sha1_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, 1, false);
+ mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(SHA1_CTX), type);
+ o->final = false;
+ SHA1_Init((SHA1_CTX *)o->state);
+ if (n_args == 1) {
+ hashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
+ }
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
+ SHA1_Update((SHA1_CTX *)self->state, bufinfo.buf, bufinfo.len);
+ return mp_const_none;
+}
+
+STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ self->final = true;
+ vstr_t vstr;
+ vstr_init_len(&vstr, SHA1_SIZE);
+ SHA1_Final((byte *)vstr.buf, (SHA1_CTX *)self->state);
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+#endif
+
+#if MICROPY_SSL_MBEDTLS
+
+#if MBEDTLS_VERSION_NUMBER < 0x02070000 || MBEDTLS_VERSION_NUMBER >= 0x03000000
+#define mbedtls_sha1_starts_ret mbedtls_sha1_starts
+#define mbedtls_sha1_update_ret mbedtls_sha1_update
+#define mbedtls_sha1_finish_ret mbedtls_sha1_finish
+#endif
+
+STATIC mp_obj_t hashlib_sha1_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, 1, false);
+ mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context), type);
+ o->final = false;
+ mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
+ mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
+ if (n_args == 1) {
+ hashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
+ }
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
+ mbedtls_sha1_update_ret((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
+ return mp_const_none;
+}
+
+STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ self->final = true;
+ vstr_t vstr;
+ vstr_init_len(&vstr, 20);
+ mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
+ mbedtls_sha1_free((mbedtls_sha1_context *)self->state);
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+#endif
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha1_update_obj, hashlib_sha1_update);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha1_digest_obj, hashlib_sha1_digest);
+
+STATIC const mp_rom_map_elem_t hashlib_sha1_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_sha1_update_obj) },
+ { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_sha1_digest_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(hashlib_sha1_locals_dict, hashlib_sha1_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ hashlib_sha1_type,
+ MP_QSTR_sha1,
+ MP_TYPE_FLAG_NONE,
+ make_new, hashlib_sha1_make_new,
+ locals_dict, &hashlib_sha1_locals_dict
+ );
+#endif
+
+#if MICROPY_PY_HASHLIB_MD5
+STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
+
+#if MICROPY_SSL_AXTLS
+STATIC mp_obj_t hashlib_md5_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, 1, false);
+ mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(MD5_CTX), type);
+ o->final = false;
+ MD5_Init((MD5_CTX *)o->state);
+ if (n_args == 1) {
+ hashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
+ }
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
+ MD5_Update((MD5_CTX *)self->state, bufinfo.buf, bufinfo.len);
+ return mp_const_none;
+}
+
+STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ self->final = true;
+ vstr_t vstr;
+ vstr_init_len(&vstr, MD5_SIZE);
+ MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state);
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+#endif // MICROPY_SSL_AXTLS
+
+#if MICROPY_SSL_MBEDTLS
+
+#if MBEDTLS_VERSION_NUMBER < 0x02070000
+#define mbedtls_md5_starts_ret mbedtls_md5_starts
+#define mbedtls_md5_update_ret mbedtls_md5_update
+#define mbedtls_md5_finish_ret mbedtls_md5_finish
+#endif
+
+STATIC mp_obj_t hashlib_md5_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, 1, false);
+ mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context), type);
+ o->final = false;
+ mbedtls_md5_init((mbedtls_md5_context *)o->state);
+ mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
+ if (n_args == 1) {
+ hashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
+ }
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
+ mbedtls_md5_update_ret((mbedtls_md5_context *)self->state, bufinfo.buf, bufinfo.len);
+ return mp_const_none;
+}
+
+STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) {
+ mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
+ hashlib_ensure_not_final(self);
+ self->final = true;
+ vstr_t vstr;
+ vstr_init_len(&vstr, 16);
+ mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf);
+ mbedtls_md5_free((mbedtls_md5_context *)self->state);
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+#endif // MICROPY_SSL_MBEDTLS
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_md5_update_obj, hashlib_md5_update);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_md5_digest_obj, hashlib_md5_digest);
+
+STATIC const mp_rom_map_elem_t hashlib_md5_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_md5_update_obj) },
+ { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_md5_digest_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(hashlib_md5_locals_dict, hashlib_md5_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ hashlib_md5_type,
+ MP_QSTR_md5,
+ MP_TYPE_FLAG_NONE,
+ make_new, hashlib_md5_make_new,
+ locals_dict, &hashlib_md5_locals_dict
+ );
+#endif // MICROPY_PY_HASHLIB_MD5
+
+STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hashlib) },
+ #if MICROPY_PY_HASHLIB_SHA256
+ { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&hashlib_sha256_type) },
+ #endif
+ #if MICROPY_PY_HASHLIB_SHA1
+ { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&hashlib_sha1_type) },
+ #endif
+ #if MICROPY_PY_HASHLIB_MD5
+ { MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&hashlib_md5_type) },
+ #endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table);
+
+const mp_obj_module_t mp_module_hashlib = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_hashlib_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_hashlib, mp_module_hashlib);
+
+#endif // MICROPY_PY_HASHLIB
diff --git a/extmod/modheapq.c b/extmod/modheapq.c
new file mode 100644
index 0000000000000..db1e35bac2830
--- /dev/null
+++ b/extmod/modheapq.c
@@ -0,0 +1,124 @@
+/*
+ * 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 "py/objlist.h"
+#include "py/runtime.h"
+
+#if MICROPY_PY_HEAPQ
+
+// the algorithm here is modelled on CPython's heapq.py
+
+STATIC mp_obj_list_t *heapq_get_heap(mp_obj_t heap_in) {
+ if (!mp_obj_is_type(heap_in, &mp_type_list)) {
+ mp_raise_TypeError(MP_ERROR_TEXT("heap must be a list"));
+ }
+ return MP_OBJ_TO_PTR(heap_in);
+}
+
+STATIC void heapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
+ mp_obj_t item = heap->items[pos];
+ while (pos > start_pos) {
+ mp_uint_t parent_pos = (pos - 1) >> 1;
+ mp_obj_t parent = heap->items[parent_pos];
+ if (mp_binary_op(MP_BINARY_OP_LESS, item, parent) == mp_const_true) {
+ heap->items[pos] = parent;
+ pos = parent_pos;
+ } else {
+ break;
+ }
+ }
+ heap->items[pos] = item;
+}
+
+STATIC void heapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
+ mp_uint_t start_pos = pos;
+ mp_uint_t end_pos = heap->len;
+ mp_obj_t item = heap->items[pos];
+ for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) {
+ // choose right child if it's <= left child
+ if (child_pos + 1 < end_pos && mp_binary_op(MP_BINARY_OP_LESS, heap->items[child_pos], heap->items[child_pos + 1]) == mp_const_false) {
+ child_pos += 1;
+ }
+ // bubble up the smaller child
+ heap->items[pos] = heap->items[child_pos];
+ pos = child_pos;
+ }
+ heap->items[pos] = item;
+ heapq_heap_siftdown(heap, start_pos, pos);
+}
+
+STATIC mp_obj_t mod_heapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
+ mp_obj_list_t *heap = heapq_get_heap(heap_in);
+ mp_obj_list_append(heap_in, item);
+ heapq_heap_siftdown(heap, 0, heap->len - 1);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_heapq_heappush_obj, mod_heapq_heappush);
+
+STATIC mp_obj_t mod_heapq_heappop(mp_obj_t heap_in) {
+ mp_obj_list_t *heap = heapq_get_heap(heap_in);
+ if (heap->len == 0) {
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
+ }
+ mp_obj_t item = heap->items[0];
+ heap->len -= 1;
+ heap->items[0] = heap->items[heap->len];
+ heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer
+ if (heap->len) {
+ heapq_heap_siftup(heap, 0);
+ }
+ return item;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heappop_obj, mod_heapq_heappop);
+
+STATIC mp_obj_t mod_heapq_heapify(mp_obj_t heap_in) {
+ mp_obj_list_t *heap = heapq_get_heap(heap_in);
+ for (mp_uint_t i = heap->len / 2; i > 0;) {
+ heapq_heap_siftup(heap, --i);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heapify_obj, mod_heapq_heapify);
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_rom_map_elem_t mp_module_heapq_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_heapq) },
+ { MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_heapq_heappush_obj) },
+ { MP_ROM_QSTR(MP_QSTR_heappop), MP_ROM_PTR(&mod_heapq_heappop_obj) },
+ { MP_ROM_QSTR(MP_QSTR_heapify), MP_ROM_PTR(&mod_heapq_heapify_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_heapq_globals, mp_module_heapq_globals_table);
+
+const mp_obj_module_t mp_module_heapq = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_heapq_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_heapq, mp_module_heapq);
+#endif
+
+#endif // MICROPY_PY_HEAPQ
diff --git a/extmod/modjson.c b/extmod/modjson.c
new file mode 100644
index 0000000000000..1772b7299886e
--- /dev/null
+++ b/extmod/modjson.c
@@ -0,0 +1,386 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+
+#include "py/objlist.h"
+#include "py/objstringio.h"
+#include "py/parsenum.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+
+#if MICROPY_PY_JSON
+
+#if MICROPY_PY_JSON_SEPARATORS
+
+enum {
+ DUMP_MODE_TO_STRING = 1,
+ DUMP_MODE_TO_STREAM = 2,
+};
+
+STATIC mp_obj_t mod_json_dump_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, unsigned int mode) {
+ enum { ARG_separators };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_separators, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - mode, pos_args + mode, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_print_ext_t print_ext;
+
+ if (args[ARG_separators].u_obj == mp_const_none) {
+ print_ext.item_separator = ", ";
+ print_ext.key_separator = ": ";
+ } else {
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(args[ARG_separators].u_obj, 2, &items);
+ print_ext.item_separator = mp_obj_str_get_str(items[0]);
+ print_ext.key_separator = mp_obj_str_get_str(items[1]);
+ }
+
+ if (mode == DUMP_MODE_TO_STRING) {
+ // dumps(obj)
+ vstr_t vstr;
+ vstr_init_print(&vstr, 8, &print_ext.base);
+ mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON);
+ return mp_obj_new_str_from_utf8_vstr(&vstr);
+ } else {
+ // dump(obj, stream)
+ print_ext.base.data = MP_OBJ_TO_PTR(pos_args[1]);
+ print_ext.base.print_strn = mp_stream_write_adaptor;
+ mp_get_stream_raise(pos_args[1], MP_STREAM_OP_WRITE);
+ mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON);
+ return mp_const_none;
+ }
+}
+
+STATIC mp_obj_t mod_json_dump(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ return mod_json_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STREAM);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dump_obj, 2, mod_json_dump);
+
+STATIC mp_obj_t mod_json_dumps(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ return mod_json_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STRING);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dumps_obj, 1, mod_json_dumps);
+
+#else
+
+STATIC mp_obj_t mod_json_dump(mp_obj_t obj, mp_obj_t stream) {
+ mp_get_stream_raise(stream, MP_STREAM_OP_WRITE);
+ mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor};
+ mp_obj_print_helper(&print, obj, PRINT_JSON);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_json_dump_obj, mod_json_dump);
+
+STATIC mp_obj_t mod_json_dumps(mp_obj_t obj) {
+ vstr_t vstr;
+ mp_print_t print;
+ vstr_init_print(&vstr, 8, &print);
+ mp_obj_print_helper(&print, obj, PRINT_JSON);
+ return mp_obj_new_str_from_utf8_vstr(&vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_dumps_obj, mod_json_dumps);
+
+#endif
+
+// The function below implements a simple non-recursive JSON parser.
+//
+// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
+// The parser here will parse any valid JSON and return the correct
+// corresponding Python object. It allows through a superset of JSON, since
+// it treats commas and colons as "whitespace", and doesn't care if
+// brackets/braces are correctly paired. It will raise a ValueError if the
+// input is outside it's specs.
+//
+// Most of the work is parsing the primitives (null, false, true, numbers,
+// strings). It does 1 pass over the input stream. It tries to be fast and
+// small in code size, while not using more RAM than necessary.
+
+typedef struct _json_stream_t {
+ mp_obj_t stream_obj;
+ mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
+ int errcode;
+ byte cur;
+} json_stream_t;
+
+#define S_EOF (0) // null is not allowed in json stream so is ok as EOF marker
+#define S_END(s) ((s).cur == S_EOF)
+#define S_CUR(s) ((s).cur)
+#define S_NEXT(s) (json_stream_next(&(s)))
+
+STATIC byte json_stream_next(json_stream_t *s) {
+ mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
+ if (s->errcode != 0) {
+ mp_raise_OSError(s->errcode);
+ }
+ if (ret == 0) {
+ s->cur = S_EOF;
+ }
+ return s->cur;
+}
+
+STATIC mp_obj_t mod_json_load(mp_obj_t stream_obj) {
+ const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ);
+ json_stream_t s = {stream_obj, stream_p->read, 0, 0};
+ vstr_t vstr;
+ vstr_init(&vstr, 8);
+ mp_obj_list_t stack; // we use a list as a simple stack for nested JSON
+ stack.len = 0;
+ stack.items = NULL;
+ mp_obj_t stack_top = MP_OBJ_NULL;
+ const mp_obj_type_t *stack_top_type = NULL;
+ mp_obj_t stack_key = MP_OBJ_NULL;
+ S_NEXT(s);
+ for (;;) {
+ cont:
+ if (S_END(s)) {
+ break;
+ }
+ mp_obj_t next = MP_OBJ_NULL;
+ bool enter = false;
+ byte cur = S_CUR(s);
+ S_NEXT(s);
+ switch (cur) {
+ case ',':
+ case ':':
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ goto cont;
+ case 'n':
+ if (S_CUR(s) == 'u' && S_NEXT(s) == 'l' && S_NEXT(s) == 'l') {
+ S_NEXT(s);
+ next = mp_const_none;
+ } else {
+ goto fail;
+ }
+ break;
+ case 'f':
+ if (S_CUR(s) == 'a' && S_NEXT(s) == 'l' && S_NEXT(s) == 's' && S_NEXT(s) == 'e') {
+ S_NEXT(s);
+ next = mp_const_false;
+ } else {
+ goto fail;
+ }
+ break;
+ case 't':
+ if (S_CUR(s) == 'r' && S_NEXT(s) == 'u' && S_NEXT(s) == 'e') {
+ S_NEXT(s);
+ next = mp_const_true;
+ } else {
+ goto fail;
+ }
+ break;
+ case '"':
+ vstr_reset(&vstr);
+ for (; !S_END(s) && S_CUR(s) != '"';) {
+ byte c = S_CUR(s);
+ if (c == '\\') {
+ c = S_NEXT(s);
+ switch (c) {
+ case 'b':
+ c = 0x08;
+ break;
+ case 'f':
+ c = 0x0c;
+ break;
+ case 'n':
+ c = 0x0a;
+ break;
+ case 'r':
+ c = 0x0d;
+ break;
+ case 't':
+ c = 0x09;
+ break;
+ case 'u': {
+ mp_uint_t num = 0;
+ for (int i = 0; i < 4; i++) {
+ c = (S_NEXT(s) | 0x20) - '0';
+ if (c > 9) {
+ c -= ('a' - ('9' + 1));
+ }
+ num = (num << 4) | c;
+ }
+ vstr_add_char(&vstr, num);
+ goto str_cont;
+ }
+ }
+ }
+ vstr_add_byte(&vstr, c);
+ str_cont:
+ S_NEXT(s);
+ }
+ if (S_END(s)) {
+ goto fail;
+ }
+ S_NEXT(s);
+ next = mp_obj_new_str(vstr.buf, vstr.len);
+ break;
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ bool flt = false;
+ vstr_reset(&vstr);
+ for (;;) {
+ vstr_add_byte(&vstr, cur);
+ cur = S_CUR(s);
+ if (cur == '.' || cur == 'E' || cur == 'e') {
+ flt = true;
+ } else if (cur == '+' || cur == '-' || unichar_isdigit(cur)) {
+ // pass
+ } else {
+ break;
+ }
+ S_NEXT(s);
+ }
+ if (flt) {
+ next = mp_parse_num_float(vstr.buf, vstr.len, false, NULL);
+ } else {
+ next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);
+ }
+ break;
+ }
+ case '[':
+ next = mp_obj_new_list(0, NULL);
+ enter = true;
+ break;
+ case '{':
+ next = mp_obj_new_dict(0);
+ enter = true;
+ break;
+ case '}':
+ case ']': {
+ if (stack_top == MP_OBJ_NULL) {
+ // no object at all
+ goto fail;
+ }
+ if (stack.len == 0) {
+ // finished; compound object
+ goto success;
+ }
+ stack.len -= 1;
+ stack_top = stack.items[stack.len];
+ stack_top_type = mp_obj_get_type(stack_top);
+ goto cont;
+ }
+ default:
+ goto fail;
+ }
+ if (stack_top == MP_OBJ_NULL) {
+ stack_top = next;
+ stack_top_type = mp_obj_get_type(stack_top);
+ if (!enter) {
+ // finished; single primitive only
+ goto success;
+ }
+ } else {
+ // append to list or dict
+ if (stack_top_type == &mp_type_list) {
+ mp_obj_list_append(stack_top, next);
+ } else {
+ if (stack_key == MP_OBJ_NULL) {
+ stack_key = next;
+ if (enter) {
+ goto fail;
+ }
+ } else {
+ mp_obj_dict_store(stack_top, stack_key, next);
+ stack_key = MP_OBJ_NULL;
+ }
+ }
+ if (enter) {
+ if (stack.items == NULL) {
+ mp_obj_list_init(&stack, 1);
+ stack.items[0] = stack_top;
+ } else {
+ mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top);
+ }
+ stack_top = next;
+ stack_top_type = mp_obj_get_type(stack_top);
+ }
+ }
+ }
+success:
+ // eat trailing whitespace
+ while (unichar_isspace(S_CUR(s))) {
+ S_NEXT(s);
+ }
+ if (!S_END(s)) {
+ // unexpected chars
+ goto fail;
+ }
+ if (stack_top == MP_OBJ_NULL || stack.len != 0) {
+ // not exactly 1 object
+ goto fail;
+ }
+ vstr_clear(&vstr);
+ return stack_top;
+
+fail:
+ mp_raise_ValueError(MP_ERROR_TEXT("syntax error in JSON"));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_load_obj, mod_json_load);
+
+STATIC mp_obj_t mod_json_loads(mp_obj_t obj) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ);
+ vstr_t vstr = {bufinfo.len, bufinfo.len, (char *)bufinfo.buf, true};
+ mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
+ return mod_json_load(MP_OBJ_FROM_PTR(&sio));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_loads_obj, mod_json_loads);
+
+STATIC const mp_rom_map_elem_t mp_module_json_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_json) },
+ { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_json_dump_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_json_dumps_obj) },
+ { MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_json_load_obj) },
+ { MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_json_loads_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_json_globals, mp_module_json_globals_table);
+
+const mp_obj_module_t mp_module_json = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_json_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_json, mp_module_json);
+
+#endif // MICROPY_PY_JSON
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index bbfd3a2253cb8..0d4c03c68a876 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -66,6 +66,7 @@
// All socket options should be globally distinct,
// because we ignore option levels for efficiency.
#define IP_ADD_MEMBERSHIP 0x400
+#define IP_DROP_MEMBERSHIP 0x401
// For compatibilily with older lwIP versions.
#ifndef ip_set_option
@@ -176,12 +177,13 @@ STATIC const mp_rom_map_elem_t lwip_slip_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(lwip_slip_locals_dict, lwip_slip_locals_dict_table);
-STATIC const mp_obj_type_t lwip_slip_type = {
- { &mp_type_type },
- .name = MP_QSTR_slip,
- .make_new = lwip_slip_make_new,
- .locals_dict = (mp_obj_dict_t *)&lwip_slip_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ lwip_slip_type,
+ MP_QSTR_slip,
+ MP_TYPE_FLAG_NONE,
+ make_new, lwip_slip_make_new,
+ locals_dict, &lwip_slip_locals_dict
+ );
#endif // MICROPY_PY_LWIP_SLIP
@@ -916,7 +918,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_bind_obj, lwip_socket_bind);
STATIC mp_obj_t lwip_socket_listen(size_t n_args, const mp_obj_t *args) {
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(args[0]);
- mp_int_t backlog = MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT;
+ mp_int_t backlog = MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT;
if (n_args > 1) {
backlog = mp_obj_get_int(args[1]);
backlog = (backlog < 0) ? 0 : backlog;
@@ -929,9 +931,20 @@ STATIC mp_obj_t lwip_socket_listen(size_t n_args, const mp_obj_t *args) {
mp_raise_OSError(MP_EOPNOTSUPP);
}
- struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
+ struct tcp_pcb *new_pcb;
+ #if LWIP_VERSION_MACRO < 0x02000100
+ new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
+ #else
+ err_t error;
+ new_pcb = tcp_listen_with_backlog_and_err(socket->pcb.tcp, (u8_t)backlog, &error);
+ #endif
+
if (new_pcb == NULL) {
+ #if LWIP_VERSION_MACRO < 0x02000100
mp_raise_OSError(MP_ENOMEM);
+ #else
+ mp_raise_OSError(error_lookup_table[-error]);
+ #endif
}
socket->pcb.tcp = new_pcb;
@@ -1197,7 +1210,7 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
return mp_const_empty_bytes;
}
vstr.len = ret;
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recv_obj, lwip_socket_recv);
@@ -1270,7 +1283,7 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
tuple[0] = mp_const_empty_bytes;
} else {
vstr.len = ret;
- tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ tuple[0] = mp_obj_new_bytes_from_vstr(&vstr);
}
tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
return mp_obj_new_tuple(2, tuple);
@@ -1376,7 +1389,8 @@ STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
}
// level: IPPROTO_IP
- case IP_ADD_MEMBERSHIP: {
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP: {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != sizeof(ip_addr_t) * 2) {
@@ -1384,7 +1398,12 @@ STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
}
// POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa
- err_t err = igmp_joingroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf);
+ err_t err;
+ if (opt == IP_ADD_MEMBERSHIP) {
+ err = igmp_joingroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf);
+ } else {
+ err = igmp_leavegroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf);
+ }
if (err != ERR_OK) {
mp_raise_OSError(error_lookup_table[-err]);
}
@@ -1587,14 +1606,15 @@ STATIC const mp_stream_p_t lwip_socket_stream_p = {
.ioctl = lwip_socket_ioctl,
};
-STATIC const mp_obj_type_t lwip_socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_socket,
- .print = lwip_socket_print,
- .make_new = lwip_socket_make_new,
- .protocol = &lwip_socket_stream_p,
- .locals_dict = (mp_obj_dict_t *)&lwip_socket_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ lwip_socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, lwip_socket_make_new,
+ print, lwip_socket_print,
+ protocol, &lwip_socket_stream_p,
+ locals_dict, &lwip_socket_locals_dict
+ );
/******************************************************************************/
// Support functions for memory protection. lwIP has its own memory management
@@ -1769,6 +1789,7 @@ STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(0) },
{ MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) },
+ { MP_ROM_QSTR(MP_QSTR_IP_DROP_MEMBERSHIP), MP_ROM_INT(IP_DROP_MEMBERSHIP) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table);
@@ -1780,7 +1801,9 @@ const mp_obj_module_t mp_module_lwip = {
MP_REGISTER_MODULE(MP_QSTR_lwip, mp_module_lwip);
-// On LWIP-ports, this is the usocket module (replaces extmod/modusocket.c).
-MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_lwip);
+// On LWIP-ports, this is the socket module (replaces extmod/modsocket.c).
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_socket, mp_module_lwip);
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t lwip_slip_stream);
#endif // MICROPY_PY_LWIP
diff --git a/extmod/modnetwork.c b/extmod/modnetwork.c
index 87e155e091543..7c1b91de45d04 100644
--- a/extmod/modnetwork.c
+++ b/extmod/modnetwork.c
@@ -31,23 +31,35 @@
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/mphal.h"
+
+#if MICROPY_PY_NETWORK
+
#include "shared/netutils/netutils.h"
#include "modnetwork.h"
-#if MICROPY_PY_NETWORK
+#if MICROPY_PY_NETWORK_CYW43
+// So that CYW43_LINK_xxx constants are available to MICROPY_PORT_NETWORK_INTERFACES.
+#include "lib/cyw43-driver/src/cyw43.h"
+#endif
-#if MICROPY_PY_LWIP
-#include "lwip/netif.h"
-#include "lwip/timeouts.h"
-#include "lwip/dns.h"
-#include "lwip/dhcp.h"
-#include "lwip/apps/mdns.h"
+#ifdef MICROPY_PY_NETWORK_INCLUDEFILE
+#include MICROPY_PY_NETWORK_INCLUDEFILE
#endif
/// \module network - network configuration
///
/// This module provides network drivers and routing configuration.
+char mod_network_country_code[2] = "XX";
+
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#error "MICROPY_PY_NETWORK_HOSTNAME_DEFAULT must be set in mpconfigport.h or mpconfigboard.h"
+#endif
+
+char mod_network_hostname[MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN] = MICROPY_PY_NETWORK_HOSTNAME_DEFAULT;
+
+#ifdef MICROPY_PORT_NETWORK_INTERFACES
+
void mod_network_init(void) {
mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0);
}
@@ -71,7 +83,7 @@ mp_obj_t mod_network_find_nic(const uint8_t *ip) {
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);
+ // mod_network_nic_protocol_t *nic_protocol = (mod_network_nic_protocol_t *)MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(nic), protocol);
return nic;
}
@@ -83,16 +95,61 @@ STATIC mp_obj_t network_route(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route);
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t mod_network_nic_list);
+
+#endif // MICROPY_PORT_NETWORK_INTERFACES
+
+STATIC mp_obj_t network_country(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ return mp_obj_new_str(mod_network_country_code, 2);
+ } else {
+ size_t len;
+ const char *str = mp_obj_str_get_data(args[0], &len);
+ if (len != 2) {
+ mp_raise_ValueError(NULL);
+ }
+ mod_network_country_code[0] = str[0];
+ mod_network_country_code[1] = str[1];
+ return mp_const_none;
+ }
+}
+// TODO: Non-static to allow backwards-compatible pyb.country.
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj, 0, 1, network_country);
+
+STATIC mp_obj_t network_hostname(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ return mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
+ } else {
+ size_t len;
+ const char *str = mp_obj_str_get_data(args[0], &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
+ }
+ strcpy(mod_network_hostname, str);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_hostname_obj, 0, 1, network_hostname);
+
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_route), MP_ROM_PTR(&network_route_obj) },
+ { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) },
+ { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mod_network_hostname_obj) },
// Defined per port in mpconfigport.h
+ #ifdef MICROPY_PORT_NETWORK_INTERFACES
+ { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },
MICROPY_PORT_NETWORK_INTERFACES
+ #endif
+ // Allow a port to take mostly full control of the network module.
+ #ifdef MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE
+ #include MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE
+ #else
// Constants
{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(MOD_NETWORK_STA_IF) },
{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(MOD_NETWORK_AP_IF) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
@@ -104,58 +161,4 @@ const mp_obj_module_t mp_module_network = {
MP_REGISTER_MODULE(MP_QSTR_network, mp_module_network);
-/*******************************************************************************/
-// 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, MP_ERROR_TEXT("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/extmod/modnetwork.h b/extmod/modnetwork.h
index 3481cc6dcc575..4786596e9b93d 100644
--- a/extmod/modnetwork.h
+++ b/extmod/modnetwork.h
@@ -52,18 +52,24 @@
#define MOD_NETWORK_SS_CONNECTED (2)
#define MOD_NETWORK_SS_CLOSED (3)
+extern char mod_network_country_code[2];
+
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN
+#define MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN (16)
+#endif
+
+extern char mod_network_hostname[MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN];
+
#if MICROPY_PY_LWIP
struct netif;
void mod_network_lwip_init(void);
void mod_network_lwip_poll_wrapper(uint32_t ticks_ms);
mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args);
-#else
+#elif defined(MICROPY_PORT_NETWORK_INTERFACES)
struct _mod_network_socket_obj_t;
-typedef struct _mod_network_nic_type_t {
- mp_obj_type_t base;
-
+typedef struct _mod_network_nic_protocol_t {
// API for non-socket operations
int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out);
@@ -81,12 +87,12 @@ typedef struct _mod_network_nic_type_t {
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;
+} mod_network_nic_protocol_t;
typedef struct _mod_network_socket_obj_t {
mp_obj_base_t base;
mp_obj_t nic;
- mod_network_nic_type_t *nic_type;
+ mod_network_nic_protocol_t *nic_protocol;
uint32_t domain : 5;
uint32_t type : 5;
uint32_t proto : 5;
@@ -95,17 +101,19 @@ typedef struct _mod_network_socket_obj_t {
int32_t timeout;
mp_obj_t callback;
int32_t state : 8;
- #if MICROPY_PY_USOCKET_EXTENDED_STATE
+ #if MICROPY_PY_SOCKET_EXTENDED_STATE
// Extended socket state for NICs/ports that need it.
void *_private;
#endif
} mod_network_socket_obj_t;
-#endif // MICROPY_PY_LWIP
+#endif // MICROPY_PY_LWIP / MICROPY_PORT_NETWORK_INTERFACES
+#ifdef MICROPY_PORT_NETWORK_INTERFACES
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
#endif // MICROPY_INCLUDED_MODNETWORK_H
diff --git a/extmod/modos.c b/extmod/modos.c
new file mode 100644
index 0000000000000..6df49d7f84972
--- /dev/null
+++ b/extmod/modos.c
@@ -0,0 +1,200 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2022 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 "py/objstr.h"
+#include "py/runtime.h"
+
+#if MICROPY_PY_OS
+
+#include "extmod/misc.h"
+#include "extmod/vfs.h"
+
+#if MICROPY_VFS_FAT
+#include "extmod/vfs_fat.h"
+#if MICROPY_PY_OS_SYNC
+#include "lib/oofatfs/ff.h"
+#include "lib/oofatfs/diskio.h"
+#endif
+#endif
+
+#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2
+#include "extmod/vfs_lfs.h"
+#endif
+
+#if MICROPY_VFS_POSIX
+#include "extmod/vfs_posix.h"
+#endif
+
+#if MICROPY_PY_OS_UNAME
+#include "genhdr/mpversion.h"
+#endif
+
+#ifdef MICROPY_PY_OS_INCLUDEFILE
+#include MICROPY_PY_OS_INCLUDEFILE
+#endif
+
+#ifdef MICROPY_BUILD_TYPE
+#define MICROPY_BUILD_TYPE_PAREN " (" MICROPY_BUILD_TYPE ")"
+#else
+#define MICROPY_BUILD_TYPE_PAREN
+#endif
+
+#if MICROPY_PY_OS_SYNC
+// sync()
+// Sync all filesystems.
+STATIC mp_obj_t mp_os_sync(void) {
+ #if MICROPY_VFS_FAT
+ for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
+ // this assumes that vfs->obj is fs_user_mount_t with block device functions
+ disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL);
+ }
+ #endif
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_0(mp_os_sync_obj, mp_os_sync);
+#endif
+
+#if MICROPY_PY_OS_UNAME
+
+#if MICROPY_PY_OS_UNAME_RELEASE_DYNAMIC
+#define CONST_RELEASE
+#else
+#define CONST_RELEASE const
+#endif
+
+STATIC const qstr mp_os_uname_info_fields[] = {
+ MP_QSTR_sysname,
+ MP_QSTR_nodename,
+ MP_QSTR_release,
+ MP_QSTR_version,
+ MP_QSTR_machine
+};
+STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
+STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
+STATIC CONST_RELEASE MP_DEFINE_STR_OBJ(mp_os_uname_info_release_obj, MICROPY_VERSION_STRING);
+STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN);
+STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
+
+STATIC MP_DEFINE_ATTRTUPLE(
+ mp_os_uname_info_obj,
+ mp_os_uname_info_fields,
+ 5,
+ MP_ROM_PTR(&mp_os_uname_info_sysname_obj),
+ MP_ROM_PTR(&mp_os_uname_info_nodename_obj),
+ MP_ROM_PTR(&mp_os_uname_info_release_obj),
+ MP_ROM_PTR(&mp_os_uname_info_version_obj),
+ MP_ROM_PTR(&mp_os_uname_info_machine_obj)
+ );
+
+STATIC mp_obj_t mp_os_uname(void) {
+ #if MICROPY_PY_OS_UNAME_RELEASE_DYNAMIC
+ const char *release = mp_os_uname_release();
+ mp_os_uname_info_release_obj.len = strlen(release);
+ mp_os_uname_info_release_obj.data = (const byte *)release;
+ #endif
+ return MP_OBJ_FROM_PTR(&mp_os_uname_info_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_os_uname_obj, mp_os_uname);
+
+#endif
+
+STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) },
+
+ #if MICROPY_PY_OS_GETENV_PUTENV_UNSETENV
+ { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mp_os_getenv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_os_putenv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_os_unsetenv_obj) },
+ #endif
+ #if MICROPY_PY_OS_SEP
+ { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
+ #endif
+ #if MICROPY_PY_OS_SYNC
+ { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_os_sync_obj) },
+ #endif
+ #if MICROPY_PY_OS_SYSTEM
+ { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mp_os_system_obj) },
+ #endif
+ #if MICROPY_PY_OS_UNAME
+ { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&mp_os_uname_obj) },
+ #endif
+ #if MICROPY_PY_OS_URANDOM
+ { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_os_urandom_obj) },
+ #endif
+
+ #if MICROPY_VFS
+ { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
+ { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove
+ #endif
+
+ // The following are MicroPython extensions.
+
+ #if MICROPY_PY_OS_DUPTERM
+ { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_os_dupterm_obj) },
+ #endif
+ #if MICROPY_PY_OS_DUPTERM_NOTIFY
+ { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&mp_os_dupterm_notify_obj) },
+ #endif
+ #if MICROPY_PY_OS_ERRNO
+ { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_os_errno_obj) },
+ #endif
+
+ #if MICROPY_VFS
+ { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
+ { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
+ #if MICROPY_VFS_FAT
+ { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
+ #endif
+ #if MICROPY_VFS_LFS1
+ { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) },
+ #endif
+ #if MICROPY_VFS_LFS2
+ { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) },
+ #endif
+ #if MICROPY_VFS_POSIX
+ { MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) },
+ #endif
+ #endif
+};
+STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
+
+const mp_obj_module_t mp_module_os = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&os_module_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_os, mp_module_os);
+
+#endif // MICROPY_PY_OS
diff --git a/extmod/modplatform.c b/extmod/modplatform.c
new file mode 100644
index 0000000000000..73846f946d0ed
--- /dev/null
+++ b/extmod/modplatform.c
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2021 Ibrahim Abdelkader
+ *
+ * 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/objtuple.h"
+#include "py/objstr.h"
+#include "py/mphal.h"
+#include "extmod/modplatform.h"
+#include "genhdr/mpversion.h"
+
+#if MICROPY_PY_PLATFORM
+
+// platform - Access to underlying platform's identifying data
+
+STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, MICROPY_PLATFORM_SYSTEM "-" \
+ MICROPY_VERSION_STRING "-" MICROPY_PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" \
+ MICROPY_PLATFORM_LIBC_LIB "" MICROPY_PLATFORM_LIBC_VER);
+STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, MICROPY_PLATFORM_COMPILER);
+STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, MICROPY_PLATFORM_LIBC_LIB);
+STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, MICROPY_PLATFORM_LIBC_VER);
+STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = {
+ {&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)}
+};
+
+STATIC mp_obj_t platform_platform(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ return MP_OBJ_FROM_PTR(&info_platform_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_platform_obj, 0, platform_platform);
+
+STATIC mp_obj_t platform_python_compiler(void) {
+ return MP_OBJ_FROM_PTR(&info_python_compiler_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(platform_python_compiler_obj, platform_python_compiler);
+
+STATIC mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ return MP_OBJ_FROM_PTR(&info_libc_tuple_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver);
+
+STATIC const mp_rom_map_elem_t modplatform_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_platform) },
+ { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_platform_obj) },
+ { MP_ROM_QSTR(MP_QSTR_python_compiler), MP_ROM_PTR(&platform_python_compiler_obj) },
+ { MP_ROM_QSTR(MP_QSTR_libc_ver), MP_ROM_PTR(&platform_libc_ver_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table);
+
+const mp_obj_module_t mp_module_platform = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&modplatform_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_platform, mp_module_platform);
+
+#endif // MICROPY_PY_PLATFORM
diff --git a/extmod/modplatform.h b/extmod/modplatform.h
new file mode 100644
index 0000000000000..56a50e53c5445
--- /dev/null
+++ b/extmod/modplatform.h
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2021 Ibrahim Abdelkader
+ *
+ * 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_MODPLATFORM_H
+#define MICROPY_INCLUDED_MODPLATFORM_H
+
+#include "py/misc.h" // For MP_STRINGIFY.
+#include "py/mpconfig.h"
+
+// Preprocessor directives identifying the platform.
+// The platform module itself is guarded by MICROPY_PY_PLATFORM, see the
+// .c file, but these are made available because they're generally usable.
+// TODO: Add more architectures, compilers and libraries.
+// See: https://sourceforge.net/p/predef/wiki/Home/
+
+#if defined(__ARM_ARCH)
+#define MICROPY_PLATFORM_ARCH "arm"
+#elif defined(__x86_64__) || defined(_M_X64)
+#define MICROPY_PLATFORM_ARCH "x86_64"
+#elif defined(__i386__) || defined(_M_IX86)
+#define MICROPY_PLATFORM_ARCH "x86"
+#elif defined(__xtensa__)
+#define MICROPY_PLATFORM_ARCH "xtensa"
+#elif defined(__riscv)
+#define MICROPY_PLATFORM_ARCH "riscv"
+#else
+#define MICROPY_PLATFORM_ARCH ""
+#endif
+
+#if defined(__GNUC__)
+#define MICROPY_PLATFORM_COMPILER \
+ "GCC " \
+ MP_STRINGIFY(__GNUC__) "." \
+ MP_STRINGIFY(__GNUC_MINOR__) "." \
+ MP_STRINGIFY(__GNUC_PATCHLEVEL__)
+#elif defined(__ARMCC_VERSION)
+#define MICROPY_PLATFORM_COMPILER \
+ "ARMCC " \
+ MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
+ MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
+ MP_STRINGIFY((__ARMCC_VERSION % 10000))
+#elif defined(_MSC_VER)
+#if defined(_WIN64)
+#define MICROPY_PLATFORM_COMPILER_BITS "64 bit"
+#elif defined(_M_IX86)
+#define MICROPY_PLATFORM_COMPILER_BITS "32 bit"
+#else
+#define MICROPY_PLATFORM_COMPILER_BITS ""
+#endif
+#define MICROPY_PLATFORM_COMPILER \
+ "MSC v." MP_STRINGIFY(_MSC_VER) " " MICROPY_PLATFORM_COMPILER_BITS
+#else
+#define MICROPY_PLATFORM_COMPILER ""
+#endif
+
+#if defined(__GLIBC__)
+#define MICROPY_PLATFORM_LIBC_LIB "glibc"
+#define MICROPY_PLATFORM_LIBC_VER \
+ MP_STRINGIFY(__GLIBC__) "." \
+ MP_STRINGIFY(__GLIBC_MINOR__)
+#elif defined(__NEWLIB__)
+#define MICROPY_PLATFORM_LIBC_LIB "newlib"
+#define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION
+#else
+#define MICROPY_PLATFORM_LIBC_LIB ""
+#define MICROPY_PLATFORM_LIBC_VER ""
+#endif
+
+#if defined(__linux)
+#define MICROPY_PLATFORM_SYSTEM "Linux"
+#elif defined(__unix__)
+#define MICROPY_PLATFORM_SYSTEM "Unix"
+#elif defined(__CYGWIN__)
+#define MICROPY_PLATFORM_SYSTEM "Cygwin"
+#elif defined(_WIN32)
+#define MICROPY_PLATFORM_SYSTEM "Windows"
+#else
+#define MICROPY_PLATFORM_SYSTEM "MicroPython"
+#endif
+
+#ifndef MICROPY_PLATFORM_VERSION
+#define MICROPY_PLATFORM_VERSION ""
+#endif
+
+#endif // MICROPY_INCLUDED_MODPLATFORM_H
diff --git a/extmod/modrandom.c b/extmod/modrandom.c
new file mode 100644
index 0000000000000..e65f31488bfeb
--- /dev/null
+++ b/extmod/modrandom.c
@@ -0,0 +1,261 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/runtime.h"
+
+#if MICROPY_PY_RANDOM
+
+// Work out if the seed will be set on import or not.
+#if MICROPY_MODULE_BUILTIN_INIT && defined(MICROPY_PY_RANDOM_SEED_INIT_FUNC)
+#define SEED_ON_IMPORT (1)
+#else
+#define SEED_ON_IMPORT (0)
+#endif
+
+// Yasmarang random number generator
+// by Ilya Levin
+// http://www.literatecode.com/yasmarang
+// Public Domain
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+#if SEED_ON_IMPORT
+// If the state is seeded on import then keep these variables in the BSS.
+STATIC uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
+STATIC uint8_t yasmarang_dat;
+#else
+// Without seed-on-import these variables must be initialised via the data section.
+STATIC uint32_t yasmarang_pad = 0xeda4baba, yasmarang_n = 69, yasmarang_d = 233;
+STATIC uint8_t yasmarang_dat = 0;
+#endif
+#endif
+
+STATIC uint32_t yasmarang(void) {
+ yasmarang_pad += yasmarang_dat + yasmarang_d * yasmarang_n;
+ yasmarang_pad = (yasmarang_pad << 3) + (yasmarang_pad >> 29);
+ yasmarang_n = yasmarang_pad | 2;
+ yasmarang_d ^= (yasmarang_pad << 31) + (yasmarang_pad >> 1);
+ yasmarang_dat ^= (char)yasmarang_pad ^ (yasmarang_d >> 8) ^ 1;
+
+ return yasmarang_pad ^ (yasmarang_d << 5) ^ (yasmarang_pad >> 18) ^ (yasmarang_dat << 1);
+} /* yasmarang */
+
+// End of Yasmarang
+
+#if MICROPY_PY_RANDOM_EXTRA_FUNCS
+
+// returns an unsigned integer below the given argument
+// n must not be zero
+STATIC uint32_t yasmarang_randbelow(uint32_t n) {
+ uint32_t mask = 1;
+ while ((n & mask) < n) {
+ mask = (mask << 1) | 1;
+ }
+ uint32_t r;
+ do {
+ r = yasmarang() & mask;
+ } while (r >= n);
+ return r;
+}
+
+#endif
+
+STATIC mp_obj_t mod_random_getrandbits(mp_obj_t num_in) {
+ int n = mp_obj_get_int(num_in);
+ if (n > 32 || n < 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("bits must be 32 or less"));
+ }
+ if (n == 0) {
+ return MP_OBJ_NEW_SMALL_INT(0);
+ }
+ uint32_t mask = ~0;
+ // Beware of C undefined behavior when shifting by >= than bit size
+ mask >>= (32 - n);
+ return mp_obj_new_int_from_uint(yasmarang() & mask);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_getrandbits_obj, mod_random_getrandbits);
+
+STATIC mp_obj_t mod_random_seed(size_t n_args, const mp_obj_t *args) {
+ mp_uint_t seed;
+ if (n_args == 0 || args[0] == mp_const_none) {
+ #ifdef MICROPY_PY_RANDOM_SEED_INIT_FUNC
+ seed = MICROPY_PY_RANDOM_SEED_INIT_FUNC;
+ #else
+ mp_raise_ValueError(MP_ERROR_TEXT("no default seed"));
+ #endif
+ } else {
+ seed = mp_obj_get_int_truncated(args[0]);
+ }
+ yasmarang_pad = seed;
+ yasmarang_n = 69;
+ yasmarang_d = 233;
+ yasmarang_dat = 0;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_seed_obj, 0, 1, mod_random_seed);
+
+#if MICROPY_PY_RANDOM_EXTRA_FUNCS
+
+STATIC mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) {
+ mp_int_t start = mp_obj_get_int(args[0]);
+ if (n_args == 1) {
+ // range(stop)
+ if (start > 0) {
+ return mp_obj_new_int(yasmarang_randbelow(start));
+ } else {
+ goto error;
+ }
+ } else {
+ mp_int_t stop = mp_obj_get_int(args[1]);
+ if (n_args == 2) {
+ // range(start, stop)
+ if (start < stop) {
+ return mp_obj_new_int(start + yasmarang_randbelow(stop - start));
+ } else {
+ goto error;
+ }
+ } else {
+ // range(start, stop, step)
+ mp_int_t step = mp_obj_get_int(args[2]);
+ mp_int_t n;
+ if (step > 0) {
+ n = (stop - start + step - 1) / step;
+ } else if (step < 0) {
+ n = (stop - start + step + 1) / step;
+ } else {
+ goto error;
+ }
+ if (n > 0) {
+ return mp_obj_new_int(start + step * yasmarang_randbelow(n));
+ } else {
+ goto error;
+ }
+ }
+ }
+
+error:
+ mp_raise_ValueError(NULL);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_randrange_obj, 1, 3, mod_random_randrange);
+
+STATIC mp_obj_t mod_random_randint(mp_obj_t a_in, mp_obj_t b_in) {
+ mp_int_t a = mp_obj_get_int(a_in);
+ mp_int_t b = mp_obj_get_int(b_in);
+ if (a <= b) {
+ return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1));
+ } else {
+ mp_raise_ValueError(NULL);
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_randint_obj, mod_random_randint);
+
+STATIC mp_obj_t mod_random_choice(mp_obj_t seq) {
+ mp_int_t len = mp_obj_get_int(mp_obj_len(seq));
+ if (len > 0) {
+ return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL);
+ } else {
+ mp_raise_type(&mp_type_IndexError);
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_choice_obj, mod_random_choice);
+
+#if MICROPY_PY_BUILTINS_FLOAT
+
+// returns a number in the range [0..1) using Yasmarang to fill in the fraction bits
+STATIC mp_float_t yasmarang_float(void) {
+ mp_float_union_t u;
+ u.p.sgn = 0;
+ u.p.exp = (1 << (MP_FLOAT_EXP_BITS - 1)) - 1;
+ if (MP_FLOAT_FRAC_BITS <= 32) {
+ u.p.frc = yasmarang();
+ } else {
+ u.p.frc = ((uint64_t)yasmarang() << 32) | (uint64_t)yasmarang();
+ }
+ return u.f - 1;
+}
+
+STATIC mp_obj_t mod_random_random(void) {
+ return mp_obj_new_float(yasmarang_float());
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_random_random_obj, mod_random_random);
+
+STATIC mp_obj_t mod_random_uniform(mp_obj_t a_in, mp_obj_t b_in) {
+ mp_float_t a = mp_obj_get_float(a_in);
+ mp_float_t b = mp_obj_get_float(b_in);
+ return mp_obj_new_float(a + (b - a) * yasmarang_float());
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_uniform_obj, mod_random_uniform);
+
+#endif
+
+#endif // MICROPY_PY_RANDOM_EXTRA_FUNCS
+
+#if SEED_ON_IMPORT
+STATIC mp_obj_t mod_random___init__(void) {
+ // This module may be imported by more than one name so need to ensure
+ // that it's only ever seeded once.
+ static bool seeded = false;
+ if (!seeded) {
+ seeded = true;
+ mod_random_seed(0, NULL);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_random___init___obj, mod_random___init__);
+#endif
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_rom_map_elem_t mp_module_random_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_random) },
+ #if SEED_ON_IMPORT
+ { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&mod_random___init___obj) },
+ #endif
+ { MP_ROM_QSTR(MP_QSTR_getrandbits), MP_ROM_PTR(&mod_random_getrandbits_obj) },
+ { MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_random_seed_obj) },
+ #if MICROPY_PY_RANDOM_EXTRA_FUNCS
+ { MP_ROM_QSTR(MP_QSTR_randrange), MP_ROM_PTR(&mod_random_randrange_obj) },
+ { MP_ROM_QSTR(MP_QSTR_randint), MP_ROM_PTR(&mod_random_randint_obj) },
+ { MP_ROM_QSTR(MP_QSTR_choice), MP_ROM_PTR(&mod_random_choice_obj) },
+ #if MICROPY_PY_BUILTINS_FLOAT
+ { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_random_random_obj) },
+ { MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&mod_random_uniform_obj) },
+ #endif
+ #endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_random_globals, mp_module_random_globals_table);
+
+const mp_obj_module_t mp_module_random = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_random_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_random, mp_module_random);
+#endif
+
+#endif // MICROPY_PY_RANDOM
diff --git a/extmod/modre.c b/extmod/modre.c
new file mode 100644
index 0000000000000..7f00b1c23c4ae
--- /dev/null
+++ b/extmod/modre.c
@@ -0,0 +1,492 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ *
+ * 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/runtime.h"
+#include "py/binary.h"
+#include "py/objstr.h"
+#include "py/stackctrl.h"
+
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+#include "py/unicode.h"
+#endif
+
+#if MICROPY_PY_RE
+
+#define re1_5_stack_chk() MP_STACK_CHECK()
+
+#include "lib/re1.5/re1.5.h"
+
+#define FLAG_DEBUG 0x1000
+
+typedef struct _mp_obj_re_t {
+ mp_obj_base_t base;
+ ByteProg re;
+} mp_obj_re_t;
+
+typedef struct _mp_obj_match_t {
+ mp_obj_base_t base;
+ int num_matches;
+ mp_obj_t str;
+ const char *caps[0];
+} mp_obj_match_t;
+
+STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args);
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_obj_type_t re_type;
+#endif
+
+STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ (void)kind;
+ mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_printf(print, "", self->num_matches);
+}
+
+STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) {
+ mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_int_t no = mp_obj_get_int(no_in);
+ if (no < 0 || no >= self->num_matches) {
+ mp_raise_type_arg(&mp_type_IndexError, no_in);
+ }
+
+ const char *start = self->caps[no * 2];
+ if (start == NULL) {
+ // no match for this group
+ return mp_const_none;
+ }
+ return mp_obj_new_str_of_type(mp_obj_get_type(self->str),
+ (const byte *)start, self->caps[no * 2 + 1] - start);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(match_group_obj, match_group);
+
+#if MICROPY_PY_RE_MATCH_GROUPS
+
+STATIC mp_obj_t match_groups(mp_obj_t self_in) {
+ mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->num_matches <= 1) {
+ return mp_const_empty_tuple;
+ }
+ mp_obj_tuple_t *groups = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->num_matches - 1, NULL));
+ for (int i = 1; i < self->num_matches; ++i) {
+ groups->items[i - 1] = match_group(self_in, MP_OBJ_NEW_SMALL_INT(i));
+ }
+ return MP_OBJ_FROM_PTR(groups);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(match_groups_obj, match_groups);
+
+#endif
+
+#if MICROPY_PY_RE_MATCH_SPAN_START_END
+
+STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span[2]) {
+ mp_obj_match_t *self = MP_OBJ_TO_PTR(args[0]);
+
+ mp_int_t no = 0;
+ if (n_args == 2) {
+ no = mp_obj_get_int(args[1]);
+ if (no < 0 || no >= self->num_matches) {
+ mp_raise_type_arg(&mp_type_IndexError, args[1]);
+ }
+ }
+
+ mp_int_t s = -1;
+ mp_int_t e = -1;
+ const char *start = self->caps[no * 2];
+ if (start != NULL) {
+ // have a match for this group
+ const char *begin = mp_obj_str_get_str(self->str);
+ s = start - begin;
+ e = self->caps[no * 2 + 1] - begin;
+ }
+
+ #if MICROPY_PY_BUILTINS_STR_UNICODE
+ if (mp_obj_get_type(self->str) == &mp_type_str) {
+ const byte *begin = (const byte *)mp_obj_str_get_str(self->str);
+ if (s != -1) {
+ s = utf8_ptr_to_index(begin, begin + s);
+ }
+ if (e != -1) {
+ e = utf8_ptr_to_index(begin, begin + e);
+ }
+ }
+ #endif
+
+ span[0] = mp_obj_new_int(s);
+ span[1] = mp_obj_new_int(e);
+}
+
+STATIC mp_obj_t match_span(size_t n_args, const mp_obj_t *args) {
+ mp_obj_t span[2];
+ match_span_helper(n_args, args, span);
+ return mp_obj_new_tuple(2, span);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_span_obj, 1, 2, match_span);
+
+STATIC mp_obj_t match_start(size_t n_args, const mp_obj_t *args) {
+ mp_obj_t span[2];
+ match_span_helper(n_args, args, span);
+ return span[0];
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_start_obj, 1, 2, match_start);
+
+STATIC mp_obj_t match_end(size_t n_args, const mp_obj_t *args) {
+ mp_obj_t span[2];
+ match_span_helper(n_args, args, span);
+ return span[1];
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_end_obj, 1, 2, match_end);
+
+#endif
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_rom_map_elem_t match_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_group), MP_ROM_PTR(&match_group_obj) },
+ #if MICROPY_PY_RE_MATCH_GROUPS
+ { MP_ROM_QSTR(MP_QSTR_groups), MP_ROM_PTR(&match_groups_obj) },
+ #endif
+ #if MICROPY_PY_RE_MATCH_SPAN_START_END
+ { MP_ROM_QSTR(MP_QSTR_span), MP_ROM_PTR(&match_span_obj) },
+ { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&match_start_obj) },
+ { MP_ROM_QSTR(MP_QSTR_end), MP_ROM_PTR(&match_end_obj) },
+ #endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ match_type,
+ MP_QSTR_match,
+ MP_TYPE_FLAG_NONE,
+ print, match_print,
+ locals_dict, &match_locals_dict
+ );
+#endif
+
+STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ (void)kind;
+ mp_obj_re_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_printf(print, "", self);
+}
+
+STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
+ (void)n_args;
+ mp_obj_re_t *self;
+ if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) {
+ self = MP_OBJ_TO_PTR(args[0]);
+ } else {
+ self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
+ }
+ Subject subj;
+ size_t len;
+ subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
+ subj.end = subj.begin + len;
+ int caps_num = (self->re.sub + 1) * 2;
+ mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char *, caps_num);
+ // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
+ memset((char *)match->caps, 0, caps_num * sizeof(char *));
+ int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, is_anchored);
+ if (res == 0) {
+ m_del_var(mp_obj_match_t, char *, caps_num, match);
+ return mp_const_none;
+ }
+
+ match->base.type = (mp_obj_type_t *)&match_type;
+ match->num_matches = caps_num / 2; // caps_num counts start and end pointers
+ match->str = args[1];
+ return MP_OBJ_FROM_PTR(match);
+}
+
+STATIC mp_obj_t re_match(size_t n_args, const mp_obj_t *args) {
+ return re_exec(true, n_args, args);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match);
+
+STATIC mp_obj_t re_search(size_t n_args, const mp_obj_t *args) {
+ return re_exec(false, n_args, args);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);
+
+STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
+ mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
+ Subject subj;
+ size_t len;
+ const mp_obj_type_t *str_type = mp_obj_get_type(args[1]);
+ subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
+ subj.end = subj.begin + len;
+ int caps_num = (self->re.sub + 1) * 2;
+
+ int maxsplit = 0;
+ if (n_args > 2) {
+ maxsplit = mp_obj_get_int(args[2]);
+ }
+
+ mp_obj_t retval = mp_obj_new_list(0, NULL);
+ const char **caps = mp_local_alloc(caps_num * sizeof(char *));
+ while (true) {
+ // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
+ memset((char **)caps, 0, caps_num * sizeof(char *));
+ int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false);
+
+ // if we didn't have a match, or had an empty match, it's time to stop
+ if (!res || caps[0] == caps[1]) {
+ break;
+ }
+
+ mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte *)subj.begin, caps[0] - subj.begin);
+ mp_obj_list_append(retval, s);
+ if (self->re.sub > 0) {
+ mp_raise_NotImplementedError(MP_ERROR_TEXT("splitting with sub-captures"));
+ }
+ subj.begin = caps[1];
+ if (maxsplit > 0 && --maxsplit == 0) {
+ break;
+ }
+ }
+ // cast is a workaround for a bug in msvc (see above)
+ mp_local_free((char **)caps);
+
+ mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte *)subj.begin, subj.end - subj.begin);
+ mp_obj_list_append(retval, s);
+ return retval;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split);
+
+#if MICROPY_PY_RE_SUB
+
+STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
+ mp_obj_re_t *self;
+ if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) {
+ self = MP_OBJ_TO_PTR(args[0]);
+ } else {
+ self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
+ }
+ mp_obj_t replace = args[1];
+ mp_obj_t where = args[2];
+ mp_int_t count = 0;
+ if (n_args > 3) {
+ count = mp_obj_get_int(args[3]);
+ // Note: flags are currently ignored
+ }
+
+ size_t where_len;
+ const char *where_str = mp_obj_str_get_data(where, &where_len);
+ Subject subj;
+ subj.begin_line = subj.begin = where_str;
+ subj.end = subj.begin + where_len;
+ int caps_num = (self->re.sub + 1) * 2;
+
+ vstr_t vstr_return;
+ vstr_return.buf = NULL; // We'll init the vstr after the first match
+ mp_obj_match_t *match = mp_local_alloc(sizeof(mp_obj_match_t) + caps_num * sizeof(char *));
+ match->base.type = (mp_obj_type_t *)&match_type;
+ match->num_matches = caps_num / 2; // caps_num counts start and end pointers
+ match->str = where;
+
+ for (;;) {
+ // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
+ memset((char *)match->caps, 0, caps_num * sizeof(char *));
+ int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, false);
+
+ // If we didn't have a match, or had an empty match, it's time to stop
+ if (!res || match->caps[0] == match->caps[1]) {
+ break;
+ }
+
+ // Initialise the vstr if it's not already
+ if (vstr_return.buf == NULL) {
+ vstr_init(&vstr_return, match->caps[0] - subj.begin);
+ }
+
+ // Add pre-match string
+ vstr_add_strn(&vstr_return, subj.begin, match->caps[0] - subj.begin);
+
+ // Get replacement string
+ const char *repl = mp_obj_str_get_str((mp_obj_is_callable(replace) ? mp_call_function_1(replace, MP_OBJ_FROM_PTR(match)) : replace));
+
+ // Append replacement string to result, substituting any regex groups
+ while (*repl != '\0') {
+ if (*repl == '\\') {
+ ++repl;
+ bool is_g_format = false;
+ if (*repl == 'g' && repl[1] == '<') {
+ // Group specified with syntax "\g"
+ repl += 2;
+ is_g_format = true;
+ }
+
+ if ('0' <= *repl && *repl <= '9') {
+ // Group specified with syntax "\g" or "\number"
+ unsigned int match_no = 0;
+ do {
+ match_no = match_no * 10 + (*repl++ - '0');
+ } while ('0' <= *repl && *repl <= '9');
+ if (is_g_format && *repl == '>') {
+ ++repl;
+ }
+
+ if (match_no >= (unsigned int)match->num_matches) {
+ mp_raise_type_arg(&mp_type_IndexError, MP_OBJ_NEW_SMALL_INT(match_no));
+ }
+
+ const char *start_match = match->caps[match_no * 2];
+ if (start_match != NULL) {
+ // Add the substring matched by group
+ const char *end_match = match->caps[match_no * 2 + 1];
+ vstr_add_strn(&vstr_return, start_match, end_match - start_match);
+ }
+ } else if (*repl == '\\') {
+ // Add the \ character
+ vstr_add_byte(&vstr_return, *repl++);
+ }
+ } else {
+ // Just add the current byte from the replacement string
+ vstr_add_byte(&vstr_return, *repl++);
+ }
+ }
+
+ // Move start pointer to end of last match
+ subj.begin = match->caps[1];
+
+ // Stop substitutions if count was given and gets to 0
+ if (count > 0 && --count == 0) {
+ break;
+ }
+ }
+
+ mp_local_free(match);
+
+ if (vstr_return.buf == NULL) {
+ // Optimisation for case of no substitutions
+ return where;
+ }
+
+ // Add post-match string
+ vstr_add_strn(&vstr_return, subj.begin, subj.end - subj.begin);
+
+ if (mp_obj_get_type(where) == &mp_type_str) {
+ return mp_obj_new_str_from_utf8_vstr(&vstr_return);
+ } else {
+ return mp_obj_new_bytes_from_vstr(&vstr_return);
+ }
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub_helper);
+
+#endif
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_rom_map_elem_t re_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
+ { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
+ { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&re_split_obj) },
+ #if MICROPY_PY_RE_SUB
+ { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) },
+ #endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ re_type,
+ MP_QSTR_re,
+ MP_TYPE_FLAG_NONE,
+ print, re_print,
+ locals_dict, &re_locals_dict
+ );
+#endif
+
+STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ const char *re_str = mp_obj_str_get_str(args[0]);
+ int size = re1_5_sizecode(re_str);
+ if (size == -1) {
+ goto error;
+ }
+ mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, (mp_obj_type_t *)&re_type);
+ #if MICROPY_PY_RE_DEBUG
+ int flags = 0;
+ if (n_args > 1) {
+ flags = mp_obj_get_int(args[1]);
+ }
+ #endif
+ int error = re1_5_compilecode(&o->re, re_str);
+ if (error != 0) {
+ error:
+ mp_raise_ValueError(MP_ERROR_TEXT("error in regex"));
+ }
+ #if MICROPY_PY_RE_DEBUG
+ if (flags & FLAG_DEBUG) {
+ re1_5_dumpcode(&o->re);
+ }
+ #endif
+ return MP_OBJ_FROM_PTR(o);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile);
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_re) },
+ { MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) },
+ { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
+ { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
+ #if MICROPY_PY_RE_SUB
+ { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) },
+ #endif
+ #if MICROPY_PY_RE_DEBUG
+ { MP_ROM_QSTR(MP_QSTR_DEBUG), MP_ROM_INT(FLAG_DEBUG) },
+ #endif
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table);
+
+const mp_obj_module_t mp_module_re = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_re_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_re, mp_module_re);
+#endif
+
+// Source files #include'd here to make sure they're compiled in
+// only if module is enabled by config setting.
+
+#define re1_5_fatal(x) assert(!x)
+
+#include "lib/re1.5/compilecode.c"
+#include "lib/re1.5/recursiveloop.c"
+#include "lib/re1.5/charclass.c"
+
+#if MICROPY_PY_RE_DEBUG
+// Make sure the output print statements go to the same output as other Python output.
+#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
+#include "lib/re1.5/dumpcode.c"
+#undef printf
+#endif
+
+#endif // MICROPY_PY_RE
diff --git a/extmod/modselect.c b/extmod/modselect.c
new file mode 100644
index 0000000000000..3d7ccbd99558b
--- /dev/null
+++ b/extmod/modselect.c
@@ -0,0 +1,378 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ * Copyright (c) 2015-2017 Paul Sokolovsky
+ *
+ * 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_SELECT
+
+#include
+
+#include "py/runtime.h"
+#include "py/obj.h"
+#include "py/objlist.h"
+#include "py/stream.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+
+// Flags for poll()
+#define FLAG_ONESHOT (1)
+
+typedef struct _poll_obj_t {
+ mp_obj_t obj;
+ mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
+ mp_uint_t flags;
+ mp_uint_t flags_ret;
+} poll_obj_t;
+
+STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) {
+ for (mp_uint_t i = 0; i < obj_len; i++) {
+ mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
+ if (elem->value == MP_OBJ_NULL) {
+ // object not found; get its ioctl and add it to the poll list
+ const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL);
+ poll_obj_t *poll_obj = m_new_obj(poll_obj_t);
+ poll_obj->obj = obj[i];
+ poll_obj->ioctl = stream_p->ioctl;
+ poll_obj->flags = flags;
+ poll_obj->flags_ret = 0;
+ elem->value = MP_OBJ_FROM_PTR(poll_obj);
+ } else {
+ // object exists; update its flags
+ if (or_flags) {
+ ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags |= flags;
+ } else {
+ ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = flags;
+ }
+ }
+ }
+}
+
+// poll each object in the map
+STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) {
+ mp_uint_t n_ready = 0;
+ for (mp_uint_t i = 0; i < poll_map->alloc; ++i) {
+ if (!mp_map_slot_is_filled(poll_map, i)) {
+ continue;
+ }
+
+ poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map->table[i].value);
+ int errcode;
+ mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode);
+ poll_obj->flags_ret = ret;
+
+ if (ret == -1) {
+ // error doing ioctl
+ mp_raise_OSError(errcode);
+ }
+
+ if (ret != 0) {
+ // object is ready
+ n_ready += 1;
+ if (rwx_num != NULL) {
+ if (ret & MP_STREAM_POLL_RD) {
+ rwx_num[0] += 1;
+ }
+ if (ret & MP_STREAM_POLL_WR) {
+ rwx_num[1] += 1;
+ }
+ if ((ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
+ rwx_num[2] += 1;
+ }
+ }
+ }
+ }
+ return n_ready;
+}
+
+#if MICROPY_PY_SELECT_SELECT
+// select(rlist, wlist, xlist[, timeout])
+STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
+ // get array data from tuple/list arguments
+ size_t rwx_len[3];
+ mp_obj_t *r_array, *w_array, *x_array;
+ mp_obj_get_array(args[0], &rwx_len[0], &r_array);
+ mp_obj_get_array(args[1], &rwx_len[1], &w_array);
+ mp_obj_get_array(args[2], &rwx_len[2], &x_array);
+
+ // get timeout
+ mp_uint_t timeout = -1;
+ if (n_args == 4) {
+ if (args[3] != mp_const_none) {
+ #if MICROPY_PY_BUILTINS_FLOAT
+ float timeout_f = mp_obj_get_float_to_f(args[3]);
+ if (timeout_f >= 0) {
+ timeout = (mp_uint_t)(timeout_f * 1000);
+ }
+ #else
+ timeout = mp_obj_get_int(args[3]) * 1000;
+ #endif
+ }
+ }
+
+ // merge separate lists and get the ioctl function for each object
+ mp_map_t poll_map;
+ mp_map_init(&poll_map, rwx_len[0] + rwx_len[1] + rwx_len[2]);
+ poll_map_add(&poll_map, r_array, rwx_len[0], MP_STREAM_POLL_RD, true);
+ poll_map_add(&poll_map, w_array, rwx_len[1], MP_STREAM_POLL_WR, true);
+ poll_map_add(&poll_map, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true);
+
+ mp_uint_t start_tick = mp_hal_ticks_ms();
+ rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
+ for (;;) {
+ // poll the objects
+ mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len);
+
+ if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
+ // one or more objects are ready, or we had a timeout
+ mp_obj_t list_array[3];
+ list_array[0] = mp_obj_new_list(rwx_len[0], NULL);
+ list_array[1] = mp_obj_new_list(rwx_len[1], NULL);
+ list_array[2] = mp_obj_new_list(rwx_len[2], NULL);
+ rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
+ for (mp_uint_t i = 0; i < poll_map.alloc; ++i) {
+ if (!mp_map_slot_is_filled(&poll_map, i)) {
+ continue;
+ }
+ poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value);
+ if (poll_obj->flags_ret & MP_STREAM_POLL_RD) {
+ ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
+ }
+ if (poll_obj->flags_ret & MP_STREAM_POLL_WR) {
+ ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
+ }
+ if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
+ ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
+ }
+ }
+ mp_map_deinit(&poll_map);
+ return mp_obj_new_tuple(3, list_array);
+ }
+ MICROPY_EVENT_POLL_HOOK
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select);
+#endif // MICROPY_PY_SELECT_SELECT
+
+typedef struct _mp_obj_poll_t {
+ mp_obj_base_t base;
+ mp_map_t poll_map;
+ short iter_cnt;
+ short iter_idx;
+ int flags;
+ // callee-owned tuple
+ mp_obj_t ret_tuple;
+} mp_obj_poll_t;
+
+// register(obj[, eventmask])
+STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_uint_t flags;
+ if (n_args == 3) {
+ flags = mp_obj_get_int(args[2]);
+ } else {
+ flags = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR;
+ }
+ poll_map_add(&self->poll_map, &args[1], 1, flags, false);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
+
+// unregister(obj)
+STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
+ // TODO raise KeyError if obj didn't exist in map
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
+
+// modify(obj, eventmask)
+STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
+ if (elem == NULL) {
+ mp_raise_OSError(MP_ENOENT);
+ }
+ ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
+
+STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
+
+ // work out timeout (its given already in ms)
+ mp_uint_t timeout = -1;
+ int flags = 0;
+ if (n_args >= 2) {
+ if (args[1] != mp_const_none) {
+ mp_int_t timeout_i = mp_obj_get_int(args[1]);
+ if (timeout_i >= 0) {
+ timeout = timeout_i;
+ }
+ }
+ if (n_args >= 3) {
+ flags = mp_obj_get_int(args[2]);
+ }
+ }
+
+ self->flags = flags;
+
+ mp_uint_t start_tick = mp_hal_ticks_ms();
+ mp_uint_t n_ready;
+ for (;;) {
+ // poll the objects
+ n_ready = poll_map_poll(&self->poll_map, NULL);
+ if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
+ break;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ }
+
+ return n_ready;
+}
+
+STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_uint_t n_ready = poll_poll_internal(n_args, args);
+
+ // one or more objects are ready, or we had a timeout
+ mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
+ n_ready = 0;
+ for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) {
+ if (!mp_map_slot_is_filled(&self->poll_map, i)) {
+ continue;
+ }
+ poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
+ if (poll_obj->flags_ret != 0) {
+ mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)};
+ ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
+ if (self->flags & FLAG_ONESHOT) {
+ // Don't poll next time, until new event flags will be set explicitly
+ poll_obj->flags = 0;
+ }
+ }
+ }
+ return MP_OBJ_FROM_PTR(ret_list);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
+
+STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
+
+ if (self->ret_tuple == MP_OBJ_NULL) {
+ self->ret_tuple = mp_obj_new_tuple(2, NULL);
+ }
+
+ int n_ready = poll_poll_internal(n_args, args);
+ self->iter_cnt = n_ready;
+ self->iter_idx = 0;
+
+ return args[0];
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll);
+
+STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (self->iter_cnt == 0) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
+ self->iter_cnt--;
+
+ for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) {
+ self->iter_idx++;
+ if (!mp_map_slot_is_filled(&self->poll_map, i)) {
+ continue;
+ }
+ poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
+ if (poll_obj->flags_ret != 0) {
+ mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
+ t->items[0] = poll_obj->obj;
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret);
+ if (self->flags & FLAG_ONESHOT) {
+ // Don't poll next time, until new event flags will be set explicitly
+ poll_obj->flags = 0;
+ }
+ return MP_OBJ_FROM_PTR(t);
+ }
+ }
+
+ assert(!"inconsistent number of poll active entries");
+ self->iter_cnt = 0;
+ return MP_OBJ_STOP_ITERATION;
+}
+
+STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) },
+ { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) },
+ { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_poll,
+ MP_QSTR_poll,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, poll_iternext,
+ locals_dict, &poll_locals_dict
+ );
+
+// poll()
+STATIC mp_obj_t select_poll(void) {
+ mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll);
+ mp_map_init(&poll->poll_map, 0);
+ poll->iter_cnt = 0;
+ poll->ret_tuple = MP_OBJ_NULL;
+ return MP_OBJ_FROM_PTR(poll);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);
+
+STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_select) },
+ #if MICROPY_PY_SELECT_SELECT
+ { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) },
+ #endif
+ { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) },
+ { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(MP_STREAM_POLL_RD) },
+ { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(MP_STREAM_POLL_WR) },
+ { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(MP_STREAM_POLL_ERR) },
+ { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(MP_STREAM_POLL_HUP) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table);
+
+const mp_obj_module_t mp_module_select = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_select_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_select, mp_module_select);
+
+#endif // MICROPY_PY_SELECT
diff --git a/extmod/modsocket.c b/extmod/modsocket.c
new file mode 100644
index 0000000000000..488b6d17125d5
--- /dev/null
+++ b/extmod/modsocket.c
@@ -0,0 +1,658 @@
+/*
+ * 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 "py/objtuple.h"
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/mperrno.h"
+
+#if MICROPY_PY_NETWORK && MICROPY_PY_SOCKET && !MICROPY_PY_LWIP
+
+#include "shared/netutils/netutils.h"
+#include "modnetwork.h"
+
+/******************************************************************************/
+// socket class
+
+STATIC const mp_obj_type_t socket_type;
+
+STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_printf(print, "",
+ self->fileno, self->timeout, self->domain, self->type, self->proto, self->bound);
+}
+
+// constructor socket(domain=AF_INET, type=SOCK_STREAM, proto=0)
+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, 3, false);
+
+ // create socket object (not bound to any NIC yet)
+ mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
+ s->base.type = &socket_type;
+ s->nic = MP_OBJ_NULL;
+ s->nic_protocol = NULL;
+ s->domain = MOD_NETWORK_AF_INET;
+ s->type = MOD_NETWORK_SOCK_STREAM;
+ s->proto = 0;
+ s->bound = false;
+ s->fileno = -1;
+ if (n_args > 0) {
+ s->domain = mp_obj_get_int(args[0]);
+ if (n_args > 1) {
+ s->type = mp_obj_get_int(args[1]);
+ if (n_args > 2) {
+ s->proto = mp_obj_get_int(args[2]);
+ }
+ }
+ }
+ s->timeout = -1;
+ s->callback = MP_OBJ_NULL;
+ s->state = MOD_NETWORK_SS_NEW;
+ #if MICROPY_PY_SOCKET_EXTENDED_STATE
+ s->_private = NULL;
+ #endif
+
+ return MP_OBJ_FROM_PTR(s);
+}
+
+STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
+ if (self->nic == MP_OBJ_NULL) {
+ // select NIC based on IP
+ self->nic = mod_network_find_nic(ip);
+ self->nic_protocol = (mod_network_nic_protocol_t *)MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(self->nic), protocol);
+
+ // call the NIC to open the socket
+ int _errno;
+ if (self->nic_protocol->socket(self, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ #if MICROPY_PY_SOCKET_EXTENDED_STATE
+ // if a timeout was set before binding a NIC, call settimeout to reset it
+ if (self->timeout != -1 && self->nic_protocol->settimeout(self, self->timeout, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+ #endif
+ }
+}
+
+// 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 = MP_OBJ_TO_PTR(self_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);
+
+ // call the NIC to bind the socket
+ int _errno;
+ if (self->nic_protocol->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 = MP_OBJ_TO_PTR(args[0]);
+
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ // TODO I think we can listen even if not bound...
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+
+ mp_int_t backlog = MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT;
+ if (n_args > 1) {
+ backlog = mp_obj_get_int(args[1]);
+ backlog = (backlog < 0) ? 0 : backlog;
+ }
+
+ int _errno;
+ if (self->nic_protocol->listen(self, backlog, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ // set socket state
+ self->state = MOD_NETWORK_SS_LISTENING;
+
+ 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 = MP_OBJ_TO_PTR(self_in);
+
+ if (self->nic == MP_OBJ_NULL) {
+ // not bound
+ mp_raise_OSError(MP_EINVAL);
+ }
+
+ // create new socket object
+ // starts with empty NIC so that finaliser doesn't run close() method if accept() fails
+ mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
+ socket2->base.type = &socket_type;
+ socket2->nic = MP_OBJ_NULL;
+ socket2->nic_protocol = NULL;
+
+ // set the same address family, socket type and protocol as parent
+ socket2->domain = self->domain;
+ socket2->type = self->type;
+ socket2->proto = self->proto;
+ socket2->bound = false;
+ socket2->fileno = -1;
+ socket2->timeout = -1;
+ socket2->callback = MP_OBJ_NULL;
+ socket2->state = MOD_NETWORK_SS_NEW;
+ #if MICROPY_PY_SOCKET_EXTENDED_STATE
+ socket2->_private = NULL;
+ #endif
+
+ // accept incoming connection
+ uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ mp_uint_t port;
+ int _errno;
+ if (self->nic_protocol->accept(self, socket2, ip, &port, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ // new socket has valid state, so set the NIC to the same as parent
+ socket2->nic = self->nic;
+ socket2->nic_protocol = self->nic_protocol;
+
+ // make the return value
+ mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
+ client->items[0] = MP_OBJ_FROM_PTR(socket2);
+ client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
+
+ return MP_OBJ_FROM_PTR(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 = MP_OBJ_TO_PTR(self_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);
+
+ // call the NIC to connect the socket
+ int _errno;
+ if (self->nic_protocol->connect(self, ip, port, &_errno) != 0) {
+ mp_raise_OSError(_errno);
+ }
+
+ // set socket state
+ self->state = MOD_NETWORK_SS_CONNECTED;
+
+ 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 = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_EPIPE);
+ }
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+ int _errno;
+ mp_uint_t ret = self->nic_protocol->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+ return mp_obj_new_int_from_uint(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
+
+STATIC mp_obj_t socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_EPIPE);
+ }
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+
+ int _errno;
+ mp_uint_t ret = 0;
+ if (self->timeout == 0) {
+ ret = self->nic_protocol->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ } else if (bufinfo.len > ret) {
+ mp_raise_OSError(MP_EAGAIN);
+ }
+ } else {
+ // TODO: In CPython3.5, socket timeout should apply to the
+ // entire sendall() operation, not to individual send() chunks.
+ while (bufinfo.len != 0) {
+ ret = self->nic_protocol->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+ bufinfo.len -= ret;
+ bufinfo.buf = (char *)bufinfo.buf + ret;
+ }
+ }
+ return mp_obj_new_int_from_uint(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_sendall_obj, socket_sendall);
+
+// 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 = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+ mp_int_t len = mp_obj_get_int(len_in);
+ vstr_t vstr;
+ vstr_init_len(&vstr, len);
+ int _errno;
+ mp_uint_t ret = self->nic_protocol->recv(self, (byte *)vstr.buf, len, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+ if (ret == 0) {
+ return mp_const_empty_bytes;
+ }
+ vstr.len = ret;
+ return mp_obj_new_bytes_from_vstr(&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 = MP_OBJ_TO_PTR(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_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);
+
+ // call the NIC to sendto
+ int _errno;
+ mp_int_t ret = self->nic_protocol->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
+ if (ret == -1) {
+ 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 = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ // not connected
+ mp_raise_OSError(MP_ENOTCONN);
+ }
+ vstr_t vstr;
+ vstr_init_len(&vstr, mp_obj_get_int(len_in));
+ byte ip[4];
+ mp_uint_t port;
+ int _errno;
+ mp_int_t ret = self->nic_protocol->recvfrom(self, (byte *)vstr.buf, vstr.len, ip, &port, &_errno);
+ if (ret == -1) {
+ mp_raise_OSError(_errno);
+ }
+ mp_obj_t tuple[2];
+ if (ret == 0) {
+ tuple[0] = mp_const_empty_bytes;
+ } else {
+ vstr.len = ret;
+ tuple[0] = mp_obj_new_bytes_from_vstr(&vstr);
+ }
+ tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
+ 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 = MP_OBJ_TO_PTR(args[0]);
+
+ if (self->nic == MP_OBJ_NULL) {
+ // bind to default NIC.
+ uint8_t ip[4] = {0, 0, 0, 0};
+ socket_select_nic(self, ip);
+ }
+
+ 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 if (opt == 20 && args[3] == mp_const_none) {
+ optval = MP_OBJ_NULL;
+ optlen = 0;
+ } else if (opt == 20 && mp_obj_is_callable(args[3])) {
+ optval = args[3];
+ optlen = sizeof(optval);
+ } 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 (self->nic_protocol->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);
+
+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, 3, socket_makefile);
+
+// 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 = MP_OBJ_TO_PTR(self_in);
+ mp_uint_t timeout;
+ if (timeout_in == mp_const_none) {
+ timeout = -1;
+ } else {
+ #if MICROPY_PY_BUILTINS_FLOAT
+ timeout = (mp_uint_t)(MICROPY_FLOAT_CONST(1000.0) * mp_obj_get_float(timeout_in));
+ #else
+ timeout = 1000 * mp_obj_get_int(timeout_in);
+ #endif
+ }
+ if (self->nic == MP_OBJ_NULL) {
+ #if MICROPY_PY_SOCKET_EXTENDED_STATE
+ // store the timeout in the socket state until a NIC is bound
+ self->timeout = timeout;
+ #else
+ // not connected
+ mp_raise_OSError(MP_ENOTCONN);
+ #endif
+ } else {
+ int _errno;
+ if (self->nic_protocol->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 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_sendall_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_makefile), MP_ROM_PTR(&socket_makefile_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_read), MP_ROM_PTR(&mp_stream_read_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_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
+ mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ return MP_STREAM_ERROR;
+ }
+ mp_int_t ret = self->nic_protocol->recv(self, (byte *)buf, size, errcode);
+ if (ret < 0) {
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+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 = MP_OBJ_TO_PTR(self_in);
+ if (self->nic == MP_OBJ_NULL) {
+ return MP_STREAM_ERROR;
+ }
+ mp_int_t ret = self->nic_protocol->send(self, buf, size, errcode);
+ if (ret < 0) {
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+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);
+ if (request == MP_STREAM_CLOSE) {
+ if (self->nic != MP_OBJ_NULL) {
+ self->nic_protocol->close(self);
+ self->nic = MP_OBJ_NULL;
+ }
+ self->state = MOD_NETWORK_SS_CLOSED;
+ return 0;
+ }
+ if (self->nic == MP_OBJ_NULL) {
+ if (request == MP_STREAM_POLL) {
+ if (self->state == MOD_NETWORK_SS_NEW) {
+ // New sockets are writable and not connected.
+ return MP_STREAM_POLL_HUP | MP_STREAM_POLL_WR;
+ } else if (self->state == MOD_NETWORK_SS_CLOSED) {
+ // Closed socket, return invalid.
+ return MP_STREAM_POLL_NVAL;
+ }
+ }
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+ return self->nic_protocol->ioctl(self, request, arg, errcode);
+}
+
+STATIC const mp_stream_p_t socket_stream_p = {
+ .read = socket_read,
+ .write = socket_write,
+ .ioctl = socket_ioctl,
+ .is_text = false,
+};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, socket_make_new,
+ protocol, &socket_stream_p,
+ locals_dict, &socket_locals_dict,
+ print, socket_print
+ );
+
+/******************************************************************************/
+// socket module
+
+// function socket.getaddrinfo(host, port)
+STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
+ size_t hlen;
+ const char *host = mp_obj_str_get_data(args[0], &hlen);
+ mp_int_t port = mp_obj_get_int(args[1]);
+ uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ bool have_ip = false;
+
+ // if constraints were passed then check they are compatible with the supported params
+ if (n_args > 2) {
+ mp_int_t family = mp_obj_get_int(args[2]);
+ mp_int_t type = 0;
+ mp_int_t proto = 0;
+ mp_int_t flags = 0;
+ if (n_args > 3) {
+ type = mp_obj_get_int(args[3]);
+ if (n_args > 4) {
+ proto = mp_obj_get_int(args[4]);
+ if (n_args > 5) {
+ flags = mp_obj_get_int(args[5]);
+ }
+ }
+ }
+ if (!((family == 0 || family == MOD_NETWORK_AF_INET)
+ && (type == 0 || type == MOD_NETWORK_SOCK_STREAM)
+ && proto == 0
+ && flags == 0)) {
+ mp_warning(MP_WARN_CAT(RuntimeWarning), "unsupported getaddrinfo constraints");
+ }
+ }
+
+ if (hlen > 0) {
+ // check if host is already in IP form
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ netutils_parse_ipv4_addr(args[0], out_ip, NETUTILS_BIG);
+ have_ip = true;
+ nlr_pop();
+ } else {
+ // swallow exception: host was not in IP form so need to do DNS lookup
+ }
+ }
+
+ if (!have_ip) {
+ // find a NIC that can do a name lookup
+ 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];
+ mod_network_nic_protocol_t *nic_protocol = (mod_network_nic_protocol_t *)MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(nic), protocol);
+ if (nic_protocol->gethostbyname != NULL) {
+ int ret = nic_protocol->gethostbyname(nic, host, hlen, out_ip);
+ if (ret != 0) {
+ mp_raise_OSError(ret);
+ }
+ have_ip = true;
+ break;
+ }
+ }
+ }
+
+ if (!have_ip) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("no available NIC"));
+ }
+
+ mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
+ tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
+ tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_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_BIG);
+ return mp_obj_new_list(1, (mp_obj_t *)&tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 6, mod_socket_getaddrinfo);
+
+STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_socket) },
+
+ { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) },
+ { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_socket_getaddrinfo_obj) },
+
+ // class constants
+ { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) },
+ { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) },
+
+ { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
+
+ { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(MOD_NETWORK_SOL_SOCKET) },
+ { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(MOD_NETWORK_SO_REUSEADDR) },
+ { MP_ROM_QSTR(MP_QSTR_SO_KEEPALIVE), MP_ROM_INT(MOD_NETWORK_SO_KEEPALIVE) },
+ { MP_ROM_QSTR(MP_QSTR_SO_SNDTIMEO), MP_ROM_INT(MOD_NETWORK_SO_SNDTIMEO) },
+ { MP_ROM_QSTR(MP_QSTR_SO_RCVTIMEO), MP_ROM_INT(MOD_NETWORK_SO_RCVTIMEO) },
+
+ /*
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(MOD_NETWORK_IPPROTO_IP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_ICMP), MP_ROM_INT(MOD_NETWORK_IPPROTO_ICMP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV4), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV4) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(MOD_NETWORK_IPPROTO_TCP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(MOD_NETWORK_IPPROTO_UDP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV6), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV6) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_RAW), MP_ROM_INT(MOD_NETWORK_IPPROTO_RAW) },
+ */
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table);
+
+const mp_obj_module_t mp_module_socket = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_socket_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_socket, mp_module_socket);
+
+#endif // MICROPY_PY_NETWORK && MICROPY_PY_SOCKET && !MICROPY_PY_LWIP
diff --git a/extmod/modssl_axtls.c b/extmod/modssl_axtls.c
new file mode 100644
index 0000000000000..d169d89a2cfe0
--- /dev/null
+++ b/extmod/modssl_axtls.c
@@ -0,0 +1,461 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2019 Paul Sokolovsky
+ * Copyright (c) 2023 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/objstr.h"
+
+#if MICROPY_PY_SSL && MICROPY_SSL_AXTLS
+
+#include "ssl.h"
+
+#define PROTOCOL_TLS_CLIENT (0)
+#define PROTOCOL_TLS_SERVER (1)
+
+// This corresponds to an SSLContext object.
+typedef struct _mp_obj_ssl_context_t {
+ mp_obj_base_t base;
+ mp_obj_t key;
+ mp_obj_t cert;
+} mp_obj_ssl_context_t;
+
+// This corresponds to an SSLSocket object.
+typedef struct _mp_obj_ssl_socket_t {
+ mp_obj_base_t base;
+ mp_obj_t sock;
+ SSL_CTX *ssl_ctx;
+ SSL *ssl_sock;
+ byte *buf;
+ uint32_t bytes_left;
+ bool blocking;
+} mp_obj_ssl_socket_t;
+
+struct ssl_args {
+ mp_arg_val_t key;
+ mp_arg_val_t cert;
+ mp_arg_val_t server_side;
+ mp_arg_val_t server_hostname;
+ mp_arg_val_t do_handshake;
+};
+
+STATIC const mp_obj_type_t ssl_context_type;
+STATIC const mp_obj_type_t ssl_socket_type;
+
+STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
+ bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname);
+
+/******************************************************************************/
+// Helper functions.
+
+// Table of error strings corresponding to SSL_xxx error codes.
+STATIC const char *const ssl_error_tab1[] = {
+ "NOT_OK",
+ "DEAD",
+ "CLOSE_NOTIFY",
+ "EAGAIN",
+};
+STATIC const char *const ssl_error_tab2[] = {
+ "CONN_LOST",
+ "RECORD_OVERFLOW",
+ "SOCK_SETUP_FAILURE",
+ NULL,
+ "INVALID_HANDSHAKE",
+ "INVALID_PROT_MSG",
+ "INVALID_HMAC",
+ "INVALID_VERSION",
+ "UNSUPPORTED_EXTENSION",
+ "INVALID_SESSION",
+ "NO_CIPHER",
+ "INVALID_CERT_HASH_ALG",
+ "BAD_CERTIFICATE",
+ "INVALID_KEY",
+ NULL,
+ "FINISHED_INVALID",
+ "NO_CERT_DEFINED",
+ "NO_CLIENT_RENOG",
+ "NOT_SUPPORTED",
+};
+
+STATIC NORETURN void ssl_raise_error(int err) {
+ MP_STATIC_ASSERT(SSL_NOT_OK - 3 == SSL_EAGAIN);
+ MP_STATIC_ASSERT(SSL_ERROR_CONN_LOST - 18 == SSL_ERROR_NOT_SUPPORTED);
+
+ // Check if err corresponds to something in one of the error string tables.
+ const char *errstr = NULL;
+ if (SSL_NOT_OK >= err && err >= SSL_EAGAIN) {
+ errstr = ssl_error_tab1[SSL_NOT_OK - err];
+ } else if (SSL_ERROR_CONN_LOST >= err && err >= SSL_ERROR_NOT_SUPPORTED) {
+ errstr = ssl_error_tab2[SSL_ERROR_CONN_LOST - err];
+ }
+
+ // Unknown error, just raise the error code.
+ if (errstr == NULL) {
+ mp_raise_OSError(err);
+ }
+
+ // Construct string object.
+ mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
+ if (o_str == NULL) {
+ mp_raise_OSError(err);
+ }
+ o_str->base.type = &mp_type_str;
+ o_str->data = (const byte *)errstr;
+ o_str->len = strlen((char *)o_str->data);
+ o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
+
+ // Raise OSError(err, str).
+ mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(err), MP_OBJ_FROM_PTR(o_str)};
+ nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
+}
+
+/******************************************************************************/
+// SSLContext type.
+
+STATIC mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 1, 1, false);
+
+ // The "protocol" argument is ignored in this implementation.
+
+ // Create SSLContext object.
+ #if MICROPY_PY_SSL_FINALISER
+ mp_obj_ssl_context_t *self = m_new_obj_with_finaliser(mp_obj_ssl_context_t);
+ #else
+ mp_obj_ssl_context_t *self = m_new_obj(mp_obj_ssl_context_t);
+ #endif
+ self->base.type = type_in;
+ self->key = mp_const_none;
+ self->cert = mp_const_none;
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) {
+ self->key = key_obj;
+ self->cert = cert_obj;
+}
+
+STATIC mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_do_handshake_on_connect, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ };
+
+ // Parse arguments.
+ mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_obj_t sock = pos_args[1];
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // Create and return the new SSLSocket object.
+ return ssl_socket_make_new(self, sock, args[ARG_server_side].u_bool,
+ args[ARG_do_handshake_on_connect].u_bool, args[ARG_server_hostname].u_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ssl_context_wrap_socket_obj, 2, ssl_context_wrap_socket);
+
+STATIC const mp_rom_map_elem_t ssl_context_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_context_wrap_socket_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(ssl_context_locals_dict, ssl_context_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ssl_context_type,
+ MP_QSTR_SSLContext,
+ MP_TYPE_FLAG_NONE,
+ make_new, ssl_context_make_new,
+ locals_dict, &ssl_context_locals_dict
+ );
+
+/******************************************************************************/
+// SSLSocket type.
+
+STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
+ bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname) {
+
+ #if MICROPY_PY_SSL_FINALISER
+ mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
+ #else
+ mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
+ #endif
+ o->base.type = &ssl_socket_type;
+ o->buf = NULL;
+ o->bytes_left = 0;
+ o->sock = sock;
+ o->blocking = true;
+
+ uint32_t options = SSL_SERVER_VERIFY_LATER;
+ if (!do_handshake_on_connect) {
+ options |= SSL_CONNECT_IN_PARTS;
+ }
+ if (ssl_context->key != mp_const_none) {
+ options |= SSL_NO_DEFAULT_KEY;
+ }
+ if ((o->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) {
+ mp_raise_OSError(MP_EINVAL);
+ }
+
+ if (ssl_context->key != mp_const_none) {
+ size_t len;
+ const byte *data = (const byte *)mp_obj_str_get_data(ssl_context->key, &len);
+ int res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_RSA_KEY, data, len, NULL);
+ if (res != SSL_OK) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
+ }
+
+ data = (const byte *)mp_obj_str_get_data(ssl_context->cert, &len);
+ res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_X509_CERT, data, len, NULL);
+ if (res != SSL_OK) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
+ }
+ }
+
+ if (server_side) {
+ o->ssl_sock = ssl_server_new(o->ssl_ctx, (long)sock);
+ } else {
+ SSL_EXTENSIONS *ext = ssl_ext_new();
+
+ if (server_hostname != mp_const_none) {
+ ext->host_name = (char *)mp_obj_str_get_str(server_hostname);
+ }
+
+ o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext);
+
+ if (do_handshake_on_connect) {
+ int r = ssl_handshake_status(o->ssl_sock);
+
+ if (r != SSL_OK) {
+ if (r == SSL_CLOSE_NOTIFY) { // EOF
+ r = MP_ENOTCONN;
+ } else if (r == SSL_EAGAIN) {
+ r = MP_EAGAIN;
+ }
+ ssl_raise_error(r);
+ }
+ }
+ }
+
+ return o;
+}
+
+STATIC mp_uint_t ssl_socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
+
+ if (o->ssl_sock == NULL) {
+ *errcode = EBADF;
+ return MP_STREAM_ERROR;
+ }
+
+ while (o->bytes_left == 0) {
+ mp_int_t r = ssl_read(o->ssl_sock, &o->buf);
+ if (r == SSL_OK) {
+ // SSL_OK from ssl_read() means "everything is ok, but there's
+ // no user data yet". It may happen e.g. if handshake is not
+ // finished yet. The best way we can treat it is by returning
+ // EAGAIN. This may be a bit unexpected in blocking mode, but
+ // default is to perform complete handshake in constructor, so
+ // this should not happen in blocking mode. On the other hand,
+ // in nonblocking mode EAGAIN (comparing to the alternative of
+ // looping) is really preferable.
+ if (o->blocking) {
+ continue;
+ } else {
+ goto eagain;
+ }
+ }
+ if (r < 0) {
+ if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) {
+ // EOF
+ return 0;
+ }
+ if (r == SSL_EAGAIN) {
+ eagain:
+ r = MP_EAGAIN;
+ }
+ *errcode = r;
+ return MP_STREAM_ERROR;
+ }
+ o->bytes_left = r;
+ }
+
+ if (size > o->bytes_left) {
+ size = o->bytes_left;
+ }
+ memcpy(buf, o->buf, size);
+ o->buf += size;
+ o->bytes_left -= size;
+ return size;
+}
+
+STATIC mp_uint_t ssl_socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
+
+ if (o->ssl_sock == NULL) {
+ *errcode = EBADF;
+ return MP_STREAM_ERROR;
+ }
+
+ mp_int_t r;
+eagain:
+ r = ssl_write(o->ssl_sock, buf, size);
+ if (r == 0) {
+ // see comment in ssl_socket_read above
+ if (o->blocking) {
+ goto eagain;
+ } else {
+ r = SSL_EAGAIN;
+ }
+ }
+ if (r < 0) {
+ if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) {
+ return 0; // EOF
+ }
+ if (r == SSL_EAGAIN) {
+ r = MP_EAGAIN;
+ }
+ *errcode = r;
+ return MP_STREAM_ERROR;
+ }
+ return r;
+}
+
+STATIC mp_uint_t ssl_socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+ mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
+ if (request == MP_STREAM_CLOSE && self->ssl_sock != NULL) {
+ ssl_free(self->ssl_sock);
+ ssl_ctx_free(self->ssl_ctx);
+ self->ssl_sock = NULL;
+ }
+ // Pass all requests down to the underlying socket
+ return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode);
+}
+
+STATIC mp_obj_t ssl_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in);
+ mp_obj_t sock = o->sock;
+ mp_obj_t dest[3];
+ mp_load_method(sock, MP_QSTR_setblocking, dest);
+ dest[2] = flag_in;
+ mp_obj_t res = mp_call_method_n_kw(1, 0, dest);
+ o->blocking = mp_obj_is_true(flag_in);
+ return res;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(ssl_socket_setblocking_obj, ssl_socket_setblocking);
+
+STATIC const mp_rom_map_elem_t ssl_socket_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&ssl_socket_setblocking_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+ #if MICROPY_PY_SSL_FINALISER
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
+ #endif
+};
+STATIC MP_DEFINE_CONST_DICT(ssl_socket_locals_dict, ssl_socket_locals_dict_table);
+
+STATIC const mp_stream_p_t ssl_socket_stream_p = {
+ .read = ssl_socket_read,
+ .write = ssl_socket_write,
+ .ioctl = ssl_socket_ioctl,
+};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ssl_socket_type,
+ MP_QSTR_SSLSocket,
+ MP_TYPE_FLAG_NONE,
+ protocol, &ssl_socket_stream_p,
+ locals_dict, &ssl_socket_locals_dict
+ );
+
+/******************************************************************************/
+// ssl module.
+
+STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum {
+ ARG_key,
+ ARG_cert,
+ ARG_server_side,
+ ARG_server_hostname,
+ ARG_do_handshake,
+ };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ };
+
+ // Parse arguments.
+ mp_obj_t sock = 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);
+
+ // Create SSLContext.
+ mp_int_t protocol = args[ARG_server_side].u_bool ? PROTOCOL_TLS_SERVER : PROTOCOL_TLS_CLIENT;
+ mp_obj_t ssl_context_args[1] = { MP_OBJ_NEW_SMALL_INT(protocol) };
+ mp_obj_ssl_context_t *ssl_context = MP_OBJ_TO_PTR(ssl_context_make_new(&ssl_context_type, 1, 0, ssl_context_args));
+
+ // Load key and cert if given.
+ if (args[ARG_key].u_obj != mp_const_none) {
+ ssl_context_load_key(ssl_context, args[ARG_key].u_obj, args[ARG_cert].u_obj);
+ }
+
+ // Create and return the new SSLSocket object.
+ return ssl_socket_make_new(ssl_context, sock, args[ARG_server_side].u_bool,
+ args[ARG_do_handshake].u_bool, args[ARG_server_hostname].u_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
+
+STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ssl) },
+
+ // Functions.
+ { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
+
+ // Classes.
+ { MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_context_type) },
+
+ // Constants.
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(PROTOCOL_TLS_CLIENT) },
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(PROTOCOL_TLS_SERVER) },
+};
+STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
+
+const mp_obj_module_t mp_module_ssl = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_ssl, mp_module_ssl);
+
+#endif // MICROPY_PY_SSL && MICROPY_SSL_AXTLS
diff --git a/extmod/modssl_mbedtls.c b/extmod/modssl_mbedtls.c
new file mode 100644
index 0000000000000..83f6f907f4cc2
--- /dev/null
+++ b/extmod/modssl_mbedtls.c
@@ -0,0 +1,640 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Linaro Ltd.
+ * Copyright (c) 2019 Paul Sokolovsky
+ * Copyright (c) 2023 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 "py/mpconfig.h"
+#if MICROPY_PY_SSL && MICROPY_SSL_MBEDTLS
+
+#include
+#include
+#include // needed because mp_is_nonblocking_error uses system error codes
+
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/objstr.h"
+
+// mbedtls_time_t
+#include "mbedtls/platform.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/pk.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+
+#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
+
+// This corresponds to an SSLContext object.
+typedef struct _mp_obj_ssl_context_t {
+ mp_obj_base_t base;
+ mbedtls_entropy_context entropy;
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_ssl_config conf;
+ mbedtls_x509_crt cacert;
+ mbedtls_x509_crt cert;
+ mbedtls_pk_context pkey;
+ int authmode;
+} mp_obj_ssl_context_t;
+
+// This corresponds to an SSLSocket object.
+typedef struct _mp_obj_ssl_socket_t {
+ mp_obj_base_t base;
+ mp_obj_ssl_context_t *ssl_context;
+ mp_obj_t sock;
+ mbedtls_ssl_context ssl;
+
+ uintptr_t poll_mask; // Indicates which read or write operations the protocol needs next
+ int last_error; // The last error code, if any
+} mp_obj_ssl_socket_t;
+
+STATIC const mp_obj_type_t ssl_context_type;
+STATIC const mp_obj_type_t ssl_socket_type;
+
+STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
+ bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname);
+
+/******************************************************************************/
+// Helper functions.
+
+#ifdef MBEDTLS_DEBUG_C
+STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
+ (void)ctx;
+ (void)level;
+ mp_printf(&mp_plat_print, "DBG:%s:%04d: %s\n", file, line, str);
+}
+#endif
+
+STATIC NORETURN void mbedtls_raise_error(int err) {
+ // Handle special cases.
+ if (err == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
+ mp_raise_OSError(MP_ENOMEM);
+ } else if (err == MBEDTLS_ERR_PK_BAD_INPUT_DATA) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
+ } else if (err == MBEDTLS_ERR_X509_BAD_INPUT_DATA) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
+ }
+
+ // _mbedtls_ssl_send and _mbedtls_ssl_recv (below) turn positive error codes from the
+ // underlying socket into negative codes to pass them through mbedtls. Here we turn them
+ // positive again so they get interpreted as the OSError they really are. The
+ // cut-off of -256 is a bit hacky, sigh.
+ if (err < 0 && err > -256) {
+ mp_raise_OSError(-err);
+ }
+
+ #if defined(MBEDTLS_ERROR_C)
+ // Including mbedtls_strerror takes about 1.5KB due to the error strings.
+ // MBEDTLS_ERROR_C is the define used by mbedtls to conditionally include mbedtls_strerror.
+ // It is set/unset in the MBEDTLS_CONFIG_FILE which is defined in the Makefile.
+
+ // Try to allocate memory for the message
+ #define ERR_STR_MAX 80 // mbedtls_strerror truncates if it doesn't fit
+ mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
+ byte *o_str_buf = m_new_maybe(byte, ERR_STR_MAX);
+ if (o_str == NULL || o_str_buf == NULL) {
+ mp_raise_OSError(err);
+ }
+
+ // print the error message into the allocated buffer
+ mbedtls_strerror(err, (char *)o_str_buf, ERR_STR_MAX);
+ size_t len = strlen((char *)o_str_buf);
+
+ // Put the exception object together
+ o_str->base.type = &mp_type_str;
+ o_str->data = o_str_buf;
+ o_str->len = len;
+ o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
+ // raise
+ mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(err), MP_OBJ_FROM_PTR(o_str)};
+ nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
+ #else
+ // mbedtls is compiled without error strings so we simply return the err number
+ mp_raise_OSError(err); // err is typically a large negative number
+ #endif
+}
+
+/******************************************************************************/
+// SSLContext type.
+
+STATIC mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 1, 1, false);
+
+ // This is the "protocol" argument.
+ mp_int_t endpoint = mp_obj_get_int(args[0]);
+
+ // Create SSLContext object.
+ #if MICROPY_PY_SSL_FINALISER
+ mp_obj_ssl_context_t *self = m_new_obj_with_finaliser(mp_obj_ssl_context_t);
+ #else
+ mp_obj_ssl_context_t *self = m_new_obj(mp_obj_ssl_context_t);
+ #endif
+ self->base.type = type_in;
+
+ // Initialise mbedTLS state.
+ mbedtls_ssl_config_init(&self->conf);
+ mbedtls_entropy_init(&self->entropy);
+ mbedtls_ctr_drbg_init(&self->ctr_drbg);
+ mbedtls_x509_crt_init(&self->cacert);
+ mbedtls_x509_crt_init(&self->cert);
+ mbedtls_pk_init(&self->pkey);
+
+ #ifdef MBEDTLS_DEBUG_C
+ // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
+ mbedtls_debug_set_threshold(3);
+ #endif
+
+ const byte seed[] = "upy";
+ int ret = mbedtls_ctr_drbg_seed(&self->ctr_drbg, mbedtls_entropy_func, &self->entropy, seed, sizeof(seed));
+ if (ret != 0) {
+ mbedtls_raise_error(ret);
+ }
+
+ ret = mbedtls_ssl_config_defaults(&self->conf, endpoint,
+ MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
+ if (ret != 0) {
+ mbedtls_raise_error(ret);
+ }
+
+ if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
+ // The CPython default is MBEDTLS_SSL_VERIFY_REQUIRED, but to maintain
+ // backwards compatibility we use MBEDTLS_SSL_VERIFY_NONE for now.
+ self->authmode = MBEDTLS_SSL_VERIFY_NONE;
+ } else {
+ self->authmode = MBEDTLS_SSL_VERIFY_NONE;
+ }
+ mbedtls_ssl_conf_authmode(&self->conf, self->authmode);
+ mbedtls_ssl_conf_rng(&self->conf, mbedtls_ctr_drbg_random, &self->ctr_drbg);
+ #ifdef MBEDTLS_DEBUG_C
+ mbedtls_ssl_conf_dbg(&self->conf, mbedtls_debug, NULL);
+ #endif
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void ssl_context_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+ mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);
+ if (dest[0] == MP_OBJ_NULL) {
+ // Load attribute.
+ if (attr == MP_QSTR_verify_mode) {
+ dest[0] = MP_OBJ_NEW_SMALL_INT(self->authmode);
+ } else {
+ // Continue lookup in locals_dict.
+ dest[1] = MP_OBJ_SENTINEL;
+ }
+ } else if (dest[1] != MP_OBJ_NULL) {
+ // Store attribute.
+ if (attr == MP_QSTR_verify_mode) {
+ self->authmode = mp_obj_get_int(dest[1]);
+ dest[0] = MP_OBJ_NULL;
+ mbedtls_ssl_conf_authmode(&self->conf, self->authmode);
+ }
+ }
+}
+
+#if MICROPY_PY_SSL_FINALISER
+STATIC mp_obj_t ssl_context___del__(mp_obj_t self_in) {
+ mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);
+ mbedtls_pk_free(&self->pkey);
+ mbedtls_x509_crt_free(&self->cert);
+ mbedtls_x509_crt_free(&self->cacert);
+ mbedtls_ctr_drbg_free(&self->ctr_drbg);
+ mbedtls_entropy_free(&self->entropy);
+ mbedtls_ssl_config_free(&self->conf);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(ssl_context___del___obj, ssl_context___del__);
+#endif
+
+STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) {
+ size_t key_len;
+ const byte *key = (const byte *)mp_obj_str_get_data(key_obj, &key_len);
+ // len should include terminating null
+ int ret;
+ #if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ ret = mbedtls_pk_parse_key(&self->pkey, key, key_len + 1, NULL, 0, mbedtls_ctr_drbg_random, &self->ctr_drbg);
+ #else
+ ret = mbedtls_pk_parse_key(&self->pkey, key, key_len + 1, NULL, 0);
+ #endif
+ if (ret != 0) {
+ mbedtls_raise_error(MBEDTLS_ERR_PK_BAD_INPUT_DATA); // use general error for all key errors
+ }
+
+ size_t cert_len;
+ const byte *cert = (const byte *)mp_obj_str_get_data(cert_obj, &cert_len);
+ // len should include terminating null
+ ret = mbedtls_x509_crt_parse(&self->cert, cert, cert_len + 1);
+ if (ret != 0) {
+ mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors
+ }
+
+ ret = mbedtls_ssl_conf_own_cert(&self->conf, &self->cert, &self->pkey);
+ if (ret != 0) {
+ mbedtls_raise_error(ret);
+ }
+}
+
+STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) {
+ size_t cacert_len;
+ const byte *cacert = (const byte *)mp_obj_str_get_data(cadata_obj, &cacert_len);
+ // len should include terminating null
+ int ret = mbedtls_x509_crt_parse(&self->cacert, cacert, cacert_len + 1);
+ if (ret != 0) {
+ mbedtls_raise_error(MBEDTLS_ERR_X509_BAD_INPUT_DATA); // use general error for all cert errors
+ }
+
+ mbedtls_ssl_conf_ca_chain(&self->conf, &self->cacert, NULL);
+}
+
+STATIC mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_do_handshake_on_connect, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ };
+
+ // Parse arguments.
+ mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_obj_t sock = pos_args[1];
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // Create and return the new SSLSocket object.
+ return ssl_socket_make_new(self, sock, args[ARG_server_side].u_bool,
+ args[ARG_do_handshake_on_connect].u_bool, args[ARG_server_hostname].u_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ssl_context_wrap_socket_obj, 2, ssl_context_wrap_socket);
+
+STATIC const mp_rom_map_elem_t ssl_context_locals_dict_table[] = {
+ #if MICROPY_PY_SSL_FINALISER
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ssl_context___del___obj) },
+ #endif
+ { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_context_wrap_socket_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(ssl_context_locals_dict, ssl_context_locals_dict_table);
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ssl_context_type,
+ MP_QSTR_SSLContext,
+ MP_TYPE_FLAG_NONE,
+ make_new, ssl_context_make_new,
+ attr, ssl_context_attr,
+ locals_dict, &ssl_context_locals_dict
+ );
+
+/******************************************************************************/
+// SSLSocket type.
+
+STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
+ mp_obj_t sock = *(mp_obj_t *)ctx;
+
+ const mp_stream_p_t *sock_stream = mp_get_stream(sock);
+ int err;
+
+ mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err);
+ if (out_sz == MP_STREAM_ERROR) {
+ if (mp_is_nonblocking_error(err)) {
+ return MBEDTLS_ERR_SSL_WANT_WRITE;
+ }
+ return -err; // convert an MP_ERRNO to something mbedtls passes through as error
+ } else {
+ return out_sz;
+ }
+}
+
+// _mbedtls_ssl_recv is called by mbedtls to receive bytes from the underlying socket
+STATIC int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
+ mp_obj_t sock = *(mp_obj_t *)ctx;
+
+ const mp_stream_p_t *sock_stream = mp_get_stream(sock);
+ int err;
+
+ mp_uint_t out_sz = sock_stream->read(sock, buf, len, &err);
+ if (out_sz == MP_STREAM_ERROR) {
+ if (mp_is_nonblocking_error(err)) {
+ return MBEDTLS_ERR_SSL_WANT_READ;
+ }
+ return -err;
+ } else {
+ return out_sz;
+ }
+}
+
+STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
+ bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname) {
+
+ // Verify the socket object has the full stream protocol
+ mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
+
+ #if MICROPY_PY_SSL_FINALISER
+ mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
+ #else
+ mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
+ #endif
+ o->base.type = &ssl_socket_type;
+ o->sock = sock;
+ o->poll_mask = 0;
+ o->last_error = 0;
+
+ int ret;
+ mbedtls_ssl_init(&o->ssl);
+
+ ret = mbedtls_ssl_setup(&o->ssl, &ssl_context->conf);
+ if (ret != 0) {
+ goto cleanup;
+ }
+
+ if (server_hostname != mp_const_none) {
+ const char *sni = mp_obj_str_get_str(server_hostname);
+ ret = mbedtls_ssl_set_hostname(&o->ssl, sni);
+ if (ret != 0) {
+ goto cleanup;
+ }
+ }
+
+ mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
+
+ if (do_handshake_on_connect) {
+ while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) {
+ if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+ goto cleanup;
+ }
+ #ifdef MICROPY_EVENT_POLL_HOOK
+ MICROPY_EVENT_POLL_HOOK
+ #endif
+ }
+ }
+
+ return MP_OBJ_FROM_PTR(o);
+
+cleanup:
+ mbedtls_ssl_free(&o->ssl);
+ mbedtls_raise_error(ret);
+}
+
+STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
+ if (!mp_obj_is_true(binary_form)) {
+ mp_raise_NotImplementedError(NULL);
+ }
+ const mbedtls_x509_crt *peer_cert = mbedtls_ssl_get_peer_cert(&o->ssl);
+ if (peer_cert == NULL) {
+ return mp_const_none;
+ }
+ return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert);
+
+STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
+ o->poll_mask = 0;
+
+ if (o->last_error) {
+ *errcode = o->last_error;
+ return MP_STREAM_ERROR;
+ }
+
+ int ret = mbedtls_ssl_read(&o->ssl, buf, size);
+ if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
+ // end of stream
+ return 0;
+ }
+ if (ret >= 0) {
+ return ret;
+ }
+ if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
+ ret = MP_EWOULDBLOCK;
+ } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+ // If handshake is not finished, read attempt may end up in protocol
+ // wanting to write next handshake message. The same may happen with
+ // renegotiation.
+ ret = MP_EWOULDBLOCK;
+ o->poll_mask = MP_STREAM_POLL_WR;
+ } else {
+ o->last_error = ret;
+ }
+ *errcode = ret;
+ return MP_STREAM_ERROR;
+}
+
+STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
+ o->poll_mask = 0;
+
+ if (o->last_error) {
+ *errcode = o->last_error;
+ return MP_STREAM_ERROR;
+ }
+
+ int ret = mbedtls_ssl_write(&o->ssl, buf, size);
+ if (ret >= 0) {
+ return ret;
+ }
+ if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+ ret = MP_EWOULDBLOCK;
+ } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
+ // If handshake is not finished, write attempt may end up in protocol
+ // wanting to read next handshake message. The same may happen with
+ // renegotiation.
+ ret = MP_EWOULDBLOCK;
+ o->poll_mask = MP_STREAM_POLL_RD;
+ } else {
+ o->last_error = ret;
+ }
+ *errcode = ret;
+ return MP_STREAM_ERROR;
+}
+
+STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
+ mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in);
+ mp_obj_t sock = o->sock;
+ mp_obj_t dest[3];
+ mp_load_method(sock, MP_QSTR_setblocking, dest);
+ dest[2] = flag_in;
+ return mp_call_method_n_kw(1, 0, dest);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
+
+STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+ mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
+ mp_uint_t ret = 0;
+ uintptr_t saved_arg = 0;
+ mp_obj_t sock = self->sock;
+ if (sock == MP_OBJ_NULL || (request != MP_STREAM_CLOSE && self->last_error != 0)) {
+ // Closed or error socket:
+ return MP_STREAM_POLL_NVAL;
+ }
+
+ if (request == MP_STREAM_CLOSE) {
+ self->sock = MP_OBJ_NULL;
+ mbedtls_ssl_free(&self->ssl);
+ } else if (request == MP_STREAM_POLL) {
+ // If the library signaled us that it needs reading or writing, only check that direction,
+ // but save what the caller asked because we need to restore it later
+ if (self->poll_mask && (arg & MP_STREAM_POLL_RDWR)) {
+ saved_arg = arg & MP_STREAM_POLL_RDWR;
+ arg = (arg & ~saved_arg) | self->poll_mask;
+ }
+
+ // Take into account that the library might have buffered data already
+ int has_pending = 0;
+ if (arg & MP_STREAM_POLL_RD) {
+ has_pending = mbedtls_ssl_check_pending(&self->ssl);
+ if (has_pending) {
+ ret |= MP_STREAM_POLL_RD;
+ if (arg == MP_STREAM_POLL_RD) {
+ // Shortcut if we only need to read and we have buffered data, no need to go to the underlying socket
+ return MP_STREAM_POLL_RD;
+ }
+ }
+ }
+ }
+
+ // Pass all requests down to the underlying socket
+ ret |= mp_get_stream(sock)->ioctl(sock, request, arg, errcode);
+
+ if (request == MP_STREAM_POLL) {
+ // The direction the library needed is available, return a fake result to the caller so that
+ // it reenters a read or a write to allow the handshake to progress
+ if (ret & self->poll_mask) {
+ ret |= saved_arg;
+ }
+ }
+ return ret;
+}
+
+STATIC const mp_rom_map_elem_t ssl_socket_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+ #if MICROPY_PY_SSL_FINALISER
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
+ #endif
+ #if MICROPY_UNIX_COVERAGE
+ { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
+ #endif
+ { MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(ssl_socket_locals_dict, ssl_socket_locals_dict_table);
+
+STATIC const mp_stream_p_t ssl_socket_stream_p = {
+ .read = socket_read,
+ .write = socket_write,
+ .ioctl = socket_ioctl,
+};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ssl_socket_type,
+ MP_QSTR_SSLSocket,
+ MP_TYPE_FLAG_NONE,
+ protocol, &ssl_socket_stream_p,
+ locals_dict, &ssl_socket_locals_dict
+ );
+
+/******************************************************************************/
+// ssl module.
+
+STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum {
+ ARG_key,
+ ARG_cert,
+ ARG_server_side,
+ ARG_server_hostname,
+ ARG_cert_reqs,
+ ARG_cadata,
+ ARG_do_handshake,
+ };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MBEDTLS_SSL_VERIFY_NONE}},
+ { MP_QSTR_cadata, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ };
+
+ // Parse arguments.
+ mp_obj_t sock = 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);
+
+ // Create SSLContext.
+ mp_int_t protocol = args[ARG_server_side].u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT;
+ mp_obj_t ssl_context_args[1] = { MP_OBJ_NEW_SMALL_INT(protocol) };
+ mp_obj_ssl_context_t *ssl_context = MP_OBJ_TO_PTR(ssl_context_make_new(&ssl_context_type, 1, 0, ssl_context_args));
+
+ // Load key and cert if given.
+ if (args[ARG_key].u_obj != mp_const_none) {
+ ssl_context_load_key(ssl_context, args[ARG_key].u_obj, args[ARG_cert].u_obj);
+ }
+
+ // Set the verify_mode.
+ mp_obj_t dest[2] = { MP_OBJ_SENTINEL, MP_OBJ_NEW_SMALL_INT(args[ARG_cert_reqs].u_int) };
+ ssl_context_attr(MP_OBJ_FROM_PTR(ssl_context), MP_QSTR_verify_mode, dest);
+
+ // Load cadata if given.
+ if (args[ARG_cadata].u_obj != mp_const_none) {
+ ssl_context_load_cadata(ssl_context, args[ARG_cadata].u_obj);
+ }
+
+ // Create and return the new SSLSocket object.
+ return ssl_socket_make_new(ssl_context, sock, args[ARG_server_side].u_bool,
+ args[ARG_do_handshake].u_bool, args[ARG_server_hostname].u_obj);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
+
+STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ssl) },
+
+ // Functions.
+ { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
+
+ // Classes.
+ { MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_context_type) },
+
+ // Constants.
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(MBEDTLS_SSL_IS_CLIENT) },
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(MBEDTLS_SSL_IS_SERVER) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(MBEDTLS_SSL_VERIFY_NONE) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(MBEDTLS_SSL_VERIFY_OPTIONAL) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(MBEDTLS_SSL_VERIFY_REQUIRED) },
+};
+STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
+
+const mp_obj_module_t mp_module_ssl = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_ssl, mp_module_ssl);
+
+#endif // MICROPY_PY_SSL && MICROPY_SSL_MBEDTLS
diff --git a/extmod/modtime.c b/extmod/modtime.c
new file mode 100644
index 0000000000000..805c2621c0b67
--- /dev/null
+++ b/extmod/modtime.c
@@ -0,0 +1,236 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2023 Damien P. George
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * 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/mphal.h"
+#include "py/runtime.h"
+#include "py/smallint.h"
+#include "extmod/modtime.h"
+
+#if MICROPY_PY_TIME
+
+#ifdef MICROPY_PY_TIME_INCLUDEFILE
+#include MICROPY_PY_TIME_INCLUDEFILE
+#endif
+
+#if MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME
+
+#include "shared/timeutils/timeutils.h"
+
+// localtime([secs])
+// Convert a time expressed in seconds since the Epoch into an 8-tuple which
+// contains: (year, month, mday, hour, minute, second, weekday, yearday)
+// If secs is not provided or None, then the current time is used.
+// - year is the full year, eg 2000
+// - month is 1-12
+// - mday is 1-31
+// - hour is 0-23
+// - minute is 0-59
+// - second is 0-59
+// - weekday is 0-6 for Mon-Sun
+// - yearday is 1-366
+STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0 || args[0] == mp_const_none) {
+ // Get current date and time.
+ return mp_time_localtime_get();
+ } else {
+ // Convert given seconds to tuple.
+ mp_int_t seconds = mp_obj_get_int(args[0]);
+ timeutils_struct_time_t tm;
+ timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
+ mp_obj_t tuple[8] = {
+ tuple[0] = mp_obj_new_int(tm.tm_year),
+ tuple[1] = mp_obj_new_int(tm.tm_mon),
+ tuple[2] = mp_obj_new_int(tm.tm_mday),
+ tuple[3] = mp_obj_new_int(tm.tm_hour),
+ tuple[4] = mp_obj_new_int(tm.tm_min),
+ tuple[5] = mp_obj_new_int(tm.tm_sec),
+ tuple[6] = mp_obj_new_int(tm.tm_wday),
+ tuple[7] = mp_obj_new_int(tm.tm_yday),
+ };
+ return mp_obj_new_tuple(8, tuple);
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_time_localtime_obj, 0, 1, time_localtime);
+
+// mktime()
+// This is the inverse function of localtime. Its argument is a full 8-tuple
+// which expresses a time as per localtime. It returns an integer which is
+// the number of seconds since the Epoch (eg 1st Jan 1970, or 1st Jan 2000).
+STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
+ size_t len;
+ mp_obj_t *elem;
+ mp_obj_get_array(tuple, &len, &elem);
+
+ // localtime generates a tuple of len 8. CPython uses 9, so we accept both.
+ if (len < 8 || len > 9) {
+ mp_raise_TypeError(MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9"));
+ }
+
+ return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
+ mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
+ mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_time_mktime_obj, time_mktime);
+
+#endif // MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME
+
+#if MICROPY_PY_TIME_TIME_TIME_NS
+
+// time()
+// Return the number of seconds since the Epoch.
+STATIC mp_obj_t time_time(void) {
+ return mp_time_time_get();
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_time_time_obj, time_time);
+
+// time_ns()
+// Returns the number of nanoseconds since the Epoch, as an integer.
+STATIC mp_obj_t time_time_ns(void) {
+ return mp_obj_new_int_from_ull(mp_hal_time_ns());
+}
+MP_DEFINE_CONST_FUN_OBJ_0(mp_time_time_ns_obj, time_time_ns);
+
+#endif // MICROPY_PY_TIME_TIME_TIME_NS
+
+STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
+ #ifdef MICROPY_PY_TIME_CUSTOM_SLEEP
+ mp_time_sleep(seconds_o);
+ #else
+ #if MICROPY_PY_BUILTINS_FLOAT
+ mp_hal_delay_ms((mp_uint_t)(1000 * mp_obj_get_float(seconds_o)));
+ #else
+ mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
+ #endif
+ #endif
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_obj, time_sleep);
+
+STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
+ mp_int_t ms = mp_obj_get_int(arg);
+ if (ms >= 0) {
+ mp_hal_delay_ms(ms);
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_ms_obj, time_sleep_ms);
+
+STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
+ mp_int_t us = mp_obj_get_int(arg);
+ if (us > 0) {
+ mp_hal_delay_us(us);
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_us_obj, time_sleep_us);
+
+STATIC mp_obj_t time_ticks_ms(void) {
+ return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
+}
+MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_ms_obj, time_ticks_ms);
+
+STATIC mp_obj_t time_ticks_us(void) {
+ return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
+}
+MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_us_obj, time_ticks_us);
+
+STATIC mp_obj_t time_ticks_cpu(void) {
+ return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
+}
+MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_cpu_obj, time_ticks_cpu);
+
+STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) {
+ // we assume that the arguments come from ticks_xx so are small ints
+ mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
+ mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
+ // Optimized formula avoiding if conditions. We adjust difference "forward",
+ // wrap it around and adjust back.
+ mp_int_t diff = ((end - start + MICROPY_PY_TIME_TICKS_PERIOD / 2) & (MICROPY_PY_TIME_TICKS_PERIOD - 1))
+ - MICROPY_PY_TIME_TICKS_PERIOD / 2;
+ return MP_OBJ_NEW_SMALL_INT(diff);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_time_ticks_diff_obj, time_ticks_diff);
+
+STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {
+ // we assume that first argument come from ticks_xx so is small int
+ mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
+ mp_uint_t delta = mp_obj_get_int(delta_in);
+
+ // Check that delta does not overflow the range that ticks_diff can handle.
+ // This ensures the following:
+ // - ticks_diff(ticks_add(T, delta), T) == delta
+ // - ticks_diff(T, ticks_add(T, delta)) == -delta
+ // The latter requires excluding delta=-TICKS_PERIOD/2.
+ //
+ // This unsigned comparison is equivalent to a signed comparison of:
+ // delta <= -TICKS_PERIOD/2 || delta >= TICKS_PERIOD/2
+ if (delta + MICROPY_PY_TIME_TICKS_PERIOD / 2 - 1 >= MICROPY_PY_TIME_TICKS_PERIOD - 1) {
+ mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ticks interval overflow"));
+ }
+
+ return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_TIME_TICKS_PERIOD - 1));
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_time_ticks_add_obj, time_ticks_add);
+
+STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) },
+
+ #if MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME
+ { MP_ROM_QSTR(MP_QSTR_gmtime), MP_ROM_PTR(&mp_time_localtime_obj) },
+ { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mp_time_localtime_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&mp_time_mktime_obj) },
+ #endif
+
+ #if MICROPY_PY_TIME_TIME_TIME_NS
+ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_time_time_obj) },
+ { MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_time_time_ns_obj) },
+ #endif
+
+ { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_time_sleep_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_time_sleep_ms_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_time_sleep_us_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_time_ticks_ms_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_time_ticks_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_time_ticks_cpu_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_time_ticks_add_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_time_ticks_diff_obj) },
+
+ #ifdef MICROPY_PY_TIME_EXTRA_GLOBALS
+ MICROPY_PY_TIME_EXTRA_GLOBALS
+ #endif
+};
+STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table);
+
+const mp_obj_module_t mp_module_time = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_time_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_time, mp_module_time);
+
+#endif // MICROPY_PY_TIME
diff --git a/extmod/modtime.h b/extmod/modtime.h
new file mode 100644
index 0000000000000..f5ea6b55bf306
--- /dev/null
+++ b/extmod/modtime.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2016 Damien P. George
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * 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_EXTMOD_MODUTIME_H
+#define MICROPY_INCLUDED_EXTMOD_MODUTIME_H
+
+#include "py/obj.h"
+
+MP_DECLARE_CONST_FUN_OBJ_1(mp_time_mktime_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_time_sleep_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_time_sleep_ms_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_time_sleep_us_obj);
+MP_DECLARE_CONST_FUN_OBJ_0(mp_time_ticks_ms_obj);
+MP_DECLARE_CONST_FUN_OBJ_0(mp_time_ticks_us_obj);
+MP_DECLARE_CONST_FUN_OBJ_0(mp_time_ticks_cpu_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_time_ticks_diff_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_time_ticks_add_obj);
+MP_DECLARE_CONST_FUN_OBJ_0(mp_time_time_ns_obj);
+
+#endif // MICROPY_INCLUDED_EXTMOD_MODUTIME_H
diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c
deleted file mode 100644
index 6e3603fa18a47..0000000000000
--- a/extmod/moduasyncio.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2020 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 "py/runtime.h"
-#include "py/smallint.h"
-#include "py/pairheap.h"
-#include "py/mphal.h"
-
-#if MICROPY_PY_UASYNCIO
-
-// Used when task cannot be guaranteed to be non-NULL.
-#define TASK_PAIRHEAP(task) ((task) ? &(task)->pairheap : NULL)
-
-#define TASK_STATE_RUNNING_NOT_WAITED_ON (mp_const_true)
-#define TASK_STATE_DONE_NOT_WAITED_ON (mp_const_none)
-#define TASK_STATE_DONE_WAS_WAITED_ON (mp_const_false)
-
-#define TASK_IS_DONE(task) ( \
- (task)->state == TASK_STATE_DONE_NOT_WAITED_ON \
- || (task)->state == TASK_STATE_DONE_WAS_WAITED_ON)
-
-typedef struct _mp_obj_task_t {
- mp_pairheap_t pairheap;
- mp_obj_t coro;
- mp_obj_t data;
- mp_obj_t state;
- mp_obj_t ph_key;
-} mp_obj_task_t;
-
-typedef struct _mp_obj_task_queue_t {
- mp_obj_base_t base;
- mp_obj_task_t *heap;
-} mp_obj_task_queue_t;
-
-STATIC const mp_obj_type_t task_queue_type;
-STATIC const mp_obj_type_t task_type;
-
-STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
-
-/******************************************************************************/
-// Ticks for task ordering in pairing heap
-
-STATIC mp_obj_t ticks(void) {
- return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
-}
-
-STATIC mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) {
- mp_uint_t t0 = MP_OBJ_SMALL_INT_VALUE(t0_in);
- mp_uint_t t1 = MP_OBJ_SMALL_INT_VALUE(t1_in);
- mp_int_t diff = ((t1 - t0 + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
- - MICROPY_PY_UTIME_TICKS_PERIOD / 2;
- return diff;
-}
-
-STATIC int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
- mp_obj_task_t *t1 = (mp_obj_task_t *)n1;
- mp_obj_task_t *t2 = (mp_obj_task_t *)n2;
- return MP_OBJ_SMALL_INT_VALUE(ticks_diff(t1->ph_key, t2->ph_key)) < 0;
-}
-
-/******************************************************************************/
-// TaskQueue class
-
-STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- (void)args;
- mp_arg_check_num(n_args, n_kw, 0, 0, false);
- mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type);
- self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt);
- return MP_OBJ_FROM_PTR(self);
-}
-
-STATIC mp_obj_t task_queue_peek(mp_obj_t self_in) {
- mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->heap == NULL) {
- return mp_const_none;
- } else {
- return MP_OBJ_FROM_PTR(self->heap);
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek);
-
-STATIC mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) {
- mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_obj_task_t *task = MP_OBJ_TO_PTR(args[1]);
- task->data = mp_const_none;
- if (n_args == 2) {
- task->ph_key = ticks();
- } else {
- assert(mp_obj_is_small_int(args[2]));
- task->ph_key = args[2];
- }
- self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task));
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push);
-
-STATIC mp_obj_t task_queue_pop(mp_obj_t self_in) {
- mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_task_t *head = (mp_obj_task_t *)mp_pairheap_peek(task_lt, &self->heap->pairheap);
- if (head == NULL) {
- mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
- }
- self->heap = (mp_obj_task_t *)mp_pairheap_pop(task_lt, &self->heap->pairheap);
- return MP_OBJ_FROM_PTR(head);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_obj, task_queue_pop);
-
-STATIC mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) {
- mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_task_t *task = MP_OBJ_TO_PTR(task_in);
- self->heap = (mp_obj_task_t *)mp_pairheap_delete(task_lt, &self->heap->pairheap, &task->pairheap);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(task_queue_remove_obj, task_queue_remove);
-
-STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&task_queue_peek_obj) },
- { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&task_queue_push_obj) },
- { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&task_queue_pop_obj) },
- { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table);
-
-STATIC const mp_obj_type_t task_queue_type = {
- { &mp_type_type },
- .name = MP_QSTR_TaskQueue,
- .make_new = task_queue_make_new,
- .locals_dict = (mp_obj_dict_t *)&task_queue_locals_dict,
-};
-
-/******************************************************************************/
-// Task class
-
-// This is the core uasyncio context with cur_task, _task_queue and CancelledError.
-STATIC mp_obj_t uasyncio_context = MP_OBJ_NULL;
-
-STATIC mp_obj_t task_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, 1, 2, false);
- mp_obj_task_t *self = m_new_obj(mp_obj_task_t);
- self->pairheap.base.type = type;
- mp_pairheap_init_node(task_lt, &self->pairheap);
- self->coro = args[0];
- self->data = mp_const_none;
- self->state = TASK_STATE_RUNNING_NOT_WAITED_ON;
- self->ph_key = MP_OBJ_NEW_SMALL_INT(0);
- if (n_args == 2) {
- uasyncio_context = args[1];
- }
- return MP_OBJ_FROM_PTR(self);
-}
-
-STATIC mp_obj_t task_done(mp_obj_t self_in) {
- mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
- return mp_obj_new_bool(TASK_IS_DONE(self));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_done_obj, task_done);
-
-STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
- mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
- // Check if task is already finished.
- if (TASK_IS_DONE(self)) {
- return mp_const_false;
- }
- // Can't cancel self (not supported yet).
- mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
- if (self_in == cur_task) {
- mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't cancel self"));
- }
- // If Task waits on another task then forward the cancel to the one it's waiting on.
- while (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(self->data)), MP_OBJ_FROM_PTR(&task_type))) {
- self = MP_OBJ_TO_PTR(self->data);
- }
-
- mp_obj_t _task_queue = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR__task_queue));
-
- // Reschedule Task as a cancelled task.
- mp_obj_t dest[3];
- mp_load_method_maybe(self->data, MP_QSTR_remove, dest);
- if (dest[0] != MP_OBJ_NULL) {
- // Not on the main running queue, remove the task from the queue it's on.
- dest[2] = MP_OBJ_FROM_PTR(self);
- mp_call_method_n_kw(1, 0, dest);
- // _task_queue.push(self)
- dest[0] = _task_queue;
- dest[1] = MP_OBJ_FROM_PTR(self);
- task_queue_push(2, dest);
- } else if (ticks_diff(self->ph_key, ticks()) > 0) {
- // On the main running queue but scheduled in the future, so bring it forward to now.
- // _task_queue.remove(self)
- task_queue_remove(_task_queue, MP_OBJ_FROM_PTR(self));
- // _task_queue.push(self)
- dest[0] = _task_queue;
- dest[1] = MP_OBJ_FROM_PTR(self);
- task_queue_push(2, dest);
- }
-
- self->data = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError));
-
- return mp_const_true;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel);
-
-STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
- mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
- if (dest[0] == MP_OBJ_NULL) {
- // Load
- if (attr == MP_QSTR_coro) {
- dest[0] = self->coro;
- } else if (attr == MP_QSTR_data) {
- dest[0] = self->data;
- } else if (attr == MP_QSTR_state) {
- dest[0] = self->state;
- } else if (attr == MP_QSTR_done) {
- dest[0] = MP_OBJ_FROM_PTR(&task_done_obj);
- dest[1] = self_in;
- } else if (attr == MP_QSTR_cancel) {
- dest[0] = MP_OBJ_FROM_PTR(&task_cancel_obj);
- dest[1] = self_in;
- } else if (attr == MP_QSTR_ph_key) {
- dest[0] = self->ph_key;
- }
- } else if (dest[1] != MP_OBJ_NULL) {
- // Store
- if (attr == MP_QSTR_data) {
- self->data = dest[1];
- dest[0] = MP_OBJ_NULL;
- } else if (attr == MP_QSTR_state) {
- self->state = dest[1];
- dest[0] = MP_OBJ_NULL;
- }
- }
-}
-
-STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
- (void)iter_buf;
- mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
- if (TASK_IS_DONE(self)) {
- // Signal that the completed-task has been await'ed on.
- self->state = TASK_STATE_DONE_WAS_WAITED_ON;
- } else if (self->state == TASK_STATE_RUNNING_NOT_WAITED_ON) {
- // Allocate the waiting queue.
- self->state = task_queue_make_new(&task_queue_type, 0, 0, NULL);
- } else if (mp_obj_get_type(self->state) != &task_queue_type) {
- // Task has state used for another purpose, so can't also wait on it.
- mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't wait"));
- }
- return self_in;
-}
-
-STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
- mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
- if (TASK_IS_DONE(self)) {
- // Task finished, raise return value to caller so it can continue.
- nlr_raise(self->data);
- } else {
- // Put calling task on waiting queue.
- mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
- mp_obj_t args[2] = { self->state, cur_task };
- task_queue_push(2, args);
- // Set calling task's data to this task that it waits on, to double-link it.
- ((mp_obj_task_t *)MP_OBJ_TO_PTR(cur_task))->data = self_in;
- }
- return mp_const_none;
-}
-
-STATIC const mp_obj_type_t task_type = {
- { &mp_type_type },
- .name = MP_QSTR_Task,
- .make_new = task_make_new,
- .attr = task_attr,
- .getiter = task_getiter,
- .iternext = task_iternext,
-};
-
-/******************************************************************************/
-// C-level uasyncio module
-
-STATIC const mp_rom_map_elem_t mp_module_uasyncio_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__uasyncio) },
- { MP_ROM_QSTR(MP_QSTR_TaskQueue), MP_ROM_PTR(&task_queue_type) },
- { MP_ROM_QSTR(MP_QSTR_Task), MP_ROM_PTR(&task_type) },
-};
-STATIC MP_DEFINE_CONST_DICT(mp_module_uasyncio_globals, mp_module_uasyncio_globals_table);
-
-const mp_obj_module_t mp_module_uasyncio = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_uasyncio_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR__uasyncio, mp_module_uasyncio);
-
-#endif // MICROPY_PY_UASYNCIO
diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c
deleted file mode 100644
index c0e2c587fdd9d..0000000000000
--- a/extmod/modubinascii.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Paul Sokolovsky
- *
- * 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/runtime.h"
-#include "py/binary.h"
-
-#if MICROPY_PY_UBINASCII
-
-STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
- // First argument is the data to convert.
- // Second argument is an optional separator to be used between values.
- const char *sep = NULL;
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
-
- // Code below assumes non-zero buffer length when computing size with
- // separator, so handle the zero-length case here.
- if (bufinfo.len == 0) {
- return mp_const_empty_bytes;
- }
-
- vstr_t vstr;
- size_t out_len = bufinfo.len * 2;
- if (n_args > 1) {
- // 1-char separator between hex numbers
- out_len += bufinfo.len - 1;
- sep = mp_obj_str_get_str(args[1]);
- }
- vstr_init_len(&vstr, out_len);
- byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
- for (mp_uint_t i = bufinfo.len; i--;) {
- byte d = (*in >> 4);
- if (d > 9) {
- d += 'a' - '9' - 1;
- }
- *out++ = d + '0';
- d = (*in++ & 0xf);
- if (d > 9) {
- d += 'a' - '9' - 1;
- }
- *out++ = d + '0';
- if (sep != NULL && i != 0) {
- *out++ = *sep;
- }
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify);
-
-STATIC mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
-
- if ((bufinfo.len & 1) != 0) {
- mp_raise_ValueError(MP_ERROR_TEXT("odd-length string"));
- }
- vstr_t vstr;
- vstr_init_len(&vstr, bufinfo.len / 2);
- byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
- byte hex_byte = 0;
- for (mp_uint_t i = bufinfo.len; i--;) {
- byte hex_ch = *in++;
- if (unichar_isxdigit(hex_ch)) {
- hex_byte += unichar_xdigit_value(hex_ch);
- } else {
- mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit found"));
- }
- if (i & 1) {
- hex_byte <<= 4;
- } else {
- *out++ = hex_byte;
- hex_byte = 0;
- }
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify);
-
-// If ch is a character in the base64 alphabet, and is not a pad character, then
-// the corresponding integer between 0 and 63, inclusively, is returned.
-// Otherwise, -1 is returned.
-static int mod_binascii_sextet(byte ch) {
- if (ch >= 'A' && ch <= 'Z') {
- return ch - 'A';
- } else if (ch >= 'a' && ch <= 'z') {
- return ch - 'a' + 26;
- } else if (ch >= '0' && ch <= '9') {
- return ch - '0' + 52;
- } else if (ch == '+') {
- return 62;
- } else if (ch == '/') {
- return 63;
- } else {
- return -1;
- }
-}
-
-STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
- byte *in = bufinfo.buf;
-
- vstr_t vstr;
- vstr_init(&vstr, (bufinfo.len / 4) * 3 + 1); // Potentially over-allocate
- byte *out = (byte *)vstr.buf;
-
- uint shift = 0;
- int nbits = 0; // Number of meaningful bits in shift
- bool hadpad = false; // Had a pad character since last valid character
- for (size_t i = 0; i < bufinfo.len; i++) {
- if (in[i] == '=') {
- if ((nbits == 2) || ((nbits == 4) && hadpad)) {
- nbits = 0;
- break;
- }
- hadpad = true;
- }
-
- int sextet = mod_binascii_sextet(in[i]);
- if (sextet == -1) {
- continue;
- }
- hadpad = false;
- shift = (shift << 6) | sextet;
- nbits += 6;
-
- if (nbits >= 8) {
- nbits -= 8;
- out[vstr.len++] = (shift >> nbits) & 0xFF;
- }
- }
-
- if (nbits) {
- mp_raise_ValueError(MP_ERROR_TEXT("incorrect padding"));
- }
-
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
-
-STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_newline };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_newline, MP_ARG_BOOL, {.u_bool = true} },
- };
-
- 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);
- uint8_t newline = args[ARG_newline].u_bool;
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(pos_args[0], &bufinfo, MP_BUFFER_READ);
-
- vstr_t vstr;
- vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + newline);
-
- // First pass, we convert input buffer to numeric base 64 values
- byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
- mp_uint_t i;
- for (i = bufinfo.len; i >= 3; i -= 3) {
- *out++ = (in[0] & 0xFC) >> 2;
- *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4;
- *out++ = (in[1] & 0x0F) << 2 | (in[2] & 0xC0) >> 6;
- *out++ = in[2] & 0x3F;
- in += 3;
- }
- if (i != 0) {
- *out++ = (in[0] & 0xFC) >> 2;
- if (i == 2) {
- *out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4;
- *out++ = (in[1] & 0x0F) << 2;
- } else {
- *out++ = (in[0] & 0x03) << 4;
- *out++ = 64;
- }
- *out = 64;
- }
-
- // Second pass, we convert number base 64 values to actual base64 ascii encoding
- out = (byte *)vstr.buf;
- for (mp_uint_t j = vstr.len - newline; j--;) {
- if (*out < 26) {
- *out += 'A';
- } else if (*out < 52) {
- *out += 'a' - 26;
- } else if (*out < 62) {
- *out += '0' - 52;
- } else if (*out == 62) {
- *out = '+';
- } else if (*out == 63) {
- *out = '/';
- } else {
- *out = '=';
- }
- out++;
- }
- if (newline) {
- *out = '\n';
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64);
-
-#if MICROPY_PY_UBINASCII_CRC32
-#include "lib/uzlib/tinf.h"
-
-STATIC mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
- uint32_t crc = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 0;
- crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
- return mp_obj_new_int_from_uint(crc ^ 0xffffffff);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32);
-#endif
-
-STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) },
- { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&mod_binascii_hexlify_obj) },
- { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) },
- { MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },
- { MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) },
- #if MICROPY_PY_UBINASCII_CRC32
- { MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);
-
-const mp_obj_module_t mp_module_ubinascii = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_binascii_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_ubinascii, mp_module_ubinascii);
-
-#endif // MICROPY_PY_UBINASCII
diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c
deleted file mode 100644
index c58abaada67e0..0000000000000
--- a/extmod/moducryptolib.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2017-2018 Paul Sokolovsky
- * Copyright (c) 2018 Yonatan Goldschmidt
- *
- * 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_UCRYPTOLIB
-
-#include
-#include
-
-#include "py/runtime.h"
-
-// This module implements crypto ciphers API, roughly following
-// https://www.python.org/dev/peps/pep-0272/ . Exact implementation
-// of PEP 272 can be made with a simple wrapper which adds all the
-// needed boilerplate.
-
-// values follow PEP 272
-enum {
- UCRYPTOLIB_MODE_ECB = 1,
- UCRYPTOLIB_MODE_CBC = 2,
- UCRYPTOLIB_MODE_CTR = 6,
-};
-
-struct ctr_params {
- // counter is the IV of the AES context.
-
- size_t offset; // in encrypted_counter
- // encrypted counter
- uint8_t encrypted_counter[16];
-};
-
-#if MICROPY_SSL_AXTLS
-#include "lib/axtls/crypto/crypto.h"
-
-#define AES_CTX_IMPL AES_CTX
-#endif
-
-#if MICROPY_SSL_MBEDTLS
-#include
-
-// we can't run mbedtls AES key schedule until we know whether we're used for encrypt or decrypt.
-// therefore, we store the key & keysize and on the first call to encrypt/decrypt we override them
-// with the mbedtls_aes_context, as they are not longer required. (this is done to save space)
-struct mbedtls_aes_ctx_with_key {
- union {
- mbedtls_aes_context mbedtls_ctx;
- struct {
- uint8_t key[32];
- uint8_t keysize;
- } init_data;
- } u;
- unsigned char iv[16];
-};
-#define AES_CTX_IMPL struct mbedtls_aes_ctx_with_key
-#endif
-
-typedef struct _mp_obj_aes_t {
- mp_obj_base_t base;
- AES_CTX_IMPL ctx;
- uint8_t block_mode : 6;
-#define AES_KEYTYPE_NONE 0
-#define AES_KEYTYPE_ENC 1
-#define AES_KEYTYPE_DEC 2
- uint8_t key_type : 2;
-} mp_obj_aes_t;
-
-static inline bool is_ctr_mode(int block_mode) {
- #if MICROPY_PY_UCRYPTOLIB_CTR
- return block_mode == UCRYPTOLIB_MODE_CTR;
- #else
- return false;
- #endif
-}
-
-static inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) {
- // ctr_params follows aes object struct
- return (struct ctr_params *)&o[1];
-}
-
-#if MICROPY_SSL_AXTLS
-STATIC void aes_initial_set_key_impl(AES_CTX_IMPL *ctx, const uint8_t *key, size_t keysize, const uint8_t iv[16]) {
- assert(16 == keysize || 32 == keysize);
- AES_set_key(ctx, key, iv, (16 == keysize) ? AES_MODE_128 : AES_MODE_256);
-}
-
-STATIC void aes_final_set_key_impl(AES_CTX_IMPL *ctx, bool encrypt) {
- if (!encrypt) {
- AES_convert_key(ctx);
- }
-}
-
-STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_t out[16], bool encrypt) {
- memcpy(out, in, 16);
- // We assume that out (vstr.buf or given output buffer) is uint32_t aligned
- uint32_t *p = (uint32_t *)out;
- // axTLS likes it weird and complicated with byteswaps
- for (int i = 0; i < 4; i++) {
- p[i] = MP_HTOBE32(p[i]);
- }
- if (encrypt) {
- AES_encrypt(ctx, p);
- } else {
- AES_decrypt(ctx, p);
- }
- for (int i = 0; i < 4; i++) {
- p[i] = MP_BE32TOH(p[i]);
- }
-}
-
-STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, bool encrypt) {
- if (encrypt) {
- AES_cbc_encrypt(ctx, in, out, in_len);
- } else {
- AES_cbc_decrypt(ctx, in, out, in_len);
- }
-}
-
-#if MICROPY_PY_UCRYPTOLIB_CTR
-// axTLS doesn't have CTR support out of the box. This implements the counter part using the ECB primitive.
-STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) {
- size_t n = ctr_params->offset;
- uint8_t *const counter = ctx->iv;
-
- while (in_len--) {
- if (n == 0) {
- aes_process_ecb_impl(ctx, counter, ctr_params->encrypted_counter, true);
-
- // increment the 128-bit counter
- for (int i = 15; i >= 0; --i) {
- if (++counter[i] != 0) {
- break;
- }
- }
- }
-
- *out++ = *in++ ^ ctr_params->encrypted_counter[n];
- n = (n + 1) & 0xf;
- }
-
- ctr_params->offset = n;
-}
-#endif
-
-#endif
-
-#if MICROPY_SSL_MBEDTLS
-STATIC void aes_initial_set_key_impl(AES_CTX_IMPL *ctx, const uint8_t *key, size_t keysize, const uint8_t iv[16]) {
- ctx->u.init_data.keysize = keysize;
- memcpy(ctx->u.init_data.key, key, keysize);
-
- if (NULL != iv) {
- memcpy(ctx->iv, iv, sizeof(ctx->iv));
- }
-}
-
-STATIC void aes_final_set_key_impl(AES_CTX_IMPL *ctx, bool encrypt) {
- // first, copy key aside
- uint8_t key[32];
- uint8_t keysize = ctx->u.init_data.keysize;
- memcpy(key, ctx->u.init_data.key, keysize);
- // now, override key with the mbedtls context object
- mbedtls_aes_init(&ctx->u.mbedtls_ctx);
-
- // setkey call will succeed, we've already checked the keysize earlier.
- assert(16 == keysize || 32 == keysize);
- if (encrypt) {
- mbedtls_aes_setkey_enc(&ctx->u.mbedtls_ctx, key, keysize * 8);
- } else {
- mbedtls_aes_setkey_dec(&ctx->u.mbedtls_ctx, key, keysize * 8);
- }
-}
-
-STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_t out[16], bool encrypt) {
- mbedtls_aes_crypt_ecb(&ctx->u.mbedtls_ctx, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, in, out);
-}
-
-STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, bool encrypt) {
- mbedtls_aes_crypt_cbc(&ctx->u.mbedtls_ctx, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, in_len, ctx->iv, in, out);
-}
-
-#if MICROPY_PY_UCRYPTOLIB_CTR
-STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) {
- mbedtls_aes_crypt_ctr(&ctx->u.mbedtls_ctx, in_len, &ctr_params->offset, ctx->iv, ctr_params->encrypted_counter, in, out);
-}
-#endif
-
-#endif
-
-STATIC mp_obj_t ucryptolib_aes_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, 2, 3, false);
-
- const mp_int_t block_mode = mp_obj_get_int(args[1]);
-
- switch (block_mode) {
- case UCRYPTOLIB_MODE_ECB:
- case UCRYPTOLIB_MODE_CBC:
- #if MICROPY_PY_UCRYPTOLIB_CTR
- case UCRYPTOLIB_MODE_CTR:
- #endif
- break;
-
- default:
- mp_raise_ValueError(MP_ERROR_TEXT("mode"));
- }
-
- mp_obj_aes_t *o = mp_obj_malloc_var(mp_obj_aes_t, struct ctr_params, !!is_ctr_mode(block_mode), type);
-
- o->block_mode = block_mode;
- o->key_type = AES_KEYTYPE_NONE;
-
- mp_buffer_info_t keyinfo;
- mp_get_buffer_raise(args[0], &keyinfo, MP_BUFFER_READ);
- if (32 != keyinfo.len && 16 != keyinfo.len) {
- mp_raise_ValueError(MP_ERROR_TEXT("key"));
- }
-
- mp_buffer_info_t ivinfo;
- ivinfo.buf = NULL;
- if (n_args > 2 && args[2] != mp_const_none) {
- mp_get_buffer_raise(args[2], &ivinfo, MP_BUFFER_READ);
-
- if (16 != ivinfo.len) {
- mp_raise_ValueError(MP_ERROR_TEXT("IV"));
- }
- } else if (o->block_mode == UCRYPTOLIB_MODE_CBC || is_ctr_mode(o->block_mode)) {
- mp_raise_ValueError(MP_ERROR_TEXT("IV"));
- }
-
- if (is_ctr_mode(block_mode)) {
- ctr_params_from_aes(o)->offset = 0;
- }
-
- aes_initial_set_key_impl(&o->ctx, keyinfo.buf, keyinfo.len, ivinfo.buf);
-
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
- mp_obj_aes_t *self = MP_OBJ_TO_PTR(args[0]);
-
- mp_obj_t in_buf = args[1];
- mp_obj_t out_buf = MP_OBJ_NULL;
- if (n_args > 2) {
- out_buf = args[2];
- }
-
- mp_buffer_info_t in_bufinfo;
- mp_get_buffer_raise(in_buf, &in_bufinfo, MP_BUFFER_READ);
-
- if (!is_ctr_mode(self->block_mode) && in_bufinfo.len % 16 != 0) {
- mp_raise_ValueError(MP_ERROR_TEXT("blksize % 16"));
- }
-
- vstr_t vstr;
- mp_buffer_info_t out_bufinfo;
- uint8_t *out_buf_ptr;
-
- if (out_buf != MP_OBJ_NULL) {
- mp_get_buffer_raise(out_buf, &out_bufinfo, MP_BUFFER_WRITE);
- if (out_bufinfo.len < in_bufinfo.len) {
- mp_raise_ValueError(MP_ERROR_TEXT("output too small"));
- }
- out_buf_ptr = out_bufinfo.buf;
- } else {
- vstr_init_len(&vstr, in_bufinfo.len);
- out_buf_ptr = (uint8_t *)vstr.buf;
- }
-
- if (AES_KEYTYPE_NONE == self->key_type) {
- // always set key for encryption if CTR mode.
- const bool encrypt_mode = encrypt || is_ctr_mode(self->block_mode);
- aes_final_set_key_impl(&self->ctx, encrypt_mode);
- self->key_type = encrypt ? AES_KEYTYPE_ENC : AES_KEYTYPE_DEC;
- } else {
- if ((encrypt && self->key_type == AES_KEYTYPE_DEC) ||
- (!encrypt && self->key_type == AES_KEYTYPE_ENC)) {
-
- mp_raise_ValueError(MP_ERROR_TEXT("can't encrypt & decrypt"));
- }
- }
-
- switch (self->block_mode) {
- case UCRYPTOLIB_MODE_ECB: {
- uint8_t *in = in_bufinfo.buf, *out = out_buf_ptr;
- uint8_t *top = in + in_bufinfo.len;
- for (; in < top; in += 16, out += 16) {
- aes_process_ecb_impl(&self->ctx, in, out, encrypt);
- }
- break;
- }
-
- case UCRYPTOLIB_MODE_CBC:
- aes_process_cbc_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len, encrypt);
- break;
-
- #if MICROPY_PY_UCRYPTOLIB_CTR
- case UCRYPTOLIB_MODE_CTR:
- aes_process_ctr_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len,
- ctr_params_from_aes(self));
- break;
- #endif
- }
-
- if (out_buf != MP_OBJ_NULL) {
- return out_buf;
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-
-STATIC mp_obj_t ucryptolib_aes_encrypt(size_t n_args, const mp_obj_t *args) {
- return aes_process(n_args, args, true);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ucryptolib_aes_encrypt_obj, 2, 3, ucryptolib_aes_encrypt);
-
-STATIC mp_obj_t ucryptolib_aes_decrypt(size_t n_args, const mp_obj_t *args) {
- return aes_process(n_args, args, false);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ucryptolib_aes_decrypt_obj, 2, 3, ucryptolib_aes_decrypt);
-
-STATIC const mp_rom_map_elem_t ucryptolib_aes_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&ucryptolib_aes_encrypt_obj) },
- { MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&ucryptolib_aes_decrypt_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(ucryptolib_aes_locals_dict, ucryptolib_aes_locals_dict_table);
-
-STATIC const mp_obj_type_t ucryptolib_aes_type = {
- { &mp_type_type },
- .name = MP_QSTR_aes,
- .make_new = ucryptolib_aes_make_new,
- .locals_dict = (void *)&ucryptolib_aes_locals_dict,
-};
-
-STATIC const mp_rom_map_elem_t mp_module_ucryptolib_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucryptolib) },
- { MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&ucryptolib_aes_type) },
- #if MICROPY_PY_UCRYPTOLIB_CONSTS
- { MP_ROM_QSTR(MP_QSTR_MODE_ECB), MP_ROM_INT(UCRYPTOLIB_MODE_ECB) },
- { MP_ROM_QSTR(MP_QSTR_MODE_CBC), MP_ROM_INT(UCRYPTOLIB_MODE_CBC) },
- #if MICROPY_PY_UCRYPTOLIB_CTR
- { MP_ROM_QSTR(MP_QSTR_MODE_CTR), MP_ROM_INT(UCRYPTOLIB_MODE_CTR) },
- #endif
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_ucryptolib_globals, mp_module_ucryptolib_globals_table);
-
-const mp_obj_module_t mp_module_ucryptolib = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_ucryptolib_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_ucryptolib, mp_module_ucryptolib);
-
-#endif // MICROPY_PY_UCRYPTOLIB
diff --git a/extmod/moductypes.c b/extmod/moductypes.c
index 547453c48e9fd..63be621fbcbeb 100644
--- a/extmod/moductypes.c
+++ b/extmod/moductypes.c
@@ -582,7 +582,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
- case MP_UNARY_OP_INT:
+ case MP_UNARY_OP_INT_MAYBE:
if (mp_obj_is_type(self->desc, &mp_type_tuple)) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
@@ -634,16 +634,17 @@ STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
-STATIC const mp_obj_type_t uctypes_struct_type = {
- { &mp_type_type },
- .name = MP_QSTR_struct,
- .print = uctypes_struct_print,
- .make_new = uctypes_struct_make_new,
- .attr = uctypes_struct_attr,
- .subscr = uctypes_struct_subscr,
- .unary_op = uctypes_struct_unary_op,
- .buffer_p = { .get_buffer = uctypes_get_buffer },
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ uctypes_struct_type,
+ MP_QSTR_struct,
+ MP_TYPE_FLAG_NONE,
+ make_new, uctypes_struct_make_new,
+ print, uctypes_struct_print,
+ attr, uctypes_struct_attr,
+ subscr, uctypes_struct_subscr,
+ unary_op, uctypes_struct_unary_op,
+ buffer, uctypes_get_buffer
+ );
STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uctypes) },
@@ -717,6 +718,8 @@ const mp_obj_module_t mp_module_uctypes = {
.globals = (mp_obj_dict_t *)&mp_module_uctypes_globals,
};
+// uctypes is not a Python standard library module (hence "uctypes"
+// not "ctypes") and therefore shouldn't be extensible.
MP_REGISTER_MODULE(MP_QSTR_uctypes, mp_module_uctypes);
#endif
diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c
deleted file mode 100644
index 39488788f2712..0000000000000
--- a/extmod/moduhashlib.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Paul Sokolovsky
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-#include "py/runtime.h"
-
-#if MICROPY_PY_UHASHLIB
-
-#if MICROPY_SSL_MBEDTLS
-#include "mbedtls/version.h"
-#endif
-
-#if MICROPY_PY_UHASHLIB_SHA256
-
-#if MICROPY_SSL_MBEDTLS
-#include "mbedtls/sha256.h"
-#else
-#include "lib/crypto-algorithms/sha256.h"
-#endif
-
-#endif
-
-#if MICROPY_PY_UHASHLIB_SHA1 || MICROPY_PY_UHASHLIB_MD5
-
-#if MICROPY_SSL_AXTLS
-#include "lib/axtls/crypto/crypto.h"
-#endif
-
-#if MICROPY_SSL_MBEDTLS
-#include "mbedtls/md5.h"
-#include "mbedtls/sha1.h"
-#endif
-
-#endif
-
-typedef struct _mp_obj_hash_t {
- mp_obj_base_t base;
- bool final; // if set, update and digest raise an exception
- uintptr_t state[0]; // must be aligned to a machine word
-} mp_obj_hash_t;
-
-static void uhashlib_ensure_not_final(mp_obj_hash_t *self) {
- if (self->final) {
- mp_raise_ValueError(MP_ERROR_TEXT("hash is final"));
- }
-}
-
-#if MICROPY_PY_UHASHLIB_SHA256
-STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
-
-#if MICROPY_SSL_MBEDTLS
-
-#if MBEDTLS_VERSION_NUMBER < 0x02070000
-#define mbedtls_sha256_starts_ret mbedtls_sha256_starts
-#define mbedtls_sha256_update_ret mbedtls_sha256_update
-#define mbedtls_sha256_finish_ret mbedtls_sha256_finish
-#endif
-
-STATIC mp_obj_t uhashlib_sha256_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, 1, false);
- mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context), type);
- o->final = false;
- mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
- mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
- if (n_args == 1) {
- uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
- }
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- mbedtls_sha256_update_ret((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
- return mp_const_none;
-}
-
-STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- self->final = true;
- vstr_t vstr;
- vstr_init_len(&vstr, 32);
- mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-
-#else
-
-#include "lib/crypto-algorithms/sha256.c"
-
-STATIC mp_obj_t uhashlib_sha256_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, 1, false);
- mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX), type);
- o->final = false;
- sha256_init((CRYAL_SHA256_CTX *)o->state);
- if (n_args == 1) {
- uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
- }
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- sha256_update((CRYAL_SHA256_CTX *)self->state, bufinfo.buf, bufinfo.len);
- return mp_const_none;
-}
-
-STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- self->final = true;
- vstr_t vstr;
- vstr_init_len(&vstr, SHA256_BLOCK_SIZE);
- sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-#endif
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_sha256_update_obj, uhashlib_sha256_update);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_sha256_digest_obj, uhashlib_sha256_digest);
-
-STATIC const mp_rom_map_elem_t uhashlib_sha256_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_sha256_update_obj) },
- { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_sha256_digest_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(uhashlib_sha256_locals_dict, uhashlib_sha256_locals_dict_table);
-
-STATIC const mp_obj_type_t uhashlib_sha256_type = {
- { &mp_type_type },
- .name = MP_QSTR_sha256,
- .make_new = uhashlib_sha256_make_new,
- .locals_dict = (void *)&uhashlib_sha256_locals_dict,
-};
-#endif
-
-#if MICROPY_PY_UHASHLIB_SHA1
-STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg);
-
-#if MICROPY_SSL_AXTLS
-STATIC mp_obj_t uhashlib_sha1_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, 1, false);
- mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(SHA1_CTX), type);
- o->final = false;
- SHA1_Init((SHA1_CTX *)o->state);
- if (n_args == 1) {
- uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
- }
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- SHA1_Update((SHA1_CTX *)self->state, bufinfo.buf, bufinfo.len);
- return mp_const_none;
-}
-
-STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- self->final = true;
- vstr_t vstr;
- vstr_init_len(&vstr, SHA1_SIZE);
- SHA1_Final((byte *)vstr.buf, (SHA1_CTX *)self->state);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-#endif
-
-#if MICROPY_SSL_MBEDTLS
-
-#if MBEDTLS_VERSION_NUMBER < 0x02070000
-#define mbedtls_sha1_starts_ret mbedtls_sha1_starts
-#define mbedtls_sha1_update_ret mbedtls_sha1_update
-#define mbedtls_sha1_finish_ret mbedtls_sha1_finish
-#endif
-
-STATIC mp_obj_t uhashlib_sha1_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, 1, false);
- mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context), type);
- o->final = false;
- mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
- mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
- if (n_args == 1) {
- uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
- }
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- mbedtls_sha1_update_ret((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
- return mp_const_none;
-}
-
-STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- self->final = true;
- vstr_t vstr;
- vstr_init_len(&vstr, 20);
- mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
- mbedtls_sha1_free((mbedtls_sha1_context *)self->state);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-#endif
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_sha1_update_obj, uhashlib_sha1_update);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_sha1_digest_obj, uhashlib_sha1_digest);
-
-STATIC const mp_rom_map_elem_t uhashlib_sha1_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_sha1_update_obj) },
- { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_sha1_digest_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(uhashlib_sha1_locals_dict, uhashlib_sha1_locals_dict_table);
-
-STATIC const mp_obj_type_t uhashlib_sha1_type = {
- { &mp_type_type },
- .name = MP_QSTR_sha1,
- .make_new = uhashlib_sha1_make_new,
- .locals_dict = (void *)&uhashlib_sha1_locals_dict,
-};
-#endif
-
-#if MICROPY_PY_UHASHLIB_MD5
-STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
-
-#if MICROPY_SSL_AXTLS
-STATIC mp_obj_t uhashlib_md5_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, 1, false);
- mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(MD5_CTX), type);
- o->final = false;
- MD5_Init((MD5_CTX *)o->state);
- if (n_args == 1) {
- uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
- }
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- MD5_Update((MD5_CTX *)self->state, bufinfo.buf, bufinfo.len);
- return mp_const_none;
-}
-
-STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- self->final = true;
- vstr_t vstr;
- vstr_init_len(&vstr, MD5_SIZE);
- MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-#endif // MICROPY_SSL_AXTLS
-
-#if MICROPY_SSL_MBEDTLS
-
-#if MBEDTLS_VERSION_NUMBER < 0x02070000
-#define mbedtls_md5_starts_ret mbedtls_md5_starts
-#define mbedtls_md5_update_ret mbedtls_md5_update
-#define mbedtls_md5_finish_ret mbedtls_md5_finish
-#endif
-
-STATIC mp_obj_t uhashlib_md5_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, 1, false);
- mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context), type);
- o->final = false;
- mbedtls_md5_init((mbedtls_md5_context *)o->state);
- mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
- if (n_args == 1) {
- uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
- }
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- mbedtls_md5_update_ret((mbedtls_md5_context *)self->state, bufinfo.buf, bufinfo.len);
- return mp_const_none;
-}
-
-STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
- mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
- uhashlib_ensure_not_final(self);
- self->final = true;
- vstr_t vstr;
- vstr_init_len(&vstr, 16);
- mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf);
- mbedtls_md5_free((mbedtls_md5_context *)self->state);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-#endif // MICROPY_SSL_MBEDTLS
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(uhashlib_md5_update_obj, uhashlib_md5_update);
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(uhashlib_md5_digest_obj, uhashlib_md5_digest);
-
-STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&uhashlib_md5_update_obj) },
- { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&uhashlib_md5_digest_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table);
-
-STATIC const mp_obj_type_t uhashlib_md5_type = {
- { &mp_type_type },
- .name = MP_QSTR_md5,
- .make_new = uhashlib_md5_make_new,
- .locals_dict = (void *)&uhashlib_md5_locals_dict,
-};
-#endif // MICROPY_PY_UHASHLIB_MD5
-
-STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) },
- #if MICROPY_PY_UHASHLIB_SHA256
- { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&uhashlib_sha256_type) },
- #endif
- #if MICROPY_PY_UHASHLIB_SHA1
- { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&uhashlib_sha1_type) },
- #endif
- #if MICROPY_PY_UHASHLIB_MD5
- { MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&uhashlib_md5_type) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_uhashlib_globals, mp_module_uhashlib_globals_table);
-
-const mp_obj_module_t mp_module_uhashlib = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_uhashlib_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_uhashlib, mp_module_uhashlib);
-
-#endif // MICROPY_PY_UHASHLIB
diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c
deleted file mode 100644
index bfa6ba608d33f..0000000000000
--- a/extmod/moduheapq.c
+++ /dev/null
@@ -1,124 +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 "py/objlist.h"
-#include "py/runtime.h"
-
-#if MICROPY_PY_UHEAPQ
-
-// the algorithm here is modelled on CPython's heapq.py
-
-STATIC mp_obj_list_t *uheapq_get_heap(mp_obj_t heap_in) {
- if (!mp_obj_is_type(heap_in, &mp_type_list)) {
- mp_raise_TypeError(MP_ERROR_TEXT("heap must be a list"));
- }
- return MP_OBJ_TO_PTR(heap_in);
-}
-
-STATIC void uheapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
- mp_obj_t item = heap->items[pos];
- while (pos > start_pos) {
- mp_uint_t parent_pos = (pos - 1) >> 1;
- mp_obj_t parent = heap->items[parent_pos];
- if (mp_binary_op(MP_BINARY_OP_LESS, item, parent) == mp_const_true) {
- heap->items[pos] = parent;
- pos = parent_pos;
- } else {
- break;
- }
- }
- heap->items[pos] = item;
-}
-
-STATIC void uheapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
- mp_uint_t start_pos = pos;
- mp_uint_t end_pos = heap->len;
- mp_obj_t item = heap->items[pos];
- for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) {
- // choose right child if it's <= left child
- if (child_pos + 1 < end_pos && mp_binary_op(MP_BINARY_OP_LESS, heap->items[child_pos], heap->items[child_pos + 1]) == mp_const_false) {
- child_pos += 1;
- }
- // bubble up the smaller child
- heap->items[pos] = heap->items[child_pos];
- pos = child_pos;
- }
- heap->items[pos] = item;
- uheapq_heap_siftdown(heap, start_pos, pos);
-}
-
-STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
- mp_obj_list_t *heap = uheapq_get_heap(heap_in);
- mp_obj_list_append(heap_in, item);
- uheapq_heap_siftdown(heap, 0, heap->len - 1);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush);
-
-STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) {
- mp_obj_list_t *heap = uheapq_get_heap(heap_in);
- if (heap->len == 0) {
- mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
- }
- mp_obj_t item = heap->items[0];
- heap->len -= 1;
- heap->items[0] = heap->items[heap->len];
- heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer
- if (heap->len) {
- uheapq_heap_siftup(heap, 0);
- }
- return item;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop);
-
-STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) {
- mp_obj_list_t *heap = uheapq_get_heap(heap_in);
- for (mp_uint_t i = heap->len / 2; i > 0;) {
- uheapq_heap_siftup(heap, --i);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heapify_obj, mod_uheapq_heapify);
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_rom_map_elem_t mp_module_uheapq_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uheapq) },
- { MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_uheapq_heappush_obj) },
- { MP_ROM_QSTR(MP_QSTR_heappop), MP_ROM_PTR(&mod_uheapq_heappop_obj) },
- { MP_ROM_QSTR(MP_QSTR_heapify), MP_ROM_PTR(&mod_uheapq_heapify_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_uheapq_globals, mp_module_uheapq_globals_table);
-
-const mp_obj_module_t mp_module_uheapq = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_uheapq_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_uheapq, mp_module_uheapq);
-#endif
-
-#endif // MICROPY_PY_UHEAPQ
diff --git a/extmod/modujson.c b/extmod/modujson.c
deleted file mode 100644
index 9a73e4501e7c0..0000000000000
--- a/extmod/modujson.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014-2019 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-
-#include "py/objlist.h"
-#include "py/objstringio.h"
-#include "py/parsenum.h"
-#include "py/runtime.h"
-#include "py/stream.h"
-
-#if MICROPY_PY_UJSON
-
-#if MICROPY_PY_UJSON_SEPARATORS
-
-enum {
- DUMP_MODE_TO_STRING = 1,
- DUMP_MODE_TO_STREAM = 2,
-};
-
-STATIC mp_obj_t mod_ujson_dump_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, unsigned int mode) {
- enum { ARG_separators };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_separators, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- };
-
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args - mode, pos_args + mode, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- mp_print_ext_t print_ext;
-
- if (args[ARG_separators].u_obj == mp_const_none) {
- print_ext.item_separator = ", ";
- print_ext.key_separator = ": ";
- } else {
- mp_obj_t *items;
- mp_obj_get_array_fixed_n(args[ARG_separators].u_obj, 2, &items);
- print_ext.item_separator = mp_obj_str_get_str(items[0]);
- print_ext.key_separator = mp_obj_str_get_str(items[1]);
- }
-
- if (mode == DUMP_MODE_TO_STRING) {
- // dumps(obj)
- vstr_t vstr;
- vstr_init_print(&vstr, 8, &print_ext.base);
- mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON);
- return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
- } else {
- // dump(obj, stream)
- print_ext.base.data = MP_OBJ_TO_PTR(pos_args[1]);
- print_ext.base.print_strn = mp_stream_write_adaptor;
- mp_get_stream_raise(pos_args[1], MP_STREAM_OP_WRITE);
- mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON);
- return mp_const_none;
- }
-}
-
-STATIC mp_obj_t mod_ujson_dump(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- return mod_ujson_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STREAM);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ujson_dump_obj, 2, mod_ujson_dump);
-
-STATIC mp_obj_t mod_ujson_dumps(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- return mod_ujson_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STRING);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ujson_dumps_obj, 1, mod_ujson_dumps);
-
-#else
-
-STATIC mp_obj_t mod_ujson_dump(mp_obj_t obj, mp_obj_t stream) {
- mp_get_stream_raise(stream, MP_STREAM_OP_WRITE);
- mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor};
- mp_obj_print_helper(&print, obj, PRINT_JSON);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ujson_dump_obj, mod_ujson_dump);
-
-STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
- vstr_t vstr;
- mp_print_t print;
- vstr_init_print(&vstr, 8, &print);
- mp_obj_print_helper(&print, obj, PRINT_JSON);
- return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
-
-#endif
-
-// The function below implements a simple non-recursive JSON parser.
-//
-// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
-// The parser here will parse any valid JSON and return the correct
-// corresponding Python object. It allows through a superset of JSON, since
-// it treats commas and colons as "whitespace", and doesn't care if
-// brackets/braces are correctly paired. It will raise a ValueError if the
-// input is outside it's specs.
-//
-// Most of the work is parsing the primitives (null, false, true, numbers,
-// strings). It does 1 pass over the input stream. It tries to be fast and
-// small in code size, while not using more RAM than necessary.
-
-typedef struct _ujson_stream_t {
- mp_obj_t stream_obj;
- mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
- int errcode;
- byte cur;
-} ujson_stream_t;
-
-#define S_EOF (0) // null is not allowed in json stream so is ok as EOF marker
-#define S_END(s) ((s).cur == S_EOF)
-#define S_CUR(s) ((s).cur)
-#define S_NEXT(s) (ujson_stream_next(&(s)))
-
-STATIC byte ujson_stream_next(ujson_stream_t *s) {
- mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
- if (s->errcode != 0) {
- mp_raise_OSError(s->errcode);
- }
- if (ret == 0) {
- s->cur = S_EOF;
- }
- return s->cur;
-}
-
-STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
- const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ);
- ujson_stream_t s = {stream_obj, stream_p->read, 0, 0};
- vstr_t vstr;
- vstr_init(&vstr, 8);
- mp_obj_list_t stack; // we use a list as a simple stack for nested JSON
- stack.len = 0;
- stack.items = NULL;
- mp_obj_t stack_top = MP_OBJ_NULL;
- const mp_obj_type_t *stack_top_type = NULL;
- mp_obj_t stack_key = MP_OBJ_NULL;
- S_NEXT(s);
- for (;;) {
- cont:
- if (S_END(s)) {
- break;
- }
- mp_obj_t next = MP_OBJ_NULL;
- bool enter = false;
- byte cur = S_CUR(s);
- S_NEXT(s);
- switch (cur) {
- case ',':
- case ':':
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- goto cont;
- case 'n':
- if (S_CUR(s) == 'u' && S_NEXT(s) == 'l' && S_NEXT(s) == 'l') {
- S_NEXT(s);
- next = mp_const_none;
- } else {
- goto fail;
- }
- break;
- case 'f':
- if (S_CUR(s) == 'a' && S_NEXT(s) == 'l' && S_NEXT(s) == 's' && S_NEXT(s) == 'e') {
- S_NEXT(s);
- next = mp_const_false;
- } else {
- goto fail;
- }
- break;
- case 't':
- if (S_CUR(s) == 'r' && S_NEXT(s) == 'u' && S_NEXT(s) == 'e') {
- S_NEXT(s);
- next = mp_const_true;
- } else {
- goto fail;
- }
- break;
- case '"':
- vstr_reset(&vstr);
- for (; !S_END(s) && S_CUR(s) != '"';) {
- byte c = S_CUR(s);
- if (c == '\\') {
- c = S_NEXT(s);
- switch (c) {
- case 'b':
- c = 0x08;
- break;
- case 'f':
- c = 0x0c;
- break;
- case 'n':
- c = 0x0a;
- break;
- case 'r':
- c = 0x0d;
- break;
- case 't':
- c = 0x09;
- break;
- case 'u': {
- mp_uint_t num = 0;
- for (int i = 0; i < 4; i++) {
- c = (S_NEXT(s) | 0x20) - '0';
- if (c > 9) {
- c -= ('a' - ('9' + 1));
- }
- num = (num << 4) | c;
- }
- vstr_add_char(&vstr, num);
- goto str_cont;
- }
- }
- }
- vstr_add_byte(&vstr, c);
- str_cont:
- S_NEXT(s);
- }
- if (S_END(s)) {
- goto fail;
- }
- S_NEXT(s);
- next = mp_obj_new_str(vstr.buf, vstr.len);
- break;
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- bool flt = false;
- vstr_reset(&vstr);
- for (;;) {
- vstr_add_byte(&vstr, cur);
- cur = S_CUR(s);
- if (cur == '.' || cur == 'E' || cur == 'e') {
- flt = true;
- } else if (cur == '+' || cur == '-' || unichar_isdigit(cur)) {
- // pass
- } else {
- break;
- }
- S_NEXT(s);
- }
- if (flt) {
- next = mp_parse_num_float(vstr.buf, vstr.len, false, NULL);
- } else {
- next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);
- }
- break;
- }
- case '[':
- next = mp_obj_new_list(0, NULL);
- enter = true;
- break;
- case '{':
- next = mp_obj_new_dict(0);
- enter = true;
- break;
- case '}':
- case ']': {
- if (stack_top == MP_OBJ_NULL) {
- // no object at all
- goto fail;
- }
- if (stack.len == 0) {
- // finished; compound object
- goto success;
- }
- stack.len -= 1;
- stack_top = stack.items[stack.len];
- stack_top_type = mp_obj_get_type(stack_top);
- goto cont;
- }
- default:
- goto fail;
- }
- if (stack_top == MP_OBJ_NULL) {
- stack_top = next;
- stack_top_type = mp_obj_get_type(stack_top);
- if (!enter) {
- // finished; single primitive only
- goto success;
- }
- } else {
- // append to list or dict
- if (stack_top_type == &mp_type_list) {
- mp_obj_list_append(stack_top, next);
- } else {
- if (stack_key == MP_OBJ_NULL) {
- stack_key = next;
- if (enter) {
- goto fail;
- }
- } else {
- mp_obj_dict_store(stack_top, stack_key, next);
- stack_key = MP_OBJ_NULL;
- }
- }
- if (enter) {
- if (stack.items == NULL) {
- mp_obj_list_init(&stack, 1);
- stack.items[0] = stack_top;
- } else {
- mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top);
- }
- stack_top = next;
- stack_top_type = mp_obj_get_type(stack_top);
- }
- }
- }
-success:
- // eat trailing whitespace
- while (unichar_isspace(S_CUR(s))) {
- S_NEXT(s);
- }
- if (!S_END(s)) {
- // unexpected chars
- goto fail;
- }
- if (stack_top == MP_OBJ_NULL || stack.len != 0) {
- // not exactly 1 object
- goto fail;
- }
- vstr_clear(&vstr);
- return stack_top;
-
-fail:
- mp_raise_ValueError(MP_ERROR_TEXT("syntax error in JSON"));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
-
-STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ);
- vstr_t vstr = {bufinfo.len, bufinfo.len, (char *)bufinfo.buf, true};
- mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
- return mod_ujson_load(MP_OBJ_FROM_PTR(&sio));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
-
-STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) },
- { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_ujson_dump_obj) },
- { MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) },
- { MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) },
- { MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_ujson_loads_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_ujson_globals, mp_module_ujson_globals_table);
-
-const mp_obj_module_t mp_module_ujson = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_ujson_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_ujson, mp_module_ujson);
-
-#endif // MICROPY_PY_UJSON
diff --git a/extmod/moduos.c b/extmod/moduos.c
deleted file mode 100644
index 87a611148d1cf..0000000000000
--- a/extmod/moduos.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016-2022 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 "py/objstr.h"
-#include "py/runtime.h"
-
-#if MICROPY_PY_UOS
-
-#include "extmod/misc.h"
-#include "extmod/vfs.h"
-
-#if MICROPY_VFS_FAT
-#include "extmod/vfs_fat.h"
-#endif
-
-#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2
-#include "extmod/vfs_lfs.h"
-#endif
-
-#if MICROPY_VFS_POSIX
-#include "extmod/vfs_posix.h"
-#endif
-
-#if MICROPY_PY_UOS_UNAME
-#include "genhdr/mpversion.h"
-#endif
-
-#ifdef MICROPY_PY_UOS_INCLUDEFILE
-#include MICROPY_PY_UOS_INCLUDEFILE
-#endif
-
-#ifdef MICROPY_BUILD_TYPE
-#define MICROPY_BUILD_TYPE_PAREN " (" MICROPY_BUILD_TYPE ")"
-#else
-#define MICROPY_BUILD_TYPE_PAREN
-#endif
-
-#if MICROPY_PY_UOS_UNAME
-
-#if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
-#define CONST_RELEASE
-#else
-#define CONST_RELEASE const
-#endif
-
-STATIC const qstr mp_uos_uname_info_fields[] = {
- MP_QSTR_sysname,
- MP_QSTR_nodename,
- MP_QSTR_release,
- MP_QSTR_version,
- MP_QSTR_machine
-};
-STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
-STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
-STATIC CONST_RELEASE MP_DEFINE_STR_OBJ(mp_uos_uname_info_release_obj, MICROPY_VERSION_STRING);
-STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN);
-STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
-
-STATIC MP_DEFINE_ATTRTUPLE(
- mp_uos_uname_info_obj,
- mp_uos_uname_info_fields,
- 5,
- MP_ROM_PTR(&mp_uos_uname_info_sysname_obj),
- MP_ROM_PTR(&mp_uos_uname_info_nodename_obj),
- MP_ROM_PTR(&mp_uos_uname_info_release_obj),
- MP_ROM_PTR(&mp_uos_uname_info_version_obj),
- MP_ROM_PTR(&mp_uos_uname_info_machine_obj)
- );
-
-STATIC mp_obj_t mp_uos_uname(void) {
- #if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
- const char *release = mp_uos_uname_release();
- mp_uos_uname_info_release_obj.len = strlen(release);
- mp_uos_uname_info_release_obj.data = (const byte *)release;
- #endif
- return MP_OBJ_FROM_PTR(&mp_uos_uname_info_obj);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_uos_uname_obj, mp_uos_uname);
-
-#endif
-
-STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
-
- #if MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV
- { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mp_uos_getenv_obj) },
- { MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_uos_putenv_obj) },
- { MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_uos_unsetenv_obj) },
- #endif
- #if MICROPY_PY_UOS_SEP
- { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
- #endif
- #if MICROPY_PY_UOS_SYNC
- { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_uos_sync_obj) },
- #endif
- #if MICROPY_PY_UOS_SYSTEM
- { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mp_uos_system_obj) },
- #endif
- #if MICROPY_PY_UOS_UNAME
- { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&mp_uos_uname_obj) },
- #endif
- #if MICROPY_PY_UOS_URANDOM
- { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_uos_urandom_obj) },
- #endif
-
- #if MICROPY_VFS
- { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
- { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
- { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) },
- { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
- { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) },
- { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove
- #endif
-
- // The following are MicroPython extensions.
-
- #if MICROPY_PY_OS_DUPTERM
- { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
- #endif
- #if MICROPY_PY_UOS_DUPTERM_NOTIFY
- { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&mp_uos_dupterm_notify_obj) },
- #endif
- #if MICROPY_PY_UOS_ERRNO
- { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_uos_errno_obj) },
- #endif
-
- #if MICROPY_VFS
- { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
- { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
- #if MICROPY_VFS_FAT
- { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
- #endif
- #if MICROPY_VFS_LFS1
- { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) },
- #endif
- #if MICROPY_VFS_LFS2
- { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) },
- #endif
- #if MICROPY_VFS_POSIX
- { MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) },
- #endif
- #endif
-};
-STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
-
-const mp_obj_module_t mp_module_uos = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&os_module_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_uos, mp_module_uos);
-
-#endif // MICROPY_PY_UOS
diff --git a/extmod/moduplatform.c b/extmod/moduplatform.c
deleted file mode 100644
index 1b35b08aa7214..0000000000000
--- a/extmod/moduplatform.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013-2021 Ibrahim Abdelkader
- *
- * 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/objtuple.h"
-#include "py/objstr.h"
-#include "py/mphal.h"
-#include "extmod/moduplatform.h"
-#include "genhdr/mpversion.h"
-
-#if MICROPY_PY_UPLATFORM
-
-// platform - Access to underlying platform's identifying data
-
-STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, MICROPY_PLATFORM_SYSTEM "-" \
- MICROPY_VERSION_STRING "-" MICROPY_PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" \
- MICROPY_PLATFORM_LIBC_LIB "" MICROPY_PLATFORM_LIBC_VER);
-STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, MICROPY_PLATFORM_COMPILER);
-STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, MICROPY_PLATFORM_LIBC_LIB);
-STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, MICROPY_PLATFORM_LIBC_VER);
-STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = {
- {&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)}
-};
-
-STATIC mp_obj_t platform_platform(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- return MP_OBJ_FROM_PTR(&info_platform_obj);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_platform_obj, 0, platform_platform);
-
-STATIC mp_obj_t platform_python_compiler(void) {
- return MP_OBJ_FROM_PTR(&info_python_compiler_obj);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(platform_python_compiler_obj, platform_python_compiler);
-
-STATIC mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- return MP_OBJ_FROM_PTR(&info_libc_tuple_obj);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver);
-
-STATIC const mp_rom_map_elem_t modplatform_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uplatform) },
- { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_platform_obj) },
- { MP_ROM_QSTR(MP_QSTR_python_compiler), MP_ROM_PTR(&platform_python_compiler_obj) },
- { MP_ROM_QSTR(MP_QSTR_libc_ver), MP_ROM_PTR(&platform_libc_ver_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table);
-
-const mp_obj_module_t mp_module_uplatform = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&modplatform_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_uplatform, mp_module_uplatform);
-
-#endif // MICROPY_PY_UPLATFORM
diff --git a/extmod/moduplatform.h b/extmod/moduplatform.h
deleted file mode 100644
index 2b9ad3ae49b73..0000000000000
--- a/extmod/moduplatform.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013-2021 Ibrahim Abdelkader
- *
- * 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_MODUPLATFORM_H
-#define MICROPY_INCLUDED_MODUPLATFORM_H
-
-#include "py/misc.h" // For MP_STRINGIFY.
-#include "py/mpconfig.h"
-
-// Preprocessor directives indentifying the platform.
-// The (u)platform module itself is guarded by MICROPY_PY_UPLATFORM, see the
-// .c file, but these are made available because they're generally usable.
-// TODO: Add more architectures, compilers and libraries.
-// See: https://sourceforge.net/p/predef/wiki/Home/
-
-#if defined(__ARM_ARCH)
-#define MICROPY_PLATFORM_ARCH "arm"
-#elif defined(__x86_64__) || defined(_WIN64)
-#define MICROPY_PLATFORM_ARCH "x86_64"
-#elif defined(__i386__) || defined(_M_IX86)
-#define MICROPY_PLATFORM_ARCH "x86"
-#elif defined(__xtensa__) || defined(_M_IX86)
-#define MICROPY_PLATFORM_ARCH "xtensa"
-#else
-#define MICROPY_PLATFORM_ARCH ""
-#endif
-
-#if defined(__GNUC__)
-#define MICROPY_PLATFORM_COMPILER \
- "GCC " \
- MP_STRINGIFY(__GNUC__) "." \
- MP_STRINGIFY(__GNUC_MINOR__) "." \
- MP_STRINGIFY(__GNUC_PATCHLEVEL__)
-#elif defined(__ARMCC_VERSION)
-#define MICROPY_PLATFORM_COMPILER \
- "ARMCC " \
- MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
- MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
- MP_STRINGIFY((__ARMCC_VERSION % 10000))
-#elif defined(_MSC_VER)
-#if defined(_WIN64)
-#define MICROPY_PLATFORM_COMPILER_BITS "64 bit"
-#elif defined(_M_IX86)
-#define MICROPY_PLATFORM_COMPILER_BITS "32 bit"
-#else
-#define MICROPY_PLATFORM_COMPILER_BITS ""
-#endif
-#define MICROPY_PLATFORM_COMPILER \
- "MSC v." MP_STRINGIFY(_MSC_VER) " " MICROPY_PLATFORM_COMPILER_BITS
-#else
-#define MICROPY_PLATFORM_COMPILER ""
-#endif
-
-#if defined(__GLIBC__)
-#define MICROPY_PLATFORM_LIBC_LIB "glibc"
-#define MICROPY_PLATFORM_LIBC_VER \
- MP_STRINGIFY(__GLIBC__) "." \
- MP_STRINGIFY(__GLIBC_MINOR__)
-#elif defined(__NEWLIB__)
-#define MICROPY_PLATFORM_LIBC_LIB "newlib"
-#define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION
-#else
-#define MICROPY_PLATFORM_LIBC_LIB ""
-#define MICROPY_PLATFORM_LIBC_VER ""
-#endif
-
-#if defined(__linux)
-#define MICROPY_PLATFORM_SYSTEM "Linux"
-#elif defined(__unix__)
-#define MICROPY_PLATFORM_SYSTEM "Unix"
-#elif defined(__CYGWIN__)
-#define MICROPY_PLATFORM_SYSTEM "Cygwin"
-#elif defined(_WIN32)
-#define MICROPY_PLATFORM_SYSTEM "Windows"
-#else
-#define MICROPY_PLATFORM_SYSTEM "MicroPython"
-#endif
-
-#ifndef MICROPY_PLATFORM_VERSION
-#define MICROPY_PLATFORM_VERSION ""
-#endif
-
-#endif // MICROPY_INCLUDED_MODUPLATFORM_H
diff --git a/extmod/modurandom.c b/extmod/modurandom.c
deleted file mode 100644
index b66162719034b..0000000000000
--- a/extmod/modurandom.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016 Paul Sokolovsky
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-#include "py/runtime.h"
-
-#if MICROPY_PY_URANDOM
-
-// Work out if the seed will be set on import or not.
-#if MICROPY_MODULE_BUILTIN_INIT && defined(MICROPY_PY_URANDOM_SEED_INIT_FUNC)
-#define SEED_ON_IMPORT (1)
-#else
-#define SEED_ON_IMPORT (0)
-#endif
-
-// Yasmarang random number generator
-// by Ilya Levin
-// http://www.literatecode.com/yasmarang
-// Public Domain
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-#if SEED_ON_IMPORT
-// If the state is seeded on import then keep these variables in the BSS.
-STATIC uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
-STATIC uint8_t yasmarang_dat;
-#else
-// Without seed-on-import these variables must be initialised via the data section.
-STATIC uint32_t yasmarang_pad = 0xeda4baba, yasmarang_n = 69, yasmarang_d = 233;
-STATIC uint8_t yasmarang_dat = 0;
-#endif
-#endif
-
-STATIC uint32_t yasmarang(void) {
- yasmarang_pad += yasmarang_dat + yasmarang_d * yasmarang_n;
- yasmarang_pad = (yasmarang_pad << 3) + (yasmarang_pad >> 29);
- yasmarang_n = yasmarang_pad | 2;
- yasmarang_d ^= (yasmarang_pad << 31) + (yasmarang_pad >> 1);
- yasmarang_dat ^= (char)yasmarang_pad ^ (yasmarang_d >> 8) ^ 1;
-
- return yasmarang_pad ^ (yasmarang_d << 5) ^ (yasmarang_pad >> 18) ^ (yasmarang_dat << 1);
-} /* yasmarang */
-
-// End of Yasmarang
-
-#if MICROPY_PY_URANDOM_EXTRA_FUNCS
-
-// returns an unsigned integer below the given argument
-// n must not be zero
-STATIC uint32_t yasmarang_randbelow(uint32_t n) {
- uint32_t mask = 1;
- while ((n & mask) < n) {
- mask = (mask << 1) | 1;
- }
- uint32_t r;
- do {
- r = yasmarang() & mask;
- } while (r >= n);
- return r;
-}
-
-#endif
-
-STATIC mp_obj_t mod_urandom_getrandbits(mp_obj_t num_in) {
- int n = mp_obj_get_int(num_in);
- if (n > 32 || n < 0) {
- mp_raise_ValueError(MP_ERROR_TEXT("bits must be 32 or less"));
- }
- if (n == 0) {
- return MP_OBJ_NEW_SMALL_INT(0);
- }
- uint32_t mask = ~0;
- // Beware of C undefined behavior when shifting by >= than bit size
- mask >>= (32 - n);
- return mp_obj_new_int_from_uint(yasmarang() & mask);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_getrandbits_obj, mod_urandom_getrandbits);
-
-STATIC mp_obj_t mod_urandom_seed(size_t n_args, const mp_obj_t *args) {
- mp_uint_t seed;
- if (n_args == 0 || args[0] == mp_const_none) {
- #ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC
- seed = MICROPY_PY_URANDOM_SEED_INIT_FUNC;
- #else
- mp_raise_ValueError(MP_ERROR_TEXT("no default seed"));
- #endif
- } else {
- seed = mp_obj_get_int_truncated(args[0]);
- }
- yasmarang_pad = seed;
- yasmarang_n = 69;
- yasmarang_d = 233;
- yasmarang_dat = 0;
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_urandom_seed_obj, 0, 1, mod_urandom_seed);
-
-#if MICROPY_PY_URANDOM_EXTRA_FUNCS
-
-STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
- mp_int_t start = mp_obj_get_int(args[0]);
- if (n_args == 1) {
- // range(stop)
- if (start > 0) {
- return mp_obj_new_int(yasmarang_randbelow(start));
- } else {
- goto error;
- }
- } else {
- mp_int_t stop = mp_obj_get_int(args[1]);
- if (n_args == 2) {
- // range(start, stop)
- if (start < stop) {
- return mp_obj_new_int(start + yasmarang_randbelow(stop - start));
- } else {
- goto error;
- }
- } else {
- // range(start, stop, step)
- mp_int_t step = mp_obj_get_int(args[2]);
- mp_int_t n;
- if (step > 0) {
- n = (stop - start + step - 1) / step;
- } else if (step < 0) {
- n = (stop - start + step + 1) / step;
- } else {
- goto error;
- }
- if (n > 0) {
- return mp_obj_new_int(start + step * yasmarang_randbelow(n));
- } else {
- goto error;
- }
- }
- }
-
-error:
- mp_raise_ValueError(NULL);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_urandom_randrange_obj, 1, 3, mod_urandom_randrange);
-
-STATIC mp_obj_t mod_urandom_randint(mp_obj_t a_in, mp_obj_t b_in) {
- mp_int_t a = mp_obj_get_int(a_in);
- mp_int_t b = mp_obj_get_int(b_in);
- if (a <= b) {
- return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1));
- } else {
- mp_raise_ValueError(NULL);
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint);
-
-STATIC mp_obj_t mod_urandom_choice(mp_obj_t seq) {
- mp_int_t len = mp_obj_get_int(mp_obj_len(seq));
- if (len > 0) {
- return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL);
- } else {
- mp_raise_type(&mp_type_IndexError);
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_choice_obj, mod_urandom_choice);
-
-#if MICROPY_PY_BUILTINS_FLOAT
-
-// returns a number in the range [0..1) using Yasmarang to fill in the fraction bits
-STATIC mp_float_t yasmarang_float(void) {
- mp_float_union_t u;
- u.p.sgn = 0;
- u.p.exp = (1 << (MP_FLOAT_EXP_BITS - 1)) - 1;
- if (MP_FLOAT_FRAC_BITS <= 32) {
- u.p.frc = yasmarang();
- } else {
- u.p.frc = ((uint64_t)yasmarang() << 32) | (uint64_t)yasmarang();
- }
- return u.f - 1;
-}
-
-STATIC mp_obj_t mod_urandom_random(void) {
- return mp_obj_new_float(yasmarang_float());
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom_random_obj, mod_urandom_random);
-
-STATIC mp_obj_t mod_urandom_uniform(mp_obj_t a_in, mp_obj_t b_in) {
- mp_float_t a = mp_obj_get_float(a_in);
- mp_float_t b = mp_obj_get_float(b_in);
- return mp_obj_new_float(a + (b - a) * yasmarang_float());
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_uniform_obj, mod_urandom_uniform);
-
-#endif
-
-#endif // MICROPY_PY_URANDOM_EXTRA_FUNCS
-
-#if SEED_ON_IMPORT
-STATIC mp_obj_t mod_urandom___init__(void) {
- // This module may be imported by more than one name so need to ensure
- // that it's only ever seeded once.
- static bool seeded = false;
- if (!seeded) {
- seeded = true;
- mod_urandom_seed(0, NULL);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom___init___obj, mod_urandom___init__);
-#endif
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_rom_map_elem_t mp_module_urandom_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_urandom) },
- #if SEED_ON_IMPORT
- { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&mod_urandom___init___obj) },
- #endif
- { MP_ROM_QSTR(MP_QSTR_getrandbits), MP_ROM_PTR(&mod_urandom_getrandbits_obj) },
- { MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_urandom_seed_obj) },
- #if MICROPY_PY_URANDOM_EXTRA_FUNCS
- { MP_ROM_QSTR(MP_QSTR_randrange), MP_ROM_PTR(&mod_urandom_randrange_obj) },
- { MP_ROM_QSTR(MP_QSTR_randint), MP_ROM_PTR(&mod_urandom_randint_obj) },
- { MP_ROM_QSTR(MP_QSTR_choice), MP_ROM_PTR(&mod_urandom_choice_obj) },
- #if MICROPY_PY_BUILTINS_FLOAT
- { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_urandom_random_obj) },
- { MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&mod_urandom_uniform_obj) },
- #endif
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_urandom_globals, mp_module_urandom_globals_table);
-
-const mp_obj_module_t mp_module_urandom = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_urandom_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_urandom, mp_module_urandom);
-#endif
-
-#endif // MICROPY_PY_URANDOM
diff --git a/extmod/modure.c b/extmod/modure.c
deleted file mode 100644
index 6bd89898431ff..0000000000000
--- a/extmod/modure.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Paul Sokolovsky
- *
- * 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/runtime.h"
-#include "py/binary.h"
-#include "py/objstr.h"
-#include "py/stackctrl.h"
-
-#if MICROPY_PY_URE
-
-#define re1_5_stack_chk() MP_STACK_CHECK()
-
-#include "lib/re1.5/re1.5.h"
-
-#define FLAG_DEBUG 0x1000
-
-typedef struct _mp_obj_re_t {
- mp_obj_base_t base;
- ByteProg re;
-} mp_obj_re_t;
-
-typedef struct _mp_obj_match_t {
- mp_obj_base_t base;
- int num_matches;
- mp_obj_t str;
- const char *caps[0];
-} mp_obj_match_t;
-
-STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args);
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_obj_type_t re_type;
-#endif
-
-STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- (void)kind;
- mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
- mp_printf(print, "", self->num_matches);
-}
-
-STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) {
- mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
- mp_int_t no = mp_obj_get_int(no_in);
- if (no < 0 || no >= self->num_matches) {
- mp_raise_type_arg(&mp_type_IndexError, no_in);
- }
-
- const char *start = self->caps[no * 2];
- if (start == NULL) {
- // no match for this group
- return mp_const_none;
- }
- return mp_obj_new_str_of_type(mp_obj_get_type(self->str),
- (const byte *)start, self->caps[no * 2 + 1] - start);
-}
-MP_DEFINE_CONST_FUN_OBJ_2(match_group_obj, match_group);
-
-#if MICROPY_PY_URE_MATCH_GROUPS
-
-STATIC mp_obj_t match_groups(mp_obj_t self_in) {
- mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->num_matches <= 1) {
- return mp_const_empty_tuple;
- }
- mp_obj_tuple_t *groups = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->num_matches - 1, NULL));
- for (int i = 1; i < self->num_matches; ++i) {
- groups->items[i - 1] = match_group(self_in, MP_OBJ_NEW_SMALL_INT(i));
- }
- return MP_OBJ_FROM_PTR(groups);
-}
-MP_DEFINE_CONST_FUN_OBJ_1(match_groups_obj, match_groups);
-
-#endif
-
-#if MICROPY_PY_URE_MATCH_SPAN_START_END
-
-STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span[2]) {
- mp_obj_match_t *self = MP_OBJ_TO_PTR(args[0]);
-
- mp_int_t no = 0;
- if (n_args == 2) {
- no = mp_obj_get_int(args[1]);
- if (no < 0 || no >= self->num_matches) {
- mp_raise_type_arg(&mp_type_IndexError, args[1]);
- }
- }
-
- mp_int_t s = -1;
- mp_int_t e = -1;
- const char *start = self->caps[no * 2];
- if (start != NULL) {
- // have a match for this group
- const char *begin = mp_obj_str_get_str(self->str);
- s = start - begin;
- e = self->caps[no * 2 + 1] - begin;
- }
-
- span[0] = mp_obj_new_int(s);
- span[1] = mp_obj_new_int(e);
-}
-
-STATIC mp_obj_t match_span(size_t n_args, const mp_obj_t *args) {
- mp_obj_t span[2];
- match_span_helper(n_args, args, span);
- return mp_obj_new_tuple(2, span);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_span_obj, 1, 2, match_span);
-
-STATIC mp_obj_t match_start(size_t n_args, const mp_obj_t *args) {
- mp_obj_t span[2];
- match_span_helper(n_args, args, span);
- return span[0];
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_start_obj, 1, 2, match_start);
-
-STATIC mp_obj_t match_end(size_t n_args, const mp_obj_t *args) {
- mp_obj_t span[2];
- match_span_helper(n_args, args, span);
- return span[1];
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_end_obj, 1, 2, match_end);
-
-#endif
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_rom_map_elem_t match_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_group), MP_ROM_PTR(&match_group_obj) },
- #if MICROPY_PY_URE_MATCH_GROUPS
- { MP_ROM_QSTR(MP_QSTR_groups), MP_ROM_PTR(&match_groups_obj) },
- #endif
- #if MICROPY_PY_URE_MATCH_SPAN_START_END
- { MP_ROM_QSTR(MP_QSTR_span), MP_ROM_PTR(&match_span_obj) },
- { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&match_start_obj) },
- { MP_ROM_QSTR(MP_QSTR_end), MP_ROM_PTR(&match_end_obj) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
-
-STATIC const mp_obj_type_t match_type = {
- { &mp_type_type },
- .name = MP_QSTR_match,
- .print = match_print,
- .locals_dict = (void *)&match_locals_dict,
-};
-#endif
-
-STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- (void)kind;
- mp_obj_re_t *self = MP_OBJ_TO_PTR(self_in);
- mp_printf(print, "", self);
-}
-
-STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
- (void)n_args;
- mp_obj_re_t *self;
- if (mp_obj_is_type(args[0], &re_type)) {
- self = MP_OBJ_TO_PTR(args[0]);
- } else {
- self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
- }
- Subject subj;
- size_t len;
- subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
- subj.end = subj.begin + len;
- int caps_num = (self->re.sub + 1) * 2;
- mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char *, caps_num);
- // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
- memset((char *)match->caps, 0, caps_num * sizeof(char *));
- int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, is_anchored);
- if (res == 0) {
- m_del_var(mp_obj_match_t, char *, caps_num, match);
- return mp_const_none;
- }
-
- match->base.type = &match_type;
- match->num_matches = caps_num / 2; // caps_num counts start and end pointers
- match->str = args[1];
- return MP_OBJ_FROM_PTR(match);
-}
-
-STATIC mp_obj_t re_match(size_t n_args, const mp_obj_t *args) {
- return ure_exec(true, n_args, args);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match);
-
-STATIC mp_obj_t re_search(size_t n_args, const mp_obj_t *args) {
- return ure_exec(false, n_args, args);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);
-
-STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
- mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
- Subject subj;
- size_t len;
- const mp_obj_type_t *str_type = mp_obj_get_type(args[1]);
- subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
- subj.end = subj.begin + len;
- int caps_num = (self->re.sub + 1) * 2;
-
- int maxsplit = 0;
- if (n_args > 2) {
- maxsplit = mp_obj_get_int(args[2]);
- }
-
- mp_obj_t retval = mp_obj_new_list(0, NULL);
- const char **caps = mp_local_alloc(caps_num * sizeof(char *));
- while (true) {
- // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
- memset((char **)caps, 0, caps_num * sizeof(char *));
- int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false);
-
- // if we didn't have a match, or had an empty match, it's time to stop
- if (!res || caps[0] == caps[1]) {
- break;
- }
-
- mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte *)subj.begin, caps[0] - subj.begin);
- mp_obj_list_append(retval, s);
- if (self->re.sub > 0) {
- mp_raise_NotImplementedError(MP_ERROR_TEXT("splitting with sub-captures"));
- }
- subj.begin = caps[1];
- if (maxsplit > 0 && --maxsplit == 0) {
- break;
- }
- }
- // cast is a workaround for a bug in msvc (see above)
- mp_local_free((char **)caps);
-
- mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte *)subj.begin, subj.end - subj.begin);
- mp_obj_list_append(retval, s);
- return retval;
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split);
-
-#if MICROPY_PY_URE_SUB
-
-STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
- mp_obj_re_t *self;
- if (mp_obj_is_type(args[0], &re_type)) {
- self = MP_OBJ_TO_PTR(args[0]);
- } else {
- self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
- }
- mp_obj_t replace = args[1];
- mp_obj_t where = args[2];
- mp_int_t count = 0;
- if (n_args > 3) {
- count = mp_obj_get_int(args[3]);
- // Note: flags are currently ignored
- }
-
- size_t where_len;
- const char *where_str = mp_obj_str_get_data(where, &where_len);
- Subject subj;
- subj.begin_line = subj.begin = where_str;
- subj.end = subj.begin + where_len;
- int caps_num = (self->re.sub + 1) * 2;
-
- vstr_t vstr_return;
- vstr_return.buf = NULL; // We'll init the vstr after the first match
- mp_obj_match_t *match = mp_local_alloc(sizeof(mp_obj_match_t) + caps_num * sizeof(char *));
- match->base.type = &match_type;
- match->num_matches = caps_num / 2; // caps_num counts start and end pointers
- match->str = where;
-
- for (;;) {
- // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
- memset((char *)match->caps, 0, caps_num * sizeof(char *));
- int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, false);
-
- // If we didn't have a match, or had an empty match, it's time to stop
- if (!res || match->caps[0] == match->caps[1]) {
- break;
- }
-
- // Initialise the vstr if it's not already
- if (vstr_return.buf == NULL) {
- vstr_init(&vstr_return, match->caps[0] - subj.begin);
- }
-
- // Add pre-match string
- vstr_add_strn(&vstr_return, subj.begin, match->caps[0] - subj.begin);
-
- // Get replacement string
- const char *repl = mp_obj_str_get_str((mp_obj_is_callable(replace) ? mp_call_function_1(replace, MP_OBJ_FROM_PTR(match)) : replace));
-
- // Append replacement string to result, substituting any regex groups
- while (*repl != '\0') {
- if (*repl == '\\') {
- ++repl;
- bool is_g_format = false;
- if (*repl == 'g' && repl[1] == '<') {
- // Group specified with syntax "\g"
- repl += 2;
- is_g_format = true;
- }
-
- if ('0' <= *repl && *repl <= '9') {
- // Group specified with syntax "\g" or "\number"
- unsigned int match_no = 0;
- do {
- match_no = match_no * 10 + (*repl++ - '0');
- } while ('0' <= *repl && *repl <= '9');
- if (is_g_format && *repl == '>') {
- ++repl;
- }
-
- if (match_no >= (unsigned int)match->num_matches) {
- mp_raise_type_arg(&mp_type_IndexError, MP_OBJ_NEW_SMALL_INT(match_no));
- }
-
- const char *start_match = match->caps[match_no * 2];
- if (start_match != NULL) {
- // Add the substring matched by group
- const char *end_match = match->caps[match_no * 2 + 1];
- vstr_add_strn(&vstr_return, start_match, end_match - start_match);
- }
- } else if (*repl == '\\') {
- // Add the \ character
- vstr_add_byte(&vstr_return, *repl++);
- }
- } else {
- // Just add the current byte from the replacement string
- vstr_add_byte(&vstr_return, *repl++);
- }
- }
-
- // Move start pointer to end of last match
- subj.begin = match->caps[1];
-
- // Stop substitutions if count was given and gets to 0
- if (count > 0 && --count == 0) {
- break;
- }
- }
-
- mp_local_free(match);
-
- if (vstr_return.buf == NULL) {
- // Optimisation for case of no substitutions
- return where;
- }
-
- // Add post-match string
- vstr_add_strn(&vstr_return, subj.begin, subj.end - subj.begin);
-
- return mp_obj_new_str_from_vstr(mp_obj_get_type(where), &vstr_return);
-}
-
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub_helper);
-
-#endif
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_rom_map_elem_t re_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
- { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
- { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&re_split_obj) },
- #if MICROPY_PY_URE_SUB
- { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
-
-STATIC const mp_obj_type_t re_type = {
- { &mp_type_type },
- .name = MP_QSTR_ure,
- .print = re_print,
- .locals_dict = (void *)&re_locals_dict,
-};
-#endif
-
-STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
- const char *re_str = mp_obj_str_get_str(args[0]);
- int size = re1_5_sizecode(re_str);
- if (size == -1) {
- goto error;
- }
- mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, &re_type);
- #if MICROPY_PY_URE_DEBUG
- int flags = 0;
- if (n_args > 1) {
- flags = mp_obj_get_int(args[1]);
- }
- #endif
- int error = re1_5_compilecode(&o->re, re_str);
- if (error != 0) {
- error:
- mp_raise_ValueError(MP_ERROR_TEXT("error in regex"));
- }
- #if MICROPY_PY_URE_DEBUG
- if (flags & FLAG_DEBUG) {
- re1_5_dumpcode(&o->re);
- }
- #endif
- return MP_OBJ_FROM_PTR(o);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile);
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ure) },
- { MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) },
- { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
- { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
- #if MICROPY_PY_URE_SUB
- { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) },
- #endif
- #if MICROPY_PY_URE_DEBUG
- { MP_ROM_QSTR(MP_QSTR_DEBUG), MP_ROM_INT(FLAG_DEBUG) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table);
-
-const mp_obj_module_t mp_module_ure = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_re_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_ure, mp_module_ure);
-#endif
-
-// Source files #include'd here to make sure they're compiled in
-// only if module is enabled by config setting.
-
-#define re1_5_fatal(x) assert(!x)
-
-#include "lib/re1.5/compilecode.c"
-#include "lib/re1.5/recursiveloop.c"
-#include "lib/re1.5/charclass.c"
-
-#if MICROPY_PY_URE_DEBUG
-// Make sure the output print statements go to the same output as other Python output.
-#define printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
-#include "lib/re1.5/dumpcode.c"
-#undef printf
-#endif
-
-#endif // MICROPY_PY_URE
diff --git a/extmod/moduselect.c b/extmod/moduselect.c
deleted file mode 100644
index 70a1de2e40998..0000000000000
--- a/extmod/moduselect.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Damien P. George
- * Copyright (c) 2015-2017 Paul Sokolovsky
- *
- * 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_USELECT
-
-#include
-
-#include "py/runtime.h"
-#include "py/obj.h"
-#include "py/objlist.h"
-#include "py/stream.h"
-#include "py/mperrno.h"
-#include "py/mphal.h"
-
-// Flags for poll()
-#define FLAG_ONESHOT (1)
-
-typedef struct _poll_obj_t {
- mp_obj_t obj;
- mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
- mp_uint_t flags;
- mp_uint_t flags_ret;
-} poll_obj_t;
-
-STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) {
- for (mp_uint_t i = 0; i < obj_len; i++) {
- mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
- if (elem->value == MP_OBJ_NULL) {
- // object not found; get its ioctl and add it to the poll list
- const mp_stream_p_t *stream_p = mp_get_stream_raise(obj[i], MP_STREAM_OP_IOCTL);
- poll_obj_t *poll_obj = m_new_obj(poll_obj_t);
- poll_obj->obj = obj[i];
- poll_obj->ioctl = stream_p->ioctl;
- poll_obj->flags = flags;
- poll_obj->flags_ret = 0;
- elem->value = MP_OBJ_FROM_PTR(poll_obj);
- } else {
- // object exists; update its flags
- if (or_flags) {
- ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags |= flags;
- } else {
- ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = flags;
- }
- }
- }
-}
-
-// poll each object in the map
-STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) {
- mp_uint_t n_ready = 0;
- for (mp_uint_t i = 0; i < poll_map->alloc; ++i) {
- if (!mp_map_slot_is_filled(poll_map, i)) {
- continue;
- }
-
- poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map->table[i].value);
- int errcode;
- mp_int_t ret = poll_obj->ioctl(poll_obj->obj, MP_STREAM_POLL, poll_obj->flags, &errcode);
- poll_obj->flags_ret = ret;
-
- if (ret == -1) {
- // error doing ioctl
- mp_raise_OSError(errcode);
- }
-
- if (ret != 0) {
- // object is ready
- n_ready += 1;
- if (rwx_num != NULL) {
- if (ret & MP_STREAM_POLL_RD) {
- rwx_num[0] += 1;
- }
- if (ret & MP_STREAM_POLL_WR) {
- rwx_num[1] += 1;
- }
- if ((ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
- rwx_num[2] += 1;
- }
- }
- }
- }
- return n_ready;
-}
-
-#if MICROPY_PY_USELECT_SELECT
-// select(rlist, wlist, xlist[, timeout])
-STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
- // get array data from tuple/list arguments
- size_t rwx_len[3];
- mp_obj_t *r_array, *w_array, *x_array;
- mp_obj_get_array(args[0], &rwx_len[0], &r_array);
- mp_obj_get_array(args[1], &rwx_len[1], &w_array);
- mp_obj_get_array(args[2], &rwx_len[2], &x_array);
-
- // get timeout
- mp_uint_t timeout = -1;
- if (n_args == 4) {
- if (args[3] != mp_const_none) {
- #if MICROPY_PY_BUILTINS_FLOAT
- float timeout_f = mp_obj_get_float_to_f(args[3]);
- if (timeout_f >= 0) {
- timeout = (mp_uint_t)(timeout_f * 1000);
- }
- #else
- timeout = mp_obj_get_int(args[3]) * 1000;
- #endif
- }
- }
-
- // merge separate lists and get the ioctl function for each object
- mp_map_t poll_map;
- mp_map_init(&poll_map, rwx_len[0] + rwx_len[1] + rwx_len[2]);
- poll_map_add(&poll_map, r_array, rwx_len[0], MP_STREAM_POLL_RD, true);
- poll_map_add(&poll_map, w_array, rwx_len[1], MP_STREAM_POLL_WR, true);
- poll_map_add(&poll_map, x_array, rwx_len[2], MP_STREAM_POLL_ERR | MP_STREAM_POLL_HUP, true);
-
- mp_uint_t start_tick = mp_hal_ticks_ms();
- rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
- for (;;) {
- // poll the objects
- mp_uint_t n_ready = poll_map_poll(&poll_map, rwx_len);
-
- if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
- // one or more objects are ready, or we had a timeout
- mp_obj_t list_array[3];
- list_array[0] = mp_obj_new_list(rwx_len[0], NULL);
- list_array[1] = mp_obj_new_list(rwx_len[1], NULL);
- list_array[2] = mp_obj_new_list(rwx_len[2], NULL);
- rwx_len[0] = rwx_len[1] = rwx_len[2] = 0;
- for (mp_uint_t i = 0; i < poll_map.alloc; ++i) {
- if (!mp_map_slot_is_filled(&poll_map, i)) {
- continue;
- }
- poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value);
- if (poll_obj->flags_ret & MP_STREAM_POLL_RD) {
- ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
- }
- if (poll_obj->flags_ret & MP_STREAM_POLL_WR) {
- ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
- }
- if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
- ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
- }
- }
- mp_map_deinit(&poll_map);
- return mp_obj_new_tuple(3, list_array);
- }
- MICROPY_EVENT_POLL_HOOK
- }
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select);
-#endif // MICROPY_PY_USELECT_SELECT
-
-typedef struct _mp_obj_poll_t {
- mp_obj_base_t base;
- mp_map_t poll_map;
- short iter_cnt;
- short iter_idx;
- int flags;
- // callee-owned tuple
- mp_obj_t ret_tuple;
-} mp_obj_poll_t;
-
-// register(obj[, eventmask])
-STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
- mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_uint_t flags;
- if (n_args == 3) {
- flags = mp_obj_get_int(args[2]);
- } else {
- flags = MP_STREAM_POLL_RD | MP_STREAM_POLL_WR;
- }
- poll_map_add(&self->poll_map, &args[1], 1, flags, false);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
-
-// unregister(obj)
-STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
- mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
- mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
- // TODO raise KeyError if obj didn't exist in map
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
-
-// modify(obj, eventmask)
-STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
- mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
- mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
- if (elem == NULL) {
- mp_raise_OSError(MP_ENOENT);
- }
- ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
-
-STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
- mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
-
- // work out timeout (its given already in ms)
- mp_uint_t timeout = -1;
- int flags = 0;
- if (n_args >= 2) {
- if (args[1] != mp_const_none) {
- mp_int_t timeout_i = mp_obj_get_int(args[1]);
- if (timeout_i >= 0) {
- timeout = timeout_i;
- }
- }
- if (n_args >= 3) {
- flags = mp_obj_get_int(args[2]);
- }
- }
-
- self->flags = flags;
-
- mp_uint_t start_tick = mp_hal_ticks_ms();
- mp_uint_t n_ready;
- for (;;) {
- // poll the objects
- n_ready = poll_map_poll(&self->poll_map, NULL);
- if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
- break;
- }
- MICROPY_EVENT_POLL_HOOK
- }
-
- return n_ready;
-}
-
-STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) {
- mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_uint_t n_ready = poll_poll_internal(n_args, args);
-
- // one or more objects are ready, or we had a timeout
- mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
- n_ready = 0;
- for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) {
- if (!mp_map_slot_is_filled(&self->poll_map, i)) {
- continue;
- }
- poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
- if (poll_obj->flags_ret != 0) {
- mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)};
- ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
- if (self->flags & FLAG_ONESHOT) {
- // Don't poll next time, until new event flags will be set explicitly
- poll_obj->flags = 0;
- }
- }
- }
- return MP_OBJ_FROM_PTR(ret_list);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
-
-STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) {
- mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
-
- if (self->ret_tuple == MP_OBJ_NULL) {
- self->ret_tuple = mp_obj_new_tuple(2, NULL);
- }
-
- int n_ready = poll_poll_internal(n_args, args);
- self->iter_cnt = n_ready;
- self->iter_idx = 0;
-
- return args[0];
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll);
-
-STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
- mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
-
- if (self->iter_cnt == 0) {
- return MP_OBJ_STOP_ITERATION;
- }
-
- self->iter_cnt--;
-
- for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) {
- self->iter_idx++;
- if (!mp_map_slot_is_filled(&self->poll_map, i)) {
- continue;
- }
- poll_obj_t *poll_obj = MP_OBJ_TO_PTR(self->poll_map.table[i].value);
- if (poll_obj->flags_ret != 0) {
- mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
- t->items[0] = poll_obj->obj;
- t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret);
- if (self->flags & FLAG_ONESHOT) {
- // Don't poll next time, until new event flags will be set explicitly
- poll_obj->flags = 0;
- }
- return MP_OBJ_FROM_PTR(t);
- }
- }
-
- assert(!"inconsistent number of poll active entries");
- self->iter_cnt = 0;
- return MP_OBJ_STOP_ITERATION;
-}
-
-STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) },
- { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) },
- { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) },
- { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) },
- { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
-
-STATIC const mp_obj_type_t mp_type_poll = {
- { &mp_type_type },
- .name = MP_QSTR_poll,
- .getiter = mp_identity_getiter,
- .iternext = poll_iternext,
- .locals_dict = (void *)&poll_locals_dict,
-};
-
-// poll()
-STATIC mp_obj_t select_poll(void) {
- mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll);
- mp_map_init(&poll->poll_map, 0);
- poll->iter_cnt = 0;
- poll->ret_tuple = MP_OBJ_NULL;
- return MP_OBJ_FROM_PTR(poll);
-}
-MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);
-
-STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) },
- #if MICROPY_PY_USELECT_SELECT
- { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) },
- #endif
- { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) },
- { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_ROM_INT(MP_STREAM_POLL_RD) },
- { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_ROM_INT(MP_STREAM_POLL_WR) },
- { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_ROM_INT(MP_STREAM_POLL_ERR) },
- { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(MP_STREAM_POLL_HUP) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table);
-
-const mp_obj_module_t mp_module_uselect = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_select_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_uselect, mp_module_uselect);
-
-#endif // MICROPY_PY_USELECT
diff --git a/extmod/modusocket.c b/extmod/modusocket.c
deleted file mode 100644
index 638ab0cf28c0a..0000000000000
--- a/extmod/modusocket.c
+++ /dev/null
@@ -1,656 +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 "py/objtuple.h"
-#include "py/objlist.h"
-#include "py/runtime.h"
-#include "py/stream.h"
-#include "py/mperrno.h"
-#include "shared/netutils/netutils.h"
-#include "modnetwork.h"
-
-#if MICROPY_PY_NETWORK && MICROPY_PY_USOCKET && !MICROPY_PY_LWIP
-
-/******************************************************************************/
-// socket class
-
-STATIC const mp_obj_type_t socket_type;
-
-STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_printf(print, "",
- self->fileno, self->timeout, self->domain, self->type, self->proto, self->bound);
-}
-
-// constructor socket(domain=AF_INET, type=SOCK_STREAM, proto=0)
-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, 3, false);
-
- // create socket object (not bound to any NIC yet)
- mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
- s->base.type = &socket_type;
- s->nic = MP_OBJ_NULL;
- s->nic_type = NULL;
- s->domain = MOD_NETWORK_AF_INET;
- s->type = MOD_NETWORK_SOCK_STREAM;
- s->proto = 0;
- s->bound = false;
- s->fileno = -1;
- if (n_args > 0) {
- s->domain = mp_obj_get_int(args[0]);
- if (n_args > 1) {
- s->type = mp_obj_get_int(args[1]);
- if (n_args > 2) {
- s->proto = mp_obj_get_int(args[2]);
- }
- }
- }
- s->timeout = -1;
- s->callback = MP_OBJ_NULL;
- s->state = MOD_NETWORK_SS_NEW;
- #if MICROPY_PY_USOCKET_EXTENDED_STATE
- s->_private = NULL;
- #endif
-
- return MP_OBJ_FROM_PTR(s);
-}
-
-STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
- if (self->nic == MP_OBJ_NULL) {
- // select NIC based on IP
- self->nic = mod_network_find_nic(ip);
- self->nic_type = (mod_network_nic_type_t *)mp_obj_get_type(self->nic);
-
- // call the NIC to open the socket
- int _errno;
- if (self->nic_type->socket(self, &_errno) != 0) {
- mp_raise_OSError(_errno);
- }
-
- #if MICROPY_PY_USOCKET_EXTENDED_STATE
- // if a timeout was set before binding a NIC, call settimeout to reset it
- if (self->timeout != -1 && self->nic_type->settimeout(self, self->timeout, &_errno) != 0) {
- mp_raise_OSError(_errno);
- }
- #endif
- }
-}
-
-// 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 = MP_OBJ_TO_PTR(self_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);
-
- // call the NIC to bind the socket
- int _errno;
- if (self->nic_type->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 = MP_OBJ_TO_PTR(args[0]);
-
- if (self->nic == MP_OBJ_NULL) {
- // not connected
- // TODO I think we can listen even if not bound...
- mp_raise_OSError(MP_ENOTCONN);
- }
-
- mp_int_t backlog = MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT;
- if (n_args > 1) {
- backlog = mp_obj_get_int(args[1]);
- backlog = (backlog < 0) ? 0 : backlog;
- }
-
- int _errno;
- if (self->nic_type->listen(self, backlog, &_errno) != 0) {
- mp_raise_OSError(_errno);
- }
-
- // set socket state
- self->state = MOD_NETWORK_SS_LISTENING;
-
- 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 = MP_OBJ_TO_PTR(self_in);
-
- if (self->nic == MP_OBJ_NULL) {
- // not bound
- mp_raise_OSError(MP_EINVAL);
- }
-
- // create new socket object
- // starts with empty NIC so that finaliser doesn't run close() method if accept() fails
- mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
- socket2->base.type = &socket_type;
- socket2->nic = MP_OBJ_NULL;
- socket2->nic_type = NULL;
-
- // set the same address family, socket type and protocol as parent
- socket2->domain = self->domain;
- socket2->type = self->type;
- socket2->proto = self->proto;
- socket2->bound = false;
- socket2->fileno = -1;
- socket2->timeout = -1;
- socket2->callback = MP_OBJ_NULL;
- socket2->state = MOD_NETWORK_SS_NEW;
- #if MICROPY_PY_USOCKET_EXTENDED_STATE
- socket2->_private = NULL;
- #endif
-
- // accept incoming connection
- uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
- mp_uint_t port;
- int _errno;
- if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) {
- mp_raise_OSError(_errno);
- }
-
- // new socket has valid state, so set the NIC to the same as parent
- socket2->nic = self->nic;
- socket2->nic_type = self->nic_type;
-
- // make the return value
- mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
- client->items[0] = MP_OBJ_FROM_PTR(socket2);
- client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
-
- return MP_OBJ_FROM_PTR(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 = MP_OBJ_TO_PTR(self_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);
-
- // call the NIC to connect the socket
- int _errno;
- if (self->nic_type->connect(self, ip, port, &_errno) != 0) {
- mp_raise_OSError(_errno);
- }
-
- // set socket state
- self->state = MOD_NETWORK_SS_CONNECTED;
-
- 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 = MP_OBJ_TO_PTR(self_in);
- if (self->nic == MP_OBJ_NULL) {
- // not connected
- mp_raise_OSError(MP_EPIPE);
- }
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
- int _errno;
- mp_uint_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
- if (ret == -1) {
- mp_raise_OSError(_errno);
- }
- return mp_obj_new_int_from_uint(ret);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
-
-STATIC mp_obj_t socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
- mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->nic == MP_OBJ_NULL) {
- // not connected
- mp_raise_OSError(MP_EPIPE);
- }
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
-
- int _errno;
- mp_uint_t ret = 0;
- if (self->timeout == 0) {
- ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
- if (ret == -1) {
- mp_raise_OSError(_errno);
- } else if (bufinfo.len > ret) {
- mp_raise_OSError(MP_EAGAIN);
- }
- } else {
- // TODO: In CPython3.5, socket timeout should apply to the
- // entire sendall() operation, not to individual send() chunks.
- while (bufinfo.len != 0) {
- ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
- if (ret == -1) {
- mp_raise_OSError(_errno);
- }
- bufinfo.len -= ret;
- bufinfo.buf = (char *)bufinfo.buf + ret;
- }
- }
- return mp_obj_new_int_from_uint(ret);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_sendall_obj, socket_sendall);
-
-// 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 = MP_OBJ_TO_PTR(self_in);
- if (self->nic == MP_OBJ_NULL) {
- // not connected
- mp_raise_OSError(MP_ENOTCONN);
- }
- mp_int_t len = mp_obj_get_int(len_in);
- vstr_t vstr;
- vstr_init_len(&vstr, len);
- int _errno;
- mp_uint_t ret = self->nic_type->recv(self, (byte *)vstr.buf, len, &_errno);
- if (ret == -1) {
- mp_raise_OSError(_errno);
- }
- if (ret == 0) {
- return mp_const_empty_bytes;
- }
- vstr.len = ret;
- 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 = MP_OBJ_TO_PTR(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_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);
-
- // call the NIC to sendto
- int _errno;
- mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
- if (ret == -1) {
- 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 = MP_OBJ_TO_PTR(self_in);
- if (self->nic == MP_OBJ_NULL) {
- // not connected
- mp_raise_OSError(MP_ENOTCONN);
- }
- vstr_t vstr;
- vstr_init_len(&vstr, mp_obj_get_int(len_in));
- byte ip[4];
- mp_uint_t port;
- int _errno;
- mp_int_t ret = self->nic_type->recvfrom(self, (byte *)vstr.buf, vstr.len, ip, &port, &_errno);
- if (ret == -1) {
- mp_raise_OSError(_errno);
- }
- mp_obj_t tuple[2];
- if (ret == 0) {
- tuple[0] = mp_const_empty_bytes;
- } else {
- vstr.len = ret;
- tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
- }
- tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
- 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 = MP_OBJ_TO_PTR(args[0]);
-
- if (self->nic == MP_OBJ_NULL) {
- // bind to default NIC.
- uint8_t ip[4] = {0, 0, 0, 0};
- socket_select_nic(self, ip);
- }
-
- 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 if (opt == 20 && args[3] == mp_const_none) {
- optval = MP_OBJ_NULL;
- optlen = 0;
- } else if (opt == 20 && mp_obj_is_callable(args[3])) {
- optval = args[3];
- optlen = sizeof(optval);
- } 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 (self->nic_type->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);
-
-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, 3, socket_makefile);
-
-// 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 = MP_OBJ_TO_PTR(self_in);
- mp_uint_t timeout;
- if (timeout_in == mp_const_none) {
- timeout = -1;
- } else {
- #if MICROPY_PY_BUILTINS_FLOAT
- timeout = (mp_uint_t)(MICROPY_FLOAT_CONST(1000.0) * mp_obj_get_float(timeout_in));
- #else
- timeout = 1000 * mp_obj_get_int(timeout_in);
- #endif
- }
- if (self->nic == MP_OBJ_NULL) {
- #if MICROPY_PY_USOCKET_EXTENDED_STATE
- // store the timeout in the socket state until a NIC is bound
- self->timeout = timeout;
- #else
- // not connected
- mp_raise_OSError(MP_ENOTCONN);
- #endif
- } else {
- int _errno;
- if (self->nic_type->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 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_sendall_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_makefile), MP_ROM_PTR(&socket_makefile_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_read), MP_ROM_PTR(&mp_stream_read_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_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
- mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->nic == MP_OBJ_NULL) {
- return MP_STREAM_ERROR;
- }
- mp_int_t ret = self->nic_type->recv(self, (byte *)buf, size, errcode);
- if (ret < 0) {
- ret = MP_STREAM_ERROR;
- }
- return ret;
-}
-
-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 = MP_OBJ_TO_PTR(self_in);
- if (self->nic == MP_OBJ_NULL) {
- return MP_STREAM_ERROR;
- }
- mp_int_t ret = self->nic_type->send(self, buf, size, errcode);
- if (ret < 0) {
- ret = MP_STREAM_ERROR;
- }
- return ret;
-}
-
-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);
- if (request == MP_STREAM_CLOSE) {
- if (self->nic != MP_OBJ_NULL) {
- self->nic_type->close(self);
- self->nic = MP_OBJ_NULL;
- }
- self->state = MOD_NETWORK_SS_CLOSED;
- return 0;
- }
- if (self->nic == MP_OBJ_NULL) {
- if (request == MP_STREAM_POLL) {
- if (self->state == MOD_NETWORK_SS_NEW) {
- // New sockets are writable and not connected.
- return MP_STREAM_POLL_HUP | MP_STREAM_POLL_WR;
- } else if (self->state == MOD_NETWORK_SS_CLOSED) {
- // Closed socket, return invalid.
- return MP_STREAM_POLL_NVAL;
- }
- }
- *errcode = MP_EINVAL;
- return MP_STREAM_ERROR;
- }
- return self->nic_type->ioctl(self, request, arg, errcode);
-}
-
-STATIC 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,
- .print = socket_print,
- .make_new = socket_make_new,
- .protocol = &socket_stream_p,
- .locals_dict = (mp_obj_dict_t *)&socket_locals_dict,
-};
-
-/******************************************************************************/
-// usocket module
-
-// function usocket.getaddrinfo(host, port)
-STATIC mp_obj_t mod_usocket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
- size_t hlen;
- const char *host = mp_obj_str_get_data(args[0], &hlen);
- mp_int_t port = mp_obj_get_int(args[1]);
- uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE];
- bool have_ip = false;
-
- // if constraints were passed then check they are compatible with the supported params
- if (n_args > 2) {
- mp_int_t family = mp_obj_get_int(args[2]);
- mp_int_t type = 0;
- mp_int_t proto = 0;
- mp_int_t flags = 0;
- if (n_args > 3) {
- type = mp_obj_get_int(args[3]);
- if (n_args > 4) {
- proto = mp_obj_get_int(args[4]);
- if (n_args > 5) {
- flags = mp_obj_get_int(args[5]);
- }
- }
- }
- if (!((family == 0 || family == MOD_NETWORK_AF_INET)
- && (type == 0 || type == MOD_NETWORK_SOCK_STREAM)
- && proto == 0
- && flags == 0)) {
- mp_warning(MP_WARN_CAT(RuntimeWarning), "unsupported getaddrinfo constraints");
- }
- }
-
- if (hlen > 0) {
- // check if host is already in IP form
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- netutils_parse_ipv4_addr(args[0], out_ip, NETUTILS_BIG);
- have_ip = true;
- nlr_pop();
- } else {
- // swallow exception: host was not in IP form so need to do DNS lookup
- }
- }
-
- if (!have_ip) {
- // find a NIC that can do a name lookup
- 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];
- 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);
- if (ret != 0) {
- mp_raise_OSError(ret);
- }
- have_ip = true;
- break;
- }
- }
- }
-
- if (!have_ip) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("no available NIC"));
- }
-
- mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
- tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
- tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_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_BIG);
- return mp_obj_new_list(1, (mp_obj_t *)&tuple);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_usocket_getaddrinfo_obj, 2, 6, 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(MOD_NETWORK_AF_INET) },
- { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) },
-
- { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
- { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
- { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
-
- { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(MOD_NETWORK_SOL_SOCKET) },
- { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(MOD_NETWORK_SO_REUSEADDR) },
- { MP_ROM_QSTR(MP_QSTR_SO_KEEPALIVE), MP_ROM_INT(MOD_NETWORK_SO_KEEPALIVE) },
- { MP_ROM_QSTR(MP_QSTR_SO_SNDTIMEO), MP_ROM_INT(MOD_NETWORK_SO_SNDTIMEO) },
- { MP_ROM_QSTR(MP_QSTR_SO_RCVTIMEO), MP_ROM_INT(MOD_NETWORK_SO_RCVTIMEO) },
-
- /*
- { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(MOD_NETWORK_IPPROTO_IP) },
- { MP_ROM_QSTR(MP_QSTR_IPPROTO_ICMP), MP_ROM_INT(MOD_NETWORK_IPPROTO_ICMP) },
- { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV4), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV4) },
- { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(MOD_NETWORK_IPPROTO_TCP) },
- { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(MOD_NETWORK_IPPROTO_UDP) },
- { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV6), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV6) },
- { MP_ROM_QSTR(MP_QSTR_IPPROTO_RAW), MP_ROM_INT(MOD_NETWORK_IPPROTO_RAW) },
- */
-};
-
-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,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_usocket);
-
-#endif // MICROPY_PY_NETWORK && MICROPY_PY_USOCKET && !MICROPY_PY_LWIP
diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c
deleted file mode 100644
index 9ba613a3e89e0..0000000000000
--- a/extmod/modussl_axtls.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015-2019 Paul Sokolovsky
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-#include "py/runtime.h"
-#include "py/stream.h"
-#include "py/objstr.h"
-
-#if MICROPY_PY_USSL && MICROPY_SSL_AXTLS
-
-#include "ssl.h"
-
-typedef struct _mp_obj_ssl_socket_t {
- mp_obj_base_t base;
- mp_obj_t sock;
- SSL_CTX *ssl_ctx;
- SSL *ssl_sock;
- byte *buf;
- uint32_t bytes_left;
- bool blocking;
-} mp_obj_ssl_socket_t;
-
-struct ssl_args {
- mp_arg_val_t key;
- mp_arg_val_t cert;
- mp_arg_val_t server_side;
- mp_arg_val_t server_hostname;
- mp_arg_val_t do_handshake;
-};
-
-STATIC const mp_obj_type_t ussl_socket_type;
-
-// Table of error strings corresponding to SSL_xxx error codes.
-STATIC const char *const ssl_error_tab1[] = {
- "NOT_OK",
- "DEAD",
- "CLOSE_NOTIFY",
- "EAGAIN",
-};
-STATIC const char *const ssl_error_tab2[] = {
- "CONN_LOST",
- "RECORD_OVERFLOW",
- "SOCK_SETUP_FAILURE",
- NULL,
- "INVALID_HANDSHAKE",
- "INVALID_PROT_MSG",
- "INVALID_HMAC",
- "INVALID_VERSION",
- "UNSUPPORTED_EXTENSION",
- "INVALID_SESSION",
- "NO_CIPHER",
- "INVALID_CERT_HASH_ALG",
- "BAD_CERTIFICATE",
- "INVALID_KEY",
- NULL,
- "FINISHED_INVALID",
- "NO_CERT_DEFINED",
- "NO_CLIENT_RENOG",
- "NOT_SUPPORTED",
-};
-
-STATIC NORETURN void ussl_raise_error(int err) {
- MP_STATIC_ASSERT(SSL_NOT_OK - 3 == SSL_EAGAIN);
- MP_STATIC_ASSERT(SSL_ERROR_CONN_LOST - 18 == SSL_ERROR_NOT_SUPPORTED);
-
- // Check if err corresponds to something in one of the error string tables.
- const char *errstr = NULL;
- if (SSL_NOT_OK >= err && err >= SSL_EAGAIN) {
- errstr = ssl_error_tab1[SSL_NOT_OK - err];
- } else if (SSL_ERROR_CONN_LOST >= err && err >= SSL_ERROR_NOT_SUPPORTED) {
- errstr = ssl_error_tab2[SSL_ERROR_CONN_LOST - err];
- }
-
- // Unknown error, just raise the error code.
- if (errstr == NULL) {
- mp_raise_OSError(err);
- }
-
- // Construct string object.
- mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
- if (o_str == NULL) {
- mp_raise_OSError(err);
- }
- o_str->base.type = &mp_type_str;
- o_str->data = (const byte *)errstr;
- o_str->len = strlen((char *)o_str->data);
- o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
-
- // Raise OSError(err, str).
- mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(err), MP_OBJ_FROM_PTR(o_str)};
- nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
-}
-
-
-STATIC mp_obj_ssl_socket_t *ussl_socket_new(mp_obj_t sock, struct ssl_args *args) {
- #if MICROPY_PY_USSL_FINALISER
- mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
- #else
- mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
- #endif
- o->base.type = &ussl_socket_type;
- o->buf = NULL;
- o->bytes_left = 0;
- o->sock = sock;
- o->blocking = true;
-
- uint32_t options = SSL_SERVER_VERIFY_LATER;
- if (!args->do_handshake.u_bool) {
- options |= SSL_CONNECT_IN_PARTS;
- }
- if (args->key.u_obj != mp_const_none) {
- options |= SSL_NO_DEFAULT_KEY;
- }
- if ((o->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) {
- mp_raise_OSError(MP_EINVAL);
- }
-
- if (args->key.u_obj != mp_const_none) {
- size_t len;
- const byte *data = (const byte *)mp_obj_str_get_data(args->key.u_obj, &len);
- int res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_RSA_KEY, data, len, NULL);
- if (res != SSL_OK) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
- }
-
- data = (const byte *)mp_obj_str_get_data(args->cert.u_obj, &len);
- res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_X509_CERT, data, len, NULL);
- if (res != SSL_OK) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
- }
- }
-
- if (args->server_side.u_bool) {
- o->ssl_sock = ssl_server_new(o->ssl_ctx, (long)sock);
- } else {
- SSL_EXTENSIONS *ext = ssl_ext_new();
-
- if (args->server_hostname.u_obj != mp_const_none) {
- ext->host_name = (char *)mp_obj_str_get_str(args->server_hostname.u_obj);
- }
-
- o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext);
-
- if (args->do_handshake.u_bool) {
- int r = ssl_handshake_status(o->ssl_sock);
-
- if (r != SSL_OK) {
- if (r == SSL_CLOSE_NOTIFY) { // EOF
- r = MP_ENOTCONN;
- } else if (r == SSL_EAGAIN) {
- r = MP_EAGAIN;
- }
- ussl_raise_error(r);
- }
- }
-
- }
-
- return o;
-}
-
-STATIC void ussl_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- (void)kind;
- mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
- mp_printf(print, "<_SSLSocket %p>", self->ssl_sock);
-}
-
-STATIC mp_uint_t ussl_socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
- mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
-
- if (o->ssl_sock == NULL) {
- *errcode = EBADF;
- return MP_STREAM_ERROR;
- }
-
- while (o->bytes_left == 0) {
- mp_int_t r = ssl_read(o->ssl_sock, &o->buf);
- if (r == SSL_OK) {
- // SSL_OK from ssl_read() means "everything is ok, but there's
- // no user data yet". It may happen e.g. if handshake is not
- // finished yet. The best way we can treat it is by returning
- // EAGAIN. This may be a bit unexpected in blocking mode, but
- // default is to perform complete handshake in constructor, so
- // this should not happen in blocking mode. On the other hand,
- // in nonblocking mode EAGAIN (comparing to the alternative of
- // looping) is really preferrable.
- if (o->blocking) {
- continue;
- } else {
- goto eagain;
- }
- }
- if (r < 0) {
- if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) {
- // EOF
- return 0;
- }
- if (r == SSL_EAGAIN) {
- eagain:
- r = MP_EAGAIN;
- }
- *errcode = r;
- return MP_STREAM_ERROR;
- }
- o->bytes_left = r;
- }
-
- if (size > o->bytes_left) {
- size = o->bytes_left;
- }
- memcpy(buf, o->buf, size);
- o->buf += size;
- o->bytes_left -= size;
- return size;
-}
-
-STATIC mp_uint_t ussl_socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
- mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
-
- if (o->ssl_sock == NULL) {
- *errcode = EBADF;
- return MP_STREAM_ERROR;
- }
-
- mp_int_t r;
-eagain:
- r = ssl_write(o->ssl_sock, buf, size);
- if (r == 0) {
- // see comment in ussl_socket_read above
- if (o->blocking) {
- goto eagain;
- } else {
- r = SSL_EAGAIN;
- }
- }
- if (r < 0) {
- if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) {
- return 0; // EOF
- }
- if (r == SSL_EAGAIN) {
- r = MP_EAGAIN;
- }
- *errcode = r;
- return MP_STREAM_ERROR;
- }
- return r;
-}
-
-STATIC mp_uint_t ussl_socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
- mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
- if (request == MP_STREAM_CLOSE && self->ssl_sock != NULL) {
- ssl_free(self->ssl_sock);
- ssl_ctx_free(self->ssl_ctx);
- self->ssl_sock = NULL;
- }
- // Pass all requests down to the underlying socket
- return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode);
-}
-
-STATIC mp_obj_t ussl_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
- mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in);
- mp_obj_t sock = o->sock;
- mp_obj_t dest[3];
- mp_load_method(sock, MP_QSTR_setblocking, dest);
- dest[2] = flag_in;
- mp_obj_t res = mp_call_method_n_kw(1, 0, dest);
- o->blocking = mp_obj_is_true(flag_in);
- return res;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(ussl_socket_setblocking_obj, ussl_socket_setblocking);
-
-STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&ussl_socket_setblocking_obj) },
- { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
- #if MICROPY_PY_USSL_FINALISER
- { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
-
-STATIC const mp_stream_p_t ussl_socket_stream_p = {
- .read = ussl_socket_read,
- .write = ussl_socket_write,
- .ioctl = ussl_socket_ioctl,
-};
-
-STATIC const mp_obj_type_t ussl_socket_type = {
- { &mp_type_type },
- // Save on qstr's, reuse same as for module
- .name = MP_QSTR_ussl,
- .print = ussl_socket_print,
- .getiter = NULL,
- .iternext = NULL,
- .protocol = &ussl_socket_stream_p,
- .locals_dict = (void *)&ussl_socket_locals_dict,
-};
-
-STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- // TODO: Implement more args
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
- };
-
- // TODO: Check that sock implements stream protocol
- mp_obj_t sock = pos_args[0];
-
- struct ssl_args args;
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
- MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
-
- return MP_OBJ_FROM_PTR(ussl_socket_new(sock, &args));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
-
-STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
- { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
-
-const mp_obj_module_t mp_module_ussl = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_ussl, mp_module_ussl);
-
-#endif // MICROPY_PY_USSL && MICROPY_SSL_AXTLS
diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c
deleted file mode 100644
index 44668ae63bbad..0000000000000
--- a/extmod/modussl_mbedtls.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016 Linaro Ltd.
- * Copyright (c) 2019 Paul Sokolovsky
- *
- * 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_USSL && MICROPY_SSL_MBEDTLS
-
-#include
-#include
-#include // needed because mp_is_nonblocking_error uses system error codes
-
-#include "py/runtime.h"
-#include "py/stream.h"
-#include "py/objstr.h"
-
-// mbedtls_time_t
-#include "mbedtls/platform.h"
-#include "mbedtls/ssl.h"
-#include "mbedtls/x509_crt.h"
-#include "mbedtls/pk.h"
-#include "mbedtls/entropy.h"
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/debug.h"
-#include "mbedtls/error.h"
-
-typedef struct _mp_obj_ssl_socket_t {
- mp_obj_base_t base;
- mp_obj_t sock;
- mbedtls_entropy_context entropy;
- mbedtls_ctr_drbg_context ctr_drbg;
- mbedtls_ssl_context ssl;
- mbedtls_ssl_config conf;
- mbedtls_x509_crt cacert;
- mbedtls_x509_crt cert;
- mbedtls_pk_context pkey;
-} mp_obj_ssl_socket_t;
-
-struct ssl_args {
- mp_arg_val_t key;
- mp_arg_val_t cert;
- mp_arg_val_t server_side;
- mp_arg_val_t server_hostname;
- mp_arg_val_t do_handshake;
-};
-
-STATIC const mp_obj_type_t ussl_socket_type;
-
-#ifdef MBEDTLS_DEBUG_C
-STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
- (void)ctx;
- (void)level;
- printf("DBG:%s:%04d: %s\n", file, line, str);
-}
-#endif
-
-STATIC NORETURN void mbedtls_raise_error(int err) {
- // _mbedtls_ssl_send and _mbedtls_ssl_recv (below) turn positive error codes from the
- // underlying socket into negative codes to pass them through mbedtls. Here we turn them
- // positive again so they get interpreted as the OSError they really are. The
- // cut-off of -256 is a bit hacky, sigh.
- if (err < 0 && err > -256) {
- mp_raise_OSError(-err);
- }
-
- #if defined(MBEDTLS_ERROR_C)
- // Including mbedtls_strerror takes about 1.5KB due to the error strings.
- // MBEDTLS_ERROR_C is the define used by mbedtls to conditionally include mbedtls_strerror.
- // It is set/unset in the MBEDTLS_CONFIG_FILE which is defined in the Makefile.
-
- // Try to allocate memory for the message
- #define ERR_STR_MAX 80 // mbedtls_strerror truncates if it doesn't fit
- mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
- byte *o_str_buf = m_new_maybe(byte, ERR_STR_MAX);
- if (o_str == NULL || o_str_buf == NULL) {
- mp_raise_OSError(err);
- }
-
- // print the error message into the allocated buffer
- mbedtls_strerror(err, (char *)o_str_buf, ERR_STR_MAX);
- size_t len = strlen((char *)o_str_buf);
-
- // Put the exception object together
- o_str->base.type = &mp_type_str;
- o_str->data = o_str_buf;
- o_str->len = len;
- o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
- // raise
- mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(err), MP_OBJ_FROM_PTR(o_str)};
- nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
- #else
- // mbedtls is compiled without error strings so we simply return the err number
- mp_raise_OSError(err); // err is typically a large negative number
- #endif
-}
-
-STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
- mp_obj_t sock = *(mp_obj_t *)ctx;
-
- const mp_stream_p_t *sock_stream = mp_get_stream(sock);
- int err;
-
- mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err);
- if (out_sz == MP_STREAM_ERROR) {
- if (mp_is_nonblocking_error(err)) {
- return MBEDTLS_ERR_SSL_WANT_WRITE;
- }
- return -err; // convert an MP_ERRNO to something mbedtls passes through as error
- } else {
- return out_sz;
- }
-}
-
-// _mbedtls_ssl_recv is called by mbedtls to receive bytes from the underlying socket
-STATIC int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
- mp_obj_t sock = *(mp_obj_t *)ctx;
-
- const mp_stream_p_t *sock_stream = mp_get_stream(sock);
- int err;
-
- mp_uint_t out_sz = sock_stream->read(sock, buf, len, &err);
- if (out_sz == MP_STREAM_ERROR) {
- if (mp_is_nonblocking_error(err)) {
- return MBEDTLS_ERR_SSL_WANT_READ;
- }
- return -err;
- } else {
- return out_sz;
- }
-}
-
-
-STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
- // Verify the socket object has the full stream protocol
- mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
-
- #if MICROPY_PY_USSL_FINALISER
- mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
- #else
- mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
- #endif
- o->base.type = &ussl_socket_type;
- o->sock = sock;
-
- int ret;
- mbedtls_ssl_init(&o->ssl);
- mbedtls_ssl_config_init(&o->conf);
- mbedtls_x509_crt_init(&o->cacert);
- mbedtls_x509_crt_init(&o->cert);
- mbedtls_pk_init(&o->pkey);
- mbedtls_ctr_drbg_init(&o->ctr_drbg);
- #ifdef MBEDTLS_DEBUG_C
- // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
- mbedtls_debug_set_threshold(0);
- #endif
-
- mbedtls_entropy_init(&o->entropy);
- const byte seed[] = "upy";
- ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, mbedtls_entropy_func, &o->entropy, seed, sizeof(seed));
- if (ret != 0) {
- goto cleanup;
- }
-
- ret = mbedtls_ssl_config_defaults(&o->conf,
- args->server_side.u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
- MBEDTLS_SSL_TRANSPORT_STREAM,
- MBEDTLS_SSL_PRESET_DEFAULT);
- if (ret != 0) {
- goto cleanup;
- }
-
- mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE);
- mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg);
- #ifdef MBEDTLS_DEBUG_C
- mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL);
- #endif
-
- ret = mbedtls_ssl_setup(&o->ssl, &o->conf);
- if (ret != 0) {
- goto cleanup;
- }
-
- if (args->server_hostname.u_obj != mp_const_none) {
- const char *sni = mp_obj_str_get_str(args->server_hostname.u_obj);
- ret = mbedtls_ssl_set_hostname(&o->ssl, sni);
- if (ret != 0) {
- goto cleanup;
- }
- }
-
- mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
-
- if (args->key.u_obj != mp_const_none) {
- size_t key_len;
- const byte *key = (const byte *)mp_obj_str_get_data(args->key.u_obj, &key_len);
- // len should include terminating null
- ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0);
- if (ret != 0) {
- ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; // use general error for all key errors
- goto cleanup;
- }
-
- size_t cert_len;
- const byte *cert = (const byte *)mp_obj_str_get_data(args->cert.u_obj, &cert_len);
- // len should include terminating null
- ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1);
- if (ret != 0) {
- ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors
- goto cleanup;
- }
-
- ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey);
- if (ret != 0) {
- goto cleanup;
- }
- }
-
- if (args->do_handshake.u_bool) {
- while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) {
- if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
- goto cleanup;
- }
- #ifdef MICROPY_EVENT_POLL_HOOK
- MICROPY_EVENT_POLL_HOOK
- #endif
- }
- }
-
- return o;
-
-cleanup:
- mbedtls_pk_free(&o->pkey);
- mbedtls_x509_crt_free(&o->cert);
- mbedtls_x509_crt_free(&o->cacert);
- mbedtls_ssl_free(&o->ssl);
- mbedtls_ssl_config_free(&o->conf);
- mbedtls_ctr_drbg_free(&o->ctr_drbg);
- mbedtls_entropy_free(&o->entropy);
-
- if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
- mp_raise_OSError(MP_ENOMEM);
- } else if (ret == MBEDTLS_ERR_PK_BAD_INPUT_DATA) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
- } else if (ret == MBEDTLS_ERR_X509_BAD_INPUT_DATA) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
- } else {
- mbedtls_raise_error(ret);
- }
-}
-
-STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
- mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
- if (!mp_obj_is_true(binary_form)) {
- mp_raise_NotImplementedError(NULL);
- }
- const mbedtls_x509_crt *peer_cert = mbedtls_ssl_get_peer_cert(&o->ssl);
- if (peer_cert == NULL) {
- return mp_const_none;
- }
- return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert);
-
-STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- (void)kind;
- mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
- mp_printf(print, "<_SSLSocket %p>", self);
-}
-
-STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
- mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
-
- int ret = mbedtls_ssl_read(&o->ssl, buf, size);
- if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
- // end of stream
- return 0;
- }
- if (ret >= 0) {
- return ret;
- }
- if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
- ret = MP_EWOULDBLOCK;
- } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- // If handshake is not finished, read attempt may end up in protocol
- // wanting to write next handshake message. The same may happen with
- // renegotation.
- ret = MP_EWOULDBLOCK;
- }
- *errcode = ret;
- return MP_STREAM_ERROR;
-}
-
-STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
- mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
-
- int ret = mbedtls_ssl_write(&o->ssl, buf, size);
- if (ret >= 0) {
- return ret;
- }
- if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
- ret = MP_EWOULDBLOCK;
- } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
- // If handshake is not finished, write attempt may end up in protocol
- // wanting to read next handshake message. The same may happen with
- // renegotation.
- ret = MP_EWOULDBLOCK;
- }
- *errcode = ret;
- return MP_STREAM_ERROR;
-}
-
-STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
- mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in);
- mp_obj_t sock = o->sock;
- mp_obj_t dest[3];
- mp_load_method(sock, MP_QSTR_setblocking, dest);
- dest[2] = flag_in;
- return mp_call_method_n_kw(1, 0, dest);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
-
-STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
- mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
- if (request == MP_STREAM_CLOSE) {
- mbedtls_pk_free(&self->pkey);
- mbedtls_x509_crt_free(&self->cert);
- mbedtls_x509_crt_free(&self->cacert);
- mbedtls_ssl_free(&self->ssl);
- mbedtls_ssl_config_free(&self->conf);
- mbedtls_ctr_drbg_free(&self->ctr_drbg);
- mbedtls_entropy_free(&self->entropy);
- }
- // Pass all requests down to the underlying socket
- return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode);
-}
-
-STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
- { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
- #if MICROPY_PY_USSL_FINALISER
- { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
- #endif
- { MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
-
-STATIC const mp_stream_p_t ussl_socket_stream_p = {
- .read = socket_read,
- .write = socket_write,
- .ioctl = socket_ioctl,
-};
-
-STATIC const mp_obj_type_t ussl_socket_type = {
- { &mp_type_type },
- // Save on qstr's, reuse same as for module
- .name = MP_QSTR_ussl,
- .print = socket_print,
- .getiter = NULL,
- .iternext = NULL,
- .protocol = &ussl_socket_stream_p,
- .locals_dict = (void *)&ussl_socket_locals_dict,
-};
-
-STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- // TODO: Implement more args
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
- };
-
- // TODO: Check that sock implements stream protocol
- mp_obj_t sock = pos_args[0];
-
- struct ssl_args args;
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
- MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
-
- return MP_OBJ_FROM_PTR(socket_new(sock, &args));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
-
-STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
- { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
-
-const mp_obj_module_t mp_module_ussl = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_ussl, mp_module_ussl);
-
-#endif // MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS
diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c
deleted file mode 100644
index 1dde90bd1b026..0000000000000
--- a/extmod/modutimeq.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Damien P. George
- * Copyright (c) 2016-2017 Paul Sokolovsky
- *
- * 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 "py/objlist.h"
-#include "py/runtime.h"
-#include "py/smallint.h"
-
-#if MICROPY_PY_UTIMEQ
-
-#define MODULO MICROPY_PY_UTIME_TICKS_PERIOD
-
-#define DEBUG 0
-
-// the algorithm here is modelled on CPython's heapq.py
-
-struct qentry {
- mp_uint_t time;
- mp_uint_t id;
- mp_obj_t callback;
- mp_obj_t args;
-};
-
-typedef struct _mp_obj_utimeq_t {
- mp_obj_base_t base;
- mp_uint_t alloc;
- mp_uint_t len;
- struct qentry items[];
-} mp_obj_utimeq_t;
-
-STATIC mp_uint_t utimeq_id;
-
-STATIC mp_obj_utimeq_t *utimeq_get_heap(mp_obj_t heap_in) {
- return MP_OBJ_TO_PTR(heap_in);
-}
-
-STATIC bool time_less_than(struct qentry *item, struct qentry *parent) {
- mp_uint_t item_tm = item->time;
- mp_uint_t parent_tm = parent->time;
- mp_uint_t res = parent_tm - item_tm;
- if (res == 0) {
- // TODO: This actually should use the same "ring" logic
- // as for time, to avoid artifacts when id's overflow.
- return item->id < parent->id;
- }
- if ((mp_int_t)res < 0) {
- res += MODULO;
- }
- return res && res < (MODULO / 2);
-}
-
-STATIC mp_obj_t utimeq_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, 1, 1, false);
- mp_uint_t alloc = mp_obj_get_int(args[0]);
- mp_obj_utimeq_t *o = mp_obj_malloc_var(mp_obj_utimeq_t, struct qentry, alloc, type);
- memset(o->items, 0, sizeof(*o->items) * alloc);
- o->alloc = alloc;
- o->len = 0;
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC void utimeq_heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
- struct qentry item = heap->items[pos];
- while (pos > start_pos) {
- mp_uint_t parent_pos = (pos - 1) >> 1;
- struct qentry *parent = &heap->items[parent_pos];
- bool lessthan = time_less_than(&item, parent);
- if (lessthan) {
- heap->items[pos] = *parent;
- pos = parent_pos;
- } else {
- break;
- }
- }
- heap->items[pos] = item;
-}
-
-STATIC void utimeq_heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) {
- mp_uint_t start_pos = pos;
- mp_uint_t end_pos = heap->len;
- struct qentry item = heap->items[pos];
- for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) {
- // choose right child if it's <= left child
- if (child_pos + 1 < end_pos) {
- bool lessthan = time_less_than(&heap->items[child_pos], &heap->items[child_pos + 1]);
- if (!lessthan) {
- child_pos += 1;
- }
- }
- // bubble up the smaller child
- heap->items[pos] = heap->items[child_pos];
- pos = child_pos;
- }
- heap->items[pos] = item;
- utimeq_heap_siftdown(heap, start_pos, pos);
-}
-
-STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
- mp_obj_t heap_in = args[0];
- mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
- if (heap->len == heap->alloc) {
- mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("queue overflow"));
- }
- mp_uint_t l = heap->len;
- heap->items[l].time = MP_OBJ_SMALL_INT_VALUE(args[1]);
- heap->items[l].id = utimeq_id++;
- heap->items[l].callback = args[2];
- heap->items[l].args = args[3];
- utimeq_heap_siftdown(heap, 0, heap->len);
- heap->len++;
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_heappush_obj, 4, 4, mod_utimeq_heappush);
-
-STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
- mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
- if (heap->len == 0) {
- mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
- }
- mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref);
- if (!mp_obj_is_type(list_ref, &mp_type_list) || ret->len < 3) {
- mp_raise_TypeError(NULL);
- }
-
- struct qentry *item = &heap->items[0];
- ret->items[0] = MP_OBJ_NEW_SMALL_INT(item->time);
- ret->items[1] = item->callback;
- ret->items[2] = item->args;
- heap->len -= 1;
- heap->items[0] = heap->items[heap->len];
- heap->items[heap->len].callback = MP_OBJ_NULL; // so we don't retain a pointer
- heap->items[heap->len].args = MP_OBJ_NULL;
- if (heap->len) {
- utimeq_heap_siftup(heap, 0);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop);
-
-STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) {
- mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
- if (heap->len == 0) {
- mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
- }
-
- struct qentry *item = &heap->items[0];
- return MP_OBJ_NEW_SMALL_INT(item->time);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_peektime_obj, mod_utimeq_peektime);
-
-#if DEBUG
-STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) {
- mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
- for (int i = 0; i < heap->len; i++) {
- printf(UINT_FMT "\t%p\t%p\n", heap->items[i].time,
- MP_OBJ_TO_PTR(heap->items[i].callback), MP_OBJ_TO_PTR(heap->items[i].args));
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_dump_obj, mod_utimeq_dump);
-#endif
-
-STATIC mp_obj_t utimeq_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
- mp_obj_utimeq_t *self = MP_OBJ_TO_PTR(self_in);
- switch (op) {
- case MP_UNARY_OP_BOOL:
- return mp_obj_new_bool(self->len != 0);
- case MP_UNARY_OP_LEN:
- return MP_OBJ_NEW_SMALL_INT(self->len);
- default:
- return MP_OBJ_NULL; // op not supported
- }
-}
-
-STATIC const mp_rom_map_elem_t utimeq_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&mod_utimeq_heappush_obj) },
- { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&mod_utimeq_heappop_obj) },
- { MP_ROM_QSTR(MP_QSTR_peektime), MP_ROM_PTR(&mod_utimeq_peektime_obj) },
- #if DEBUG
- { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_utimeq_dump_obj) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(utimeq_locals_dict, utimeq_locals_dict_table);
-
-STATIC const mp_obj_type_t utimeq_type = {
- { &mp_type_type },
- .name = MP_QSTR_utimeq,
- .make_new = utimeq_make_new,
- .unary_op = utimeq_unary_op,
- .locals_dict = (void *)&utimeq_locals_dict,
-};
-
-STATIC const mp_rom_map_elem_t mp_module_utimeq_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utimeq) },
- { MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&utimeq_type) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_utimeq_globals, mp_module_utimeq_globals_table);
-
-const mp_obj_module_t mp_module_utimeq = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_utimeq_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_utimeq, mp_module_utimeq);
-
-#endif // MICROPY_PY_UTIMEQ
diff --git a/extmod/moduwebsocket.c b/extmod/moduwebsocket.c
deleted file mode 100644
index a9ad0c22e3a51..0000000000000
--- a/extmod/moduwebsocket.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016 Paul Sokolovsky
- *
- * 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/runtime.h"
-#include "py/stream.h"
-#include "extmod/moduwebsocket.h"
-
-#if MICROPY_PY_UWEBSOCKET
-
-enum { FRAME_HEADER, FRAME_OPT, PAYLOAD, CONTROL };
-
-enum { BLOCKING_WRITE = 0x80 };
-
-typedef struct _mp_obj_websocket_t {
- mp_obj_base_t base;
- mp_obj_t sock;
- uint32_t msg_sz;
- byte mask[4];
- byte state;
- byte to_recv;
- byte mask_pos;
- byte buf_pos;
- byte buf[6];
- byte opts;
- // Copy of last data frame flags
- byte ws_flags;
- // Copy of current frame flags
- byte last_flags;
-} mp_obj_websocket_t;
-
-STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode);
-
-STATIC mp_obj_t websocket_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, 1, 2, false);
- mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
- mp_obj_websocket_t *o = mp_obj_malloc(mp_obj_websocket_t, type);
- o->sock = args[0];
- o->state = FRAME_HEADER;
- o->to_recv = 2;
- o->mask_pos = 0;
- o->buf_pos = 0;
- o->opts = FRAME_TXT;
- if (n_args > 1 && args[1] == mp_const_true) {
- o->opts |= BLOCKING_WRITE;
- }
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
- mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
- const mp_stream_p_t *stream_p = mp_get_stream(self->sock);
- while (1) {
- if (self->to_recv != 0) {
- mp_uint_t out_sz = stream_p->read(self->sock, self->buf + self->buf_pos, self->to_recv, errcode);
- if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
- return out_sz;
- }
- self->buf_pos += out_sz;
- self->to_recv -= out_sz;
- if (self->to_recv != 0) {
- *errcode = MP_EAGAIN;
- return MP_STREAM_ERROR;
- }
- }
-
- switch (self->state) {
- case FRAME_HEADER: {
- // TODO: Split frame handling below is untested so far, so conservatively disable it
- assert(self->buf[0] & 0x80);
-
- // "Control frames MAY be injected in the middle of a fragmented message."
- // So, they must be processed before data frames (and not alter
- // self->ws_flags)
- byte frame_type = self->buf[0];
- self->last_flags = frame_type;
- frame_type &= FRAME_OPCODE_MASK;
-
- if ((self->buf[0] & FRAME_OPCODE_MASK) == FRAME_CONT) {
- // Preserve previous frame type
- self->ws_flags = (self->ws_flags & FRAME_OPCODE_MASK) | (self->buf[0] & ~FRAME_OPCODE_MASK);
- } else {
- self->ws_flags = self->buf[0];
- }
-
- // Reset mask in case someone will use "simplified" protocol
- // without masks.
- memset(self->mask, 0, sizeof(self->mask));
-
- int to_recv = 0;
- size_t sz = self->buf[1] & 0x7f;
- if (sz == 126) {
- // Msg size is next 2 bytes
- to_recv += 2;
- } else if (sz == 127) {
- // Msg size is next 8 bytes
- assert(0);
- }
- if (self->buf[1] & 0x80) {
- // Next 4 bytes is mask
- to_recv += 4;
- }
-
- self->buf_pos = 0;
- self->to_recv = to_recv;
- self->msg_sz = sz; // May be overridden by FRAME_OPT
- if (to_recv != 0) {
- self->state = FRAME_OPT;
- } else {
- if (frame_type >= FRAME_CLOSE) {
- self->state = CONTROL;
- } else {
- self->state = PAYLOAD;
- }
- }
- continue;
- }
-
- case FRAME_OPT: {
- if ((self->buf_pos & 3) == 2) {
- // First two bytes are message length
- self->msg_sz = (self->buf[0] << 8) | self->buf[1];
- }
- if (self->buf_pos >= 4) {
- // Last 4 bytes is mask
- memcpy(self->mask, self->buf + self->buf_pos - 4, 4);
- }
- self->buf_pos = 0;
- if ((self->last_flags & FRAME_OPCODE_MASK) >= FRAME_CLOSE) {
- self->state = CONTROL;
- } else {
- self->state = PAYLOAD;
- }
- continue;
- }
-
- case PAYLOAD:
- case CONTROL: {
- mp_uint_t out_sz = 0;
- if (self->msg_sz == 0) {
- // In case message had zero payload
- goto no_payload;
- }
-
- size_t sz = MIN(size, self->msg_sz);
- out_sz = stream_p->read(self->sock, buf, sz, errcode);
- if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
- return out_sz;
- }
-
- sz = out_sz;
- for (byte *p = buf; sz--; p++) {
- *p ^= self->mask[self->mask_pos++ & 3];
- }
-
- self->msg_sz -= out_sz;
- if (self->msg_sz == 0) {
- byte last_state;
- no_payload:
- last_state = self->state;
- self->state = FRAME_HEADER;
- self->to_recv = 2;
- self->mask_pos = 0;
- self->buf_pos = 0;
-
- // Handle control frame
- if (last_state == CONTROL) {
- byte frame_type = self->last_flags & FRAME_OPCODE_MASK;
- if (frame_type == FRAME_CLOSE) {
- static const char close_resp[2] = {0x88, 0};
- int err;
- websocket_write(self_in, close_resp, sizeof(close_resp), &err);
- return 0;
- }
-
- // DEBUG_printf("Finished receiving ctrl message %x, ignoring\n", self->last_flags);
- continue;
- }
- }
-
- if (out_sz != 0) {
- return out_sz;
- }
- // Empty (data) frame received is not EOF
- continue;
- }
-
- }
- }
-}
-
-STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
- mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
- assert(size < 0x10000);
- byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)};
- int hdr_sz;
- if (size < 126) {
- header[1] = size;
- hdr_sz = 2;
- } else {
- header[1] = 126;
- header[2] = size >> 8;
- header[3] = size & 0xff;
- hdr_sz = 4;
- }
-
- mp_obj_t dest[3];
- if (self->opts & BLOCKING_WRITE) {
- mp_load_method(self->sock, MP_QSTR_setblocking, dest);
- dest[2] = mp_const_true;
- mp_call_method_n_kw(1, 0, dest);
- }
-
- mp_uint_t out_sz = mp_stream_write_exactly(self->sock, header, hdr_sz, errcode);
- if (*errcode == 0) {
- out_sz = mp_stream_write_exactly(self->sock, buf, size, errcode);
- }
-
- if (self->opts & BLOCKING_WRITE) {
- dest[2] = mp_const_false;
- mp_call_method_n_kw(1, 0, dest);
- }
-
- if (*errcode != 0) {
- return MP_STREAM_ERROR;
- }
- return out_sz;
-}
-
-STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
- mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
- switch (request) {
- case MP_STREAM_CLOSE:
- // TODO: Send close signaling to the other side, otherwise it's
- // abrupt close (connection abort).
- mp_stream_close(self->sock);
- return 0;
- case MP_STREAM_GET_DATA_OPTS:
- return self->ws_flags & FRAME_OPCODE_MASK;
- case MP_STREAM_SET_DATA_OPTS: {
- int cur = self->opts & FRAME_OPCODE_MASK;
- self->opts = (self->opts & ~FRAME_OPCODE_MASK) | (arg & FRAME_OPCODE_MASK);
- return cur;
- }
- default:
- *errcode = MP_EINVAL;
- return MP_STREAM_ERROR;
- }
-}
-
-STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
- { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);
-
-STATIC const mp_stream_p_t websocket_stream_p = {
- .read = websocket_read,
- .write = websocket_write,
- .ioctl = websocket_ioctl,
-};
-
-STATIC const mp_obj_type_t websocket_type = {
- { &mp_type_type },
- .name = MP_QSTR_websocket,
- .make_new = websocket_make_new,
- .protocol = &websocket_stream_p,
- .locals_dict = (void *)&websocket_locals_dict,
-};
-
-STATIC const mp_rom_map_elem_t uwebsocket_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uwebsocket) },
- { MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&websocket_type) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(uwebsocket_module_globals, uwebsocket_module_globals_table);
-
-const mp_obj_module_t mp_module_uwebsocket = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&uwebsocket_module_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_uwebsocket, mp_module_uwebsocket);
-
-#endif // MICROPY_PY_UWEBSOCKET
diff --git a/extmod/moduwebsocket.h b/extmod/moduwebsocket.h
deleted file mode 100644
index c1ea291ed7434..0000000000000
--- a/extmod/moduwebsocket.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H
-#define MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H
-
-#define FRAME_OPCODE_MASK 0x0f
-enum {
- FRAME_CONT, FRAME_TXT, FRAME_BIN,
- FRAME_CLOSE = 0x8, FRAME_PING, FRAME_PONG
-};
-
-#endif // MICROPY_INCLUDED_EXTMOD_MODUWEBSOCKET_H
diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c
deleted file mode 100644
index 0161b9f49cdd8..0000000000000
--- a/extmod/moduzlib.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014-2016 Paul Sokolovsky
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-#include "py/runtime.h"
-#include "py/stream.h"
-#include "py/mperrno.h"
-
-#if MICROPY_PY_UZLIB
-
-#include "lib/uzlib/tinf.h"
-
-#if 0 // print debugging info
-#define DEBUG_printf DEBUG_printf
-#else // don't print debugging info
-#define DEBUG_printf(...) (void)0
-#endif
-
-typedef struct _mp_obj_decompio_t {
- mp_obj_base_t base;
- mp_obj_t src_stream;
- TINF_DATA decomp;
- bool eof;
-} mp_obj_decompio_t;
-
-STATIC int read_src_stream(TINF_DATA *data) {
- byte *p = (void *)data;
- p -= offsetof(mp_obj_decompio_t, decomp);
- mp_obj_decompio_t *self = (mp_obj_decompio_t *)p;
-
- const mp_stream_p_t *stream = mp_get_stream(self->src_stream);
- int err;
- byte c;
- mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err);
- if (out_sz == MP_STREAM_ERROR) {
- mp_raise_OSError(err);
- }
- if (out_sz == 0) {
- mp_raise_type(&mp_type_EOFError);
- }
- return c;
-}
-
-STATIC mp_obj_t decompio_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, 1, 2, false);
- mp_get_stream_raise(args[0], MP_STREAM_OP_READ);
- mp_obj_decompio_t *o = mp_obj_malloc(mp_obj_decompio_t, type);
- memset(&o->decomp, 0, sizeof(o->decomp));
- o->decomp.readSource = read_src_stream;
- o->src_stream = args[0];
- o->eof = false;
-
- mp_int_t dict_opt = 0;
- uint dict_sz;
- if (n_args > 1) {
- dict_opt = mp_obj_get_int(args[1]);
- }
-
- if (dict_opt >= 16) {
- int st = uzlib_gzip_parse_header(&o->decomp);
- if (st != TINF_OK) {
- goto header_error;
- }
- dict_sz = 1 << (dict_opt - 16);
- } else if (dict_opt >= 0) {
- dict_opt = uzlib_zlib_parse_header(&o->decomp);
- if (dict_opt < 0) {
- header_error:
- mp_raise_ValueError(MP_ERROR_TEXT("compression header"));
- }
- // RFC 1950 section 2.2:
- // CINFO is the base-2 logarithm of the LZ77 window size,
- // minus eight (CINFO=7 indicates a 32K window size)
- dict_sz = 1 << (dict_opt + 8);
- } else {
- dict_sz = 1 << -dict_opt;
- }
-
- uzlib_uncompress_init(&o->decomp, m_new(byte, dict_sz), dict_sz);
- return MP_OBJ_FROM_PTR(o);
-}
-
-STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
- mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in);
- if (o->eof) {
- return 0;
- }
-
- o->decomp.dest = buf;
- o->decomp.dest_limit = (byte *)buf + size;
- int st = uzlib_uncompress_chksum(&o->decomp);
- if (st == TINF_DONE) {
- o->eof = true;
- }
- if (st < 0) {
- DEBUG_printf("uncompress error=" INT_FMT "\n", st);
- *errcode = MP_EINVAL;
- return MP_STREAM_ERROR;
- }
- return o->decomp.dest - (byte *)buf;
-}
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
-#endif
-
-STATIC const mp_stream_p_t decompio_stream_p = {
- .read = decompio_read,
-};
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_obj_type_t decompio_type = {
- { &mp_type_type },
- .name = MP_QSTR_DecompIO,
- .make_new = decompio_make_new,
- .protocol = &decompio_stream_p,
- .locals_dict = (void *)&decompio_locals_dict,
-};
-#endif
-
-STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
- mp_obj_t data = args[0];
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
-
- TINF_DATA *decomp = m_new_obj(TINF_DATA);
- memset(decomp, 0, sizeof(*decomp));
- DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp));
- uzlib_uncompress_init(decomp, NULL, 0);
- mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15;
- byte *dest_buf = m_new(byte, dest_buf_size);
-
- decomp->dest = dest_buf;
- decomp->dest_limit = dest_buf + dest_buf_size;
- DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", dest_buf_size);
- decomp->source = bufinfo.buf;
- decomp->source_limit = (byte *)bufinfo.buf + bufinfo.len;
-
- int st;
- bool is_zlib = true;
-
- if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) {
- is_zlib = false;
- }
-
- if (is_zlib) {
- st = uzlib_zlib_parse_header(decomp);
- if (st < 0) {
- goto error;
- }
- }
-
- while (1) {
- st = uzlib_uncompress_chksum(decomp);
- if (st < 0) {
- goto error;
- }
- if (st == TINF_DONE) {
- break;
- }
- size_t offset = decomp->dest - dest_buf;
- dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256);
- dest_buf_size += 256;
- decomp->dest = dest_buf + offset;
- decomp->dest_limit = decomp->dest + 256;
- }
-
- mp_uint_t final_sz = decomp->dest - dest_buf;
- DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz);
- dest_buf = (byte *)m_renew(byte, dest_buf, dest_buf_size, final_sz);
- mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf);
- m_del_obj(TINF_DATA, decomp);
- return res;
-
-error:
- mp_raise_type_arg(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress);
-
-#if !MICROPY_ENABLE_DYNRUNTIME
-STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) },
- { MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) },
- { MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table);
-
-const mp_obj_module_t mp_module_uzlib = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_uzlib_globals,
-};
-
-
-MP_REGISTER_MODULE(MP_QSTR_uzlib, mp_module_uzlib);
-#endif
-
-// Source files #include'd here to make sure they're compiled in
-// only if module is enabled by config setting.
-
-#include "lib/uzlib/tinflate.c"
-#include "lib/uzlib/tinfzlib.c"
-#include "lib/uzlib/tinfgzip.c"
-#include "lib/uzlib/adler32.c"
-#include "lib/uzlib/crc32.c"
-
-#endif // MICROPY_PY_UZLIB
diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c
index 1a2a718acfab5..64276b5a8f3bd 100644
--- a/extmod/modwebrepl.c
+++ b/extmod/modwebrepl.c
@@ -34,7 +34,7 @@
#ifdef MICROPY_PY_WEBREPL_DELAY
#include "py/mphal.h"
#endif
-#include "extmod/moduwebsocket.h"
+#include "extmod/modwebsocket.h"
#if MICROPY_PY_WEBREPL
@@ -342,13 +342,14 @@ STATIC const mp_stream_p_t webrepl_stream_p = {
.ioctl = webrepl_ioctl,
};
-STATIC const mp_obj_type_t webrepl_type = {
- { &mp_type_type },
- .name = MP_QSTR__webrepl,
- .make_new = webrepl_make_new,
- .protocol = &webrepl_stream_p,
- .locals_dict = (mp_obj_dict_t *)&webrepl_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ webrepl_type,
+ MP_QSTR__webrepl,
+ MP_TYPE_FLAG_NONE,
+ make_new, webrepl_make_new,
+ protocol, &webrepl_stream_p,
+ locals_dict, &webrepl_locals_dict
+ );
STATIC const mp_rom_map_elem_t webrepl_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__webrepl) },
diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c
new file mode 100644
index 0000000000000..d2cb72039621b
--- /dev/null
+++ b/extmod/modwebsocket.c
@@ -0,0 +1,320 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * 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/runtime.h"
+#include "py/stream.h"
+#include "extmod/modwebsocket.h"
+
+#if MICROPY_PY_WEBSOCKET
+
+enum { FRAME_HEADER, FRAME_OPT, PAYLOAD, CONTROL };
+
+enum { BLOCKING_WRITE = 0x80 };
+
+typedef struct _mp_obj_websocket_t {
+ mp_obj_base_t base;
+ mp_obj_t sock;
+ uint32_t msg_sz;
+ byte mask[4];
+ byte state;
+ byte to_recv;
+ byte mask_pos;
+ byte buf_pos;
+ byte buf[6];
+ byte opts;
+ // Copy of last data frame flags
+ byte ws_flags;
+ // Copy of current frame flags
+ byte last_flags;
+} mp_obj_websocket_t;
+
+STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode);
+
+STATIC mp_obj_t websocket_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, 1, 2, false);
+ mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
+ mp_obj_websocket_t *o = mp_obj_malloc(mp_obj_websocket_t, type);
+ o->sock = args[0];
+ o->state = FRAME_HEADER;
+ o->to_recv = 2;
+ o->mask_pos = 0;
+ o->buf_pos = 0;
+ o->opts = FRAME_TXT;
+ if (n_args > 1 && args[1] == mp_const_true) {
+ o->opts |= BLOCKING_WRITE;
+ }
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
+ mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
+ const mp_stream_p_t *stream_p = mp_get_stream(self->sock);
+ while (1) {
+ if (self->to_recv != 0) {
+ mp_uint_t out_sz = stream_p->read(self->sock, self->buf + self->buf_pos, self->to_recv, errcode);
+ if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
+ return out_sz;
+ }
+ self->buf_pos += out_sz;
+ self->to_recv -= out_sz;
+ if (self->to_recv != 0) {
+ *errcode = MP_EAGAIN;
+ return MP_STREAM_ERROR;
+ }
+ }
+
+ switch (self->state) {
+ case FRAME_HEADER: {
+ // TODO: Split frame handling below is untested so far, so conservatively disable it
+ assert(self->buf[0] & 0x80);
+
+ // "Control frames MAY be injected in the middle of a fragmented message."
+ // So, they must be processed before data frames (and not alter
+ // self->ws_flags)
+ byte frame_type = self->buf[0];
+ self->last_flags = frame_type;
+ frame_type &= FRAME_OPCODE_MASK;
+
+ if ((self->buf[0] & FRAME_OPCODE_MASK) == FRAME_CONT) {
+ // Preserve previous frame type
+ self->ws_flags = (self->ws_flags & FRAME_OPCODE_MASK) | (self->buf[0] & ~FRAME_OPCODE_MASK);
+ } else {
+ self->ws_flags = self->buf[0];
+ }
+
+ // Reset mask in case someone will use "simplified" protocol
+ // without masks.
+ memset(self->mask, 0, sizeof(self->mask));
+
+ int to_recv = 0;
+ size_t sz = self->buf[1] & 0x7f;
+ if (sz == 126) {
+ // Msg size is next 2 bytes
+ to_recv += 2;
+ } else if (sz == 127) {
+ // Msg size is next 8 bytes
+ assert(0);
+ }
+ if (self->buf[1] & 0x80) {
+ // Next 4 bytes is mask
+ to_recv += 4;
+ }
+
+ self->buf_pos = 0;
+ self->to_recv = to_recv;
+ self->msg_sz = sz; // May be overridden by FRAME_OPT
+ if (to_recv != 0) {
+ self->state = FRAME_OPT;
+ } else {
+ if (frame_type >= FRAME_CLOSE) {
+ self->state = CONTROL;
+ } else {
+ self->state = PAYLOAD;
+ }
+ }
+ continue;
+ }
+
+ case FRAME_OPT: {
+ if ((self->buf_pos & 3) == 2) {
+ // First two bytes are message length
+ self->msg_sz = (self->buf[0] << 8) | self->buf[1];
+ }
+ if (self->buf_pos >= 4) {
+ // Last 4 bytes is mask
+ memcpy(self->mask, self->buf + self->buf_pos - 4, 4);
+ }
+ self->buf_pos = 0;
+ if ((self->last_flags & FRAME_OPCODE_MASK) >= FRAME_CLOSE) {
+ self->state = CONTROL;
+ } else {
+ self->state = PAYLOAD;
+ }
+ continue;
+ }
+
+ case PAYLOAD:
+ case CONTROL: {
+ mp_uint_t out_sz = 0;
+ if (self->msg_sz == 0) {
+ // In case message had zero payload
+ goto no_payload;
+ }
+
+ size_t sz = MIN(size, self->msg_sz);
+ out_sz = stream_p->read(self->sock, buf, sz, errcode);
+ if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
+ return out_sz;
+ }
+
+ sz = out_sz;
+ for (byte *p = buf; sz--; p++) {
+ *p ^= self->mask[self->mask_pos++ & 3];
+ }
+
+ self->msg_sz -= out_sz;
+ if (self->msg_sz == 0) {
+ byte last_state;
+ no_payload:
+ last_state = self->state;
+ self->state = FRAME_HEADER;
+ self->to_recv = 2;
+ self->mask_pos = 0;
+ self->buf_pos = 0;
+
+ // Handle control frame
+ if (last_state == CONTROL) {
+ byte frame_type = self->last_flags & FRAME_OPCODE_MASK;
+ if (frame_type == FRAME_CLOSE) {
+ static const char close_resp[2] = {0x88, 0};
+ int err;
+ websocket_write(self_in, close_resp, sizeof(close_resp), &err);
+ return 0;
+ }
+
+ // DEBUG_printf("Finished receiving ctrl message %x, ignoring\n", self->last_flags);
+ continue;
+ }
+ }
+
+ if (out_sz != 0) {
+ return out_sz;
+ }
+ // Empty (data) frame received is not EOF
+ continue;
+ }
+
+ }
+ }
+}
+
+STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
+ mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
+ assert(size < 0x10000);
+ byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)};
+ int hdr_sz;
+ if (size < 126) {
+ header[1] = size;
+ hdr_sz = 2;
+ } else {
+ header[1] = 126;
+ header[2] = size >> 8;
+ header[3] = size & 0xff;
+ hdr_sz = 4;
+ }
+
+ mp_obj_t dest[3];
+ if (self->opts & BLOCKING_WRITE) {
+ mp_load_method(self->sock, MP_QSTR_setblocking, dest);
+ dest[2] = mp_const_true;
+ mp_call_method_n_kw(1, 0, dest);
+ }
+
+ mp_uint_t out_sz = mp_stream_write_exactly(self->sock, header, hdr_sz, errcode);
+ if (*errcode == 0) {
+ out_sz = mp_stream_write_exactly(self->sock, buf, size, errcode);
+ }
+
+ if (self->opts & BLOCKING_WRITE) {
+ dest[2] = mp_const_false;
+ mp_call_method_n_kw(1, 0, dest);
+ }
+
+ if (*errcode != 0) {
+ return MP_STREAM_ERROR;
+ }
+ return out_sz;
+}
+
+STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+ mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
+ switch (request) {
+ case MP_STREAM_CLOSE:
+ // TODO: Send close signaling to the other side, otherwise it's
+ // abrupt close (connection abort).
+ mp_stream_close(self->sock);
+ return 0;
+ case MP_STREAM_GET_DATA_OPTS:
+ return self->ws_flags & FRAME_OPCODE_MASK;
+ case MP_STREAM_SET_DATA_OPTS: {
+ int cur = self->opts & FRAME_OPCODE_MASK;
+ self->opts = (self->opts & ~FRAME_OPCODE_MASK) | (arg & FRAME_OPCODE_MASK);
+ return cur;
+ }
+ default:
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+}
+
+STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);
+
+STATIC const mp_stream_p_t websocket_stream_p = {
+ .read = websocket_read,
+ .write = websocket_write,
+ .ioctl = websocket_ioctl,
+};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ websocket_type,
+ MP_QSTR_websocket,
+ MP_TYPE_FLAG_NONE,
+ make_new, websocket_make_new,
+ protocol, &websocket_stream_p,
+ locals_dict, &websocket_locals_dict
+ );
+
+STATIC const mp_rom_map_elem_t websocket_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_websocket) },
+ { MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&websocket_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(websocket_module_globals, websocket_module_globals_table);
+
+const mp_obj_module_t mp_module_websocket = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&websocket_module_globals,
+};
+
+// This module should not be extensible (as it is not a CPython standard
+// library nor is it necessary to override from the filesystem), however it
+// has previously been known as `uwebsocket`, so by making it extensible the
+// `uwebsocket` alias will continue to work.
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_websocket, mp_module_websocket);
+
+#endif // MICROPY_PY_WEBSOCKET
diff --git a/extmod/modwebsocket.h b/extmod/modwebsocket.h
new file mode 100644
index 0000000000000..2720147dfdb6f
--- /dev/null
+++ b/extmod/modwebsocket.h
@@ -0,0 +1,10 @@
+#ifndef MICROPY_INCLUDED_EXTMOD_MODWEBSOCKET_H
+#define MICROPY_INCLUDED_EXTMOD_MODWEBSOCKET_H
+
+#define FRAME_OPCODE_MASK 0x0f
+enum {
+ FRAME_CONT, FRAME_TXT, FRAME_BIN,
+ FRAME_CLOSE = 0x8, FRAME_PING, FRAME_PONG
+};
+
+#endif // MICROPY_INCLUDED_EXTMOD_MODWEBSOCKET_H
diff --git a/extmod/modzlib.c b/extmod/modzlib.c
new file mode 100644
index 0000000000000..31096cfeb9e92
--- /dev/null
+++ b/extmod/modzlib.c
@@ -0,0 +1,239 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Paul Sokolovsky
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "py/mperrno.h"
+
+#if MICROPY_PY_ZLIB
+
+#include "lib/uzlib/tinf.h"
+
+#if 0 // print debugging info
+#define DEBUG_printf DEBUG_printf
+#else // don't print debugging info
+#define DEBUG_printf(...) (void)0
+#endif
+
+typedef struct _mp_obj_decompio_t {
+ mp_obj_base_t base;
+ mp_obj_t src_stream;
+ TINF_DATA decomp;
+ bool eof;
+} mp_obj_decompio_t;
+
+STATIC int read_src_stream(TINF_DATA *data) {
+ byte *p = (void *)data;
+ p -= offsetof(mp_obj_decompio_t, decomp);
+ mp_obj_decompio_t *self = (mp_obj_decompio_t *)p;
+
+ const mp_stream_p_t *stream = mp_get_stream(self->src_stream);
+ int err;
+ byte c;
+ mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err);
+ if (out_sz == MP_STREAM_ERROR) {
+ mp_raise_OSError(err);
+ }
+ if (out_sz == 0) {
+ mp_raise_type(&mp_type_EOFError);
+ }
+ return c;
+}
+
+STATIC mp_obj_t decompio_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, 1, 2, false);
+ mp_get_stream_raise(args[0], MP_STREAM_OP_READ);
+ mp_obj_decompio_t *o = mp_obj_malloc(mp_obj_decompio_t, type);
+ memset(&o->decomp, 0, sizeof(o->decomp));
+ o->decomp.readSource = read_src_stream;
+ o->src_stream = args[0];
+ o->eof = false;
+
+ mp_int_t dict_opt = 0;
+ uint dict_sz;
+ if (n_args > 1) {
+ dict_opt = mp_obj_get_int(args[1]);
+ }
+
+ if (dict_opt >= 16) {
+ int st = uzlib_gzip_parse_header(&o->decomp);
+ if (st != TINF_OK) {
+ goto header_error;
+ }
+ dict_sz = 1 << (dict_opt - 16);
+ } else if (dict_opt >= 0) {
+ dict_opt = uzlib_zlib_parse_header(&o->decomp);
+ if (dict_opt < 0) {
+ header_error:
+ mp_raise_ValueError(MP_ERROR_TEXT("compression header"));
+ }
+ // RFC 1950 section 2.2:
+ // CINFO is the base-2 logarithm of the LZ77 window size,
+ // minus eight (CINFO=7 indicates a 32K window size)
+ dict_sz = 1 << (dict_opt + 8);
+ } else {
+ dict_sz = 1 << -dict_opt;
+ }
+
+ uzlib_uncompress_init(&o->decomp, m_new(byte, dict_sz), dict_sz);
+ return MP_OBJ_FROM_PTR(o);
+}
+
+STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
+ mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in);
+ if (o->eof) {
+ return 0;
+ }
+
+ o->decomp.dest = buf;
+ o->decomp.dest_limit = (byte *)buf + size;
+ int st = uzlib_uncompress_chksum(&o->decomp);
+ if (st == TINF_DONE) {
+ o->eof = true;
+ }
+ if (st < 0) {
+ DEBUG_printf("uncompress error=" INT_FMT "\n", st);
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+ return o->decomp.dest - (byte *)buf;
+}
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
+#endif
+
+STATIC const mp_stream_p_t decompio_stream_p = {
+ .read = decompio_read,
+};
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ decompio_type,
+ MP_QSTR_DecompIO,
+ MP_TYPE_FLAG_NONE,
+ make_new, decompio_make_new,
+ protocol, &decompio_stream_p,
+ locals_dict, &decompio_locals_dict
+ );
+#endif
+
+STATIC mp_obj_t mod_zlib_decompress(size_t n_args, const mp_obj_t *args) {
+ mp_obj_t data = args[0];
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
+
+ TINF_DATA *decomp = m_new_obj(TINF_DATA);
+ memset(decomp, 0, sizeof(*decomp));
+ DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp));
+ uzlib_uncompress_init(decomp, NULL, 0);
+ mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15;
+ byte *dest_buf = m_new(byte, dest_buf_size);
+
+ decomp->dest = dest_buf;
+ decomp->dest_limit = dest_buf + dest_buf_size;
+ DEBUG_printf("zlib: Initial out buffer: " UINT_FMT " bytes\n", dest_buf_size);
+ decomp->source = bufinfo.buf;
+ decomp->source_limit = (byte *)bufinfo.buf + bufinfo.len;
+
+ int st;
+ bool is_zlib = true;
+
+ if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) {
+ is_zlib = false;
+ }
+
+ if (is_zlib) {
+ st = uzlib_zlib_parse_header(decomp);
+ if (st < 0) {
+ goto error;
+ }
+ }
+
+ while (1) {
+ st = uzlib_uncompress_chksum(decomp);
+ if (st < 0) {
+ goto error;
+ }
+ if (st == TINF_DONE) {
+ break;
+ }
+ size_t offset = decomp->dest - dest_buf;
+ dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256);
+ dest_buf_size += 256;
+ decomp->dest = dest_buf + offset;
+ decomp->dest_limit = decomp->dest + 256;
+ }
+
+ mp_uint_t final_sz = decomp->dest - dest_buf;
+ DEBUG_printf("zlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz);
+ dest_buf = (byte *)m_renew(byte, dest_buf, dest_buf_size, final_sz);
+ mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf);
+ m_del_obj(TINF_DATA, decomp);
+ return res;
+
+error:
+ mp_raise_type_arg(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_zlib_decompress_obj, 1, 3, mod_zlib_decompress);
+
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_rom_map_elem_t mp_module_zlib_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_zlib) },
+ { MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_zlib_decompress_obj) },
+ { MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_zlib_globals, mp_module_zlib_globals_table);
+
+const mp_obj_module_t mp_module_zlib = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_zlib_globals,
+};
+
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_zlib, mp_module_zlib);
+#endif
+
+// Source files #include'd here to make sure they're compiled in
+// only if module is enabled by config setting.
+
+#include "lib/uzlib/tinflate.c"
+#include "lib/uzlib/tinfzlib.c"
+#include "lib/uzlib/tinfgzip.c"
+#include "lib/uzlib/adler32.c"
+#include "lib/uzlib/crc32.c"
+
+#endif // MICROPY_PY_ZLIB
diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c
index ea2fbbd45ea52..168bd3d52b52a 100644
--- a/extmod/network_cyw43.c
+++ b/extmod/network_cyw43.c
@@ -33,10 +33,24 @@
#if MICROPY_PY_NETWORK_CYW43
#include "lwip/netif.h"
-#include "drivers/cyw43/cyw43.h"
#include "extmod/network_cyw43.h"
#include "modnetwork.h"
+#include "lib/cyw43-driver/src/cyw43.h"
+#include "lib/cyw43-driver/src/cyw43_country.h"
+
+// This is the same as cyw43_pm_value but as a macro, to make it a true constant.
+#define CYW43_PM_VALUE(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc) \
+ ((li_assoc) << 20 \
+ | (li_dtim_period) << 16 \
+ | (li_beacon_period) << 12 \
+ | ((pm2_sleep_ret_ms) / 10) << 4 \
+ | (pm_mode))
+
+#define PM_NONE (CYW43_PM_VALUE(CYW43_NO_POWERSAVE_MODE, 10, 0, 0, 0))
+#define PM_PERFORMANCE (CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 200, 1, 1, 10))
+#define PM_POWERSAVE (CYW43_PM_VALUE(CYW43_PM1_POWERSAVE_MODE, 10, 0, 0, 0))
+
typedef struct _network_cyw43_obj_t {
mp_obj_base_t base;
cyw43_t *cyw;
@@ -119,7 +133,8 @@ STATIC mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf));
} else {
- cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1]));
+ uint32_t country = CYW43_COUNTRY(mod_network_country_code[0], mod_network_country_code[1], 0);
+ cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1]), country);
return mp_const_none;
}
}
@@ -223,7 +238,7 @@ STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, m
{ MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CYW43_CHANNEL_NONE} },
};
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -235,13 +250,18 @@ STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, m
args[ARG_security] = args[ARG_auth];
}
+ // Extract the SSID.
mp_buffer_info_t ssid;
mp_get_buffer_raise(args[ARG_ssid].u_obj, &ssid, MP_BUFFER_READ);
+
+ // Extract the key, if given.
mp_buffer_info_t key;
key.buf = NULL;
if (args[ARG_key].u_obj != mp_const_none) {
mp_get_buffer_raise(args[ARG_key].u_obj, &key, MP_BUFFER_READ);
}
+
+ // Extract the BSSID, if given.
mp_buffer_info_t bssid;
bssid.buf = NULL;
if (args[ARG_bssid].u_obj != mp_const_none) {
@@ -250,8 +270,25 @@ STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, m
mp_raise_ValueError(NULL);
}
}
+
+ // Extract the security type, if given.
+ uint32_t auth_type;
+ if (args[ARG_security].u_int == -1) {
+ if (key.buf == NULL || key.len == 0) {
+ // Default to open when no password set.
+ auth_type = CYW43_AUTH_OPEN;
+ } else {
+ // Default to WPA2 otherwise. All other modes require the security
+ // kwarg to be set explicitly.
+ auth_type = CYW43_AUTH_WPA2_MIXED_PSK;
+ }
+ } else {
+ auth_type = args[ARG_security].u_int;
+ }
+
+ // Start the WiFi join procedure. It will run in the background.
int ret = cyw43_wifi_join(self->cyw, ssid.len, ssid.buf, key.len, key.buf,
- args[ARG_security].u_int, bssid.buf, args[ARG_channel].u_int);
+ auth_type, bssid.buf, args[ARG_channel].u_int);
if (ret != 0) {
mp_raise_OSError(-ret);
}
@@ -289,6 +326,14 @@ STATIC mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) {
// one argument: return status based on query parameter
switch (mp_obj_str_get_qstr(args[1])) {
+ case MP_QSTR_rssi: {
+ if (self->itf != CYW43_ITF_STA) {
+ mp_raise_ValueError(MP_ERROR_TEXT("STA required"));
+ }
+ int32_t rssi;
+ cyw43_wifi_get_rssi(self->cyw, &rssi);
+ return mp_obj_new_int(rssi);
+ }
case MP_QSTR_stations: {
// return list of connected stations
if (self->itf != CYW43_ITF_AP) {
@@ -356,17 +401,29 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
return mp_obj_new_str((const char *)buf, len);
}
}
+ case MP_QSTR_security: {
+ return MP_OBJ_NEW_SMALL_INT(cyw43_wifi_ap_get_auth(self->cyw));
+ }
case MP_QSTR_mac: {
uint8_t buf[6];
cyw43_wifi_get_mac(self->cyw, self->itf, buf);
return mp_obj_new_bytes(buf, 6);
}
+ case MP_QSTR_pm: {
+ uint32_t pm;
+ cyw43_wifi_get_pm(self->cyw, &pm);
+ return MP_OBJ_NEW_SMALL_INT(pm);
+ }
case MP_QSTR_txpower: {
uint8_t buf[13];
memcpy(buf, "qtxpower\x00\x00\x00\x00\x00", 13);
cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_VAR, 13, buf, self->itf);
return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf) / 4);
}
+ case MP_QSTR_hostname: {
+ // TODO: Deprecated. Use network.hostname() instead.
+ return mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
+ }
default:
mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
}
@@ -412,6 +469,10 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
}
break;
}
+ case MP_QSTR_security: {
+ cyw43_wifi_ap_set_auth(self->cyw, mp_obj_get_int(e->value));
+ break;
+ }
case MP_QSTR_key:
case MP_QSTR_password: {
size_t len;
@@ -435,6 +496,16 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf);
break;
}
+ case MP_QSTR_hostname: {
+ // TODO: Deprecated. Use network.hostname(name) instead.
+ size_t len;
+ const char *str = mp_obj_str_get_data(e->value, &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
+ }
+ strcpy(mod_network_hostname, str);
+ break;
+ }
default:
mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
}
@@ -462,15 +533,21 @@ STATIC const mp_rom_map_elem_t network_cyw43_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_cyw43_ifconfig_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_cyw43_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_cyw43_config_obj) },
+
+ // Class constants.
+ { MP_ROM_QSTR(MP_QSTR_PM_NONE), MP_ROM_INT(PM_NONE) },
+ { MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(PM_PERFORMANCE) },
+ { MP_ROM_QSTR(MP_QSTR_PM_POWERSAVE), MP_ROM_INT(PM_POWERSAVE) },
};
STATIC MP_DEFINE_CONST_DICT(network_cyw43_locals_dict, network_cyw43_locals_dict_table);
-const mp_obj_type_t mp_network_cyw43_type = {
- { &mp_type_type },
- .name = MP_QSTR_CYW43,
- .print = network_cyw43_print,
- .make_new = network_cyw43_make_new,
- .locals_dict = (mp_obj_dict_t *)&network_cyw43_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_network_cyw43_type,
+ MP_QSTR_CYW43,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_cyw43_make_new,
+ print, network_cyw43_print,
+ locals_dict, &network_cyw43_locals_dict
+ );
#endif // MICROPY_PY_NETWORK_CYW43
diff --git a/extmod/network_lwip.c b/extmod/network_lwip.c
new file mode 100644
index 0000000000000..caa30f6fff4d2
--- /dev/null
+++ b/extmod/network_lwip.c
@@ -0,0 +1,95 @@
+/*
+ * 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 "py/runtime.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_NETWORK && MICROPY_PY_LWIP
+
+#include "shared/netutils/netutils.h"
+#include "extmod/modnetwork.h"
+
+#include "lwip/init.h"
+
+#if LWIP_VERSION_MAJOR >= 2
+
+#include "lwip/netif.h"
+#include "lwip/timeouts.h"
+#include "lwip/dns.h"
+#include "lwip/dhcp.h"
+
+// Implementations of network methods that can be used by any interface.
+
+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, MP_ERROR_TEXT("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 // LWIP_VERSION_MAJOR >= 2
+
+#endif // MICROPY_PY_NETWORK && MICROPY_PY_LWIP
diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c
index 622e29ba68431..00f53eff137a8 100644
--- a/extmod/network_ninaw10.c
+++ b/extmod/network_ninaw10.c
@@ -51,6 +51,9 @@ typedef struct _nina_obj_t {
mp_obj_base_t base;
bool active;
uint32_t itf;
+ mp_uint_t security;
+ char ssid[NINA_MAX_SSID_LEN + 1];
+ char key[NINA_MAX_WPA_LEN + 1];
} nina_obj_t;
// For auto-binding UDP sockets
@@ -74,10 +77,11 @@ typedef struct _nina_obj_t {
#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
static uint16_t bind_port = BIND_PORT_RANGE_MIN;
-const mod_network_nic_type_t mod_network_nic_type_nina;
+const mp_obj_type_t mod_network_nic_type_nina;
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_STA_IF};
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_AP_IF};
static mp_sched_node_t mp_wifi_sockpoll_node;
+static mp_sched_node_t mp_wifi_connpoll_node;
STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
(void)node;
@@ -99,6 +103,40 @@ STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
}
}
+STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
+ nina_obj_t *self = &network_nina_wl_sta;
+
+ int status = nina_connection_status();
+ if (status == NINA_STATUS_CONNECTED) {
+ // Connected to AP, nothing else to do.
+ return;
+ }
+
+ if (status != NINA_STATUS_NO_SSID_AVAIL) {
+ // If not connected, and no connection in progress, the connection attempt has failed.
+ // Read the ESP failure reason, reconnect and reschedule the connection polling code.
+ int reason = nina_connection_reason();
+ if (reason == NINA_ESP_REASON_AUTH_EXPIRE ||
+ reason == NINA_ESP_REASON_ASSOC_EXPIRE ||
+ reason == NINA_ESP_REASON_NOT_AUTHED ||
+ reason == NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT ||
+ reason >= NINA_ESP_REASON_BEACON_TIMEOUT) {
+ debug_printf(&mp_plat_print, "poll_connect() status: %d reason %d\n", status, reason);
+ if (nina_connect(self->ssid, self->security, self->key, 0) != 0) {
+ mp_raise_msg_varg(&mp_type_OSError,
+ MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"),
+ self->ssid, self->security, self->key);
+ }
+ } else {
+ // Will not attempt to reconnect if there's another error code set.
+ return;
+ }
+ }
+
+ // Reschedule the connection polling code.
+ mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
+}
+
STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) {
if (MP_STATE_PORT(mp_wifi_sockpoll_list) != MP_OBJ_NULL && MP_STATE_PORT(mp_wifi_sockpoll_list)->len) {
mp_sched_schedule_node(&mp_wifi_sockpoll_node, network_ninaw10_poll_sockets);
@@ -159,7 +197,7 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(10),
MP_OBJ_NEW_QSTR(MP_QSTR_callback), MP_OBJ_FROM_PTR(&network_ninaw10_timer_callback_obj),
};
- MP_STATE_PORT(mp_wifi_timer) = machine_timer_type.make_new((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
+ MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_TYPE_GET_SLOT(&machine_timer_type, make_new)((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
}
} else {
nina_deinit();
@@ -240,6 +278,12 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
mp_raise_msg_varg(&mp_type_OSError,
MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"), ssid, security, key);
}
+
+ // Save connection info to re-connect if needed.
+ self->security = security;
+ strncpy(self->key, key, NINA_MAX_WPA_LEN);
+ strncpy(self->ssid, ssid, NINA_MAX_SSID_LEN);
+ mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
} else {
mp_uint_t channel = args[ARG_channel].u_int;
@@ -252,6 +296,7 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to start in AP mode"));
}
}
+
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_ninaw10_connect_obj, 1, network_ninaw10_connect);
@@ -441,13 +486,33 @@ STATIC int network_ninaw10_socket_listening(mod_network_socket_obj_t *socket, in
STATIC int network_ninaw10_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
debug_printf("socket_socket(%d %d %d)\n", socket->domain, socket->type, socket->proto);
+ uint8_t socket_type;
+
+ switch (socket->type) {
+ case MOD_NETWORK_SOCK_STREAM:
+ socket_type = NINA_SOCKET_TYPE_TCP;
+ break;
+
+ case MOD_NETWORK_SOCK_DGRAM:
+ socket_type = NINA_SOCKET_TYPE_UDP;
+ break;
+
+ case MOD_NETWORK_SOCK_RAW:
+ socket_type = NINA_SOCKET_TYPE_RAW;
+ break;
+
+ default:
+ *_errno = MP_EINVAL;
+ return -1;
+ }
+
if (socket->domain != MOD_NETWORK_AF_INET) {
*_errno = MP_EAFNOSUPPORT;
return -1;
}
// open socket
- int fd = nina_socket_socket(socket->type, socket->proto);
+ int fd = nina_socket_socket(socket_type, socket->proto);
if (fd < 0) {
nina_socket_errno(_errno);
debug_printf("socket_socket() -> errno %d\n", *_errno);
@@ -477,20 +542,6 @@ STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
STATIC int network_ninaw10_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
debug_printf("socket_bind(%d, %d)\n", socket->fileno, port);
- uint8_t type;
- switch (socket->type) {
- case MOD_NETWORK_SOCK_STREAM:
- type = NINA_SOCKET_TYPE_TCP;
- break;
-
- case MOD_NETWORK_SOCK_DGRAM:
- type = NINA_SOCKET_TYPE_UDP;
- break;
-
- default:
- *_errno = MP_EINVAL;
- return -1;
- }
int ret = nina_socket_bind(socket->fileno, ip, port);
if (ret < 0) {
@@ -753,7 +804,7 @@ STATIC int network_ninaw10_socket_ioctl(mod_network_socket_obj_t *socket, mp_uin
return ret;
}
-static const mp_rom_map_elem_t nina_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t nina_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_ninaw10_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_ninaw10_scan_obj) },
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_ninaw10_connect_obj) },
@@ -772,15 +823,9 @@ static const mp_rom_map_elem_t nina_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_WPA_PSK), MP_ROM_INT(NINA_SEC_WPA_PSK) },
};
-static MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
-const mod_network_nic_type_t mod_network_nic_type_nina = {
- .base = {
- { &mp_type_type },
- .name = MP_QSTR_nina,
- .make_new = network_ninaw10_make_new,
- .locals_dict = (mp_obj_t)&nina_locals_dict,
- },
+STATIC const mod_network_nic_protocol_t mod_network_nic_protocol_nina = {
.gethostbyname = network_ninaw10_gethostbyname,
.socket = network_ninaw10_socket_socket,
.close = network_ninaw10_socket_close,
@@ -797,4 +842,17 @@ const mod_network_nic_type_t mod_network_nic_type_nina = {
.ioctl = network_ninaw10_socket_ioctl,
};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mod_network_nic_type_nina,
+ MP_QSTR_nina,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_ninaw10_make_new,
+ locals_dict, &nina_locals_dict,
+ protocol, &mod_network_nic_protocol_nina
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi);
+MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer);
+MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list);
+
#endif // #if MICROPY_PY_BLUETOOTH && MICROPY_PY_NETWORK_NINAW10
diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c
index f328276a5b269..eed656ee2419d 100644
--- a/extmod/network_wiznet5k.c
+++ b/extmod/network_wiznet5k.c
@@ -33,6 +33,9 @@
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/mphal.h"
+
+#if MICROPY_PY_NETWORK_WIZNET5K
+
#include "shared/netutils/netutils.h"
#include "extmod/modnetwork.h"
#include "extmod/machine_spi.h"
@@ -40,8 +43,6 @@
#include "modmachine.h"
#include "drivers/bus/spi.h"
-#if MICROPY_PY_NETWORK_WIZNET5K
-
#include "lib/wiznet5k/Ethernet/wizchip_conf.h"
// The WIZNET5K module supports two usage modes:
@@ -91,12 +92,11 @@
#endif
#endif
-extern struct _machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o);
-
typedef struct _wiznet5k_obj_t {
mp_obj_base_t base;
mp_uint_t cris_state;
- struct _machine_spi_obj_t *spi;
+ mp_obj_base_t *spi;
+ void (*spi_transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
mp_hal_pin_obj_t cs;
mp_hal_pin_obj_t rst;
#if WIZNET5K_WITH_LWIP_STACK
@@ -148,21 +148,21 @@ void mpy_wiznet_yield(void) {
}
STATIC void wiz_spi_read(uint8_t *buf, uint16_t len) {
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, len, buf, buf);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, len, buf, buf);
}
STATIC void wiz_spi_write(const uint8_t *buf, uint16_t len) {
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, len, buf, NULL);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, len, buf, NULL);
}
STATIC uint8_t wiz_spi_readbyte() {
uint8_t buf = 0;
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, 1, &buf, &buf);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, 1, &buf, &buf);
return buf;
}
STATIC void wiz_spi_writebyte(const uint8_t buf) {
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, 1, &buf, NULL);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, 1, &buf, NULL);
}
STATIC void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) {
@@ -177,11 +177,10 @@ STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self);
STATIC mp_obj_t mpy_wiznet_read_int(mp_obj_t none_in) {
(void)none_in;
- wizchip_clrinterrupt(IK_SOCK_0);
- setSn_IR(0, Sn_IR_RECV);
-
- // Handle incoming data
- wiznet5k_try_poll();
+ // Handle incoming data, unless the SPI bus is busy
+ if (mp_hal_pin_read(wiznet5k_obj.cs)) {
+ wiznet5k_try_poll();
+ }
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mpy_wiznet_read_int_obj, mpy_wiznet_read_int);
@@ -198,6 +197,16 @@ STATIC void wiznet5k_config_interrupt(bool enabled) {
);
}
+void wiznet5k_deinit(void) {
+ for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
+ if (netif == &wiznet5k_obj.netif) {
+ netif_remove(netif);
+ netif->flags = 0;
+ break;
+ }
+ }
+}
+
STATIC void wiznet5k_init(void) {
// Configure wiznet for raw ethernet frame usage.
@@ -219,21 +228,17 @@ STATIC void wiznet5k_init(void) {
wiznet5k_config_interrupt(true);
}
+ // Deinit before a new init to clear the state from a previous activation
+ wiznet5k_deinit();
+
// Hook the Wiznet into lwIP
wiznet5k_lwip_init(&wiznet5k_obj);
netif_set_link_up(&wiznet5k_obj.netif);
netif_set_up(&wiznet5k_obj.netif);
-}
-void wiznet5k_deinit(void) {
- for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
- if (netif == &wiznet5k_obj.netif) {
- netif_remove(netif);
- netif->flags = 0;
- break;
- }
- }
+ // register with network module
+ mod_network_register_nic(&wiznet5k_obj);
}
STATIC void wiznet5k_send_ethernet(wiznet5k_obj_t *self, size_t len, const uint8_t *buf) {
@@ -320,23 +325,25 @@ STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self) {
void wiznet5k_poll(void) {
wiznet5k_obj_t *self = &wiznet5k_obj;
- if (!(self->netif.flags & NETIF_FLAG_UP) ||
- !(self->netif.flags & NETIF_FLAG_LINK_UP)) {
- return;
- }
- uint16_t len;
- while ((len = wiznet5k_recv_ethernet(self)) > 0) {
- if (self->trace_flags & TRACE_ETH_RX) {
- netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE);
- }
- struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- if (p != NULL) {
- pbuf_take(p, self->eth_frame, len);
- if (self->netif.input(p, &self->netif) != ERR_OK) {
- pbuf_free(p);
+ if ((self->netif.flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) {
+ uint16_t len;
+ while ((len = wiznet5k_recv_ethernet(self)) > 0) {
+ if (self->trace_flags & TRACE_ETH_RX) {
+ netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE);
+ }
+ struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p != NULL) {
+ pbuf_take(p, self->eth_frame, len);
+ if (self->netif.input(p, &self->netif) != ERR_OK) {
+ pbuf_free(p);
+ }
}
}
}
+ wizchip_clrinterrupt(IK_SOCK_0);
+ #if _WIZCHIP_ == W5100S
+ setSn_IR(0, Sn_IR_RECV); // W5100S driver bug: must write to the Sn_IR register to reset the IRQ signal
+ #endif
}
#endif // MICROPY_PY_LWIP
@@ -391,6 +398,9 @@ STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len,
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(2, buf);
+ if (wiznet5k_obj.netinfo.dns[0]) {
+ memcpy(dns_ip, wiznet5k_obj.netinfo.dns, MOD_NETWORK_IPADDR_BUF_SIZE);
+ }
mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip);
m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
if (ret == 1) {
@@ -673,7 +683,7 @@ STATIC void wiznet5k_dhcp_init(wiznet5k_obj_t *self) {
// WIZNET5K(spi, pin_cs, pin_rst[, pin_intn])
// Create and return a WIZNET5K object.
STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- struct _machine_spi_obj_t *spi;
+ mp_obj_base_t *spi;
mp_hal_pin_obj_t cs;
mp_hal_pin_obj_t rst;
@@ -686,10 +696,8 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
#endif
#ifdef MICROPY_HW_WIZNET_SPI_ID
- // check arguments
- mp_arg_check_num(n_args, n_kw, 0, 3, false);
// Allow auto-configuration of SPI if defined for board and no args passed
- if (n_args == 0) {
+ if (n_args == 0 && n_kw == 0) {
// Initialize SPI.
mp_obj_t spi_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_SPI_SCK);
mp_obj_t miso_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_SPI_MISO);
@@ -701,7 +709,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
MP_ROM_QSTR(MP_QSTR_miso), mp_pin_make_new(NULL, 1, 0, &miso_obj),
MP_ROM_QSTR(MP_QSTR_mosi), mp_pin_make_new(NULL, 1, 0, &mosi_obj),
};
- spi = machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 3, args);
+ spi = MP_OBJ_TO_PTR(MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 3, args));
cs = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_CS)}));
rst = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_RST)}));
@@ -719,7 +727,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
#else
mp_arg_check_num(n_args, n_kw, 3, 3, false);
#endif
- spi = spi_from_mp_obj(args[0]);
+ spi = mp_hal_get_spi_obj(args[0]);
cs = mp_hal_get_pin_obj(args[1]);
rst = mp_hal_get_pin_obj(args[2]);
#if WIZNET5K_WITH_LWIP_STACK
@@ -737,6 +745,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k;
wiznet5k_obj.cris_state = 0;
wiznet5k_obj.spi = spi;
+ wiznet5k_obj.spi_transfer = ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(spi->type, protocol))->transfer;
wiznet5k_obj.cs = cs;
wiznet5k_obj.rst = rst;
#if WIZNET5K_WITH_LWIP_STACK
@@ -1008,20 +1017,9 @@ STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
#if WIZNET5K_WITH_LWIP_STACK
-const mp_obj_type_t mod_network_nic_type_wiznet5k = {
- { &mp_type_type },
- .name = MP_QSTR_WIZNET5K,
- .make_new = wiznet5k_make_new,
- .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict,
-};
+#define NIC_TYPE_WIZNET_PROTOCOL
#else // WIZNET5K_PROVIDED_STACK
-const mod_network_nic_type_t mod_network_nic_type_wiznet5k = {
- .base = {
- { &mp_type_type },
- .name = MP_QSTR_WIZNET5K,
- .make_new = wiznet5k_make_new,
- .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict,
- },
+const mod_network_nic_protocol_t mod_network_nic_protocol_wiznet = {
.gethostbyname = wiznet5k_gethostbyname,
.socket = wiznet5k_socket_socket,
.close = wiznet5k_socket_close,
@@ -1037,6 +1035,16 @@ const mod_network_nic_type_t mod_network_nic_type_wiznet5k = {
.settimeout = wiznet5k_socket_settimeout,
.ioctl = wiznet5k_socket_ioctl,
};
+#define NIC_TYPE_WIZNET_PROTOCOL protocol, &mod_network_nic_protocol_wiznet,
#endif
+MP_DEFINE_CONST_OBJ_TYPE(
+ mod_network_nic_type_wiznet5k,
+ MP_QSTR_WIZNET5K,
+ MP_TYPE_FLAG_NONE,
+ make_new, wiznet5k_make_new,
+ NIC_TYPE_WIZNET_PROTOCOL
+ locals_dict, &wiznet5k_locals_dict
+ );
+
#endif // MICROPY_PY_NETWORK_WIZNET5K
diff --git a/extmod/nimble/hal/hal_uart.c b/extmod/nimble/hal/hal_uart.c
index 6c17da0860714..f4a9319c8b5fa 100644
--- a/extmod/nimble/hal/hal_uart.c
+++ b/extmod/nimble/hal/hal_uart.c
@@ -39,6 +39,9 @@
#endif
#define HCI_TRACE (0)
+#define COL_OFF "\033[0m"
+#define COL_GREEN "\033[0;32m"
+#define COL_BLUE "\033[0;34m"
static hal_uart_tx_cb_t hal_uart_tx_cb;
static void *hal_uart_tx_arg;
@@ -71,17 +74,17 @@ void hal_uart_start_tx(uint32_t port) {
}
#if HCI_TRACE
- printf("< [% 8d] %02x", (int)mp_hal_ticks_ms(), mp_bluetooth_hci_cmd_buf[0]);
+ printf(COL_GREEN "< [% 8d] %02x", (int)mp_hal_ticks_ms(), mp_bluetooth_hci_cmd_buf[0]);
for (size_t i = 1; i < len; ++i) {
printf(":%02x", mp_bluetooth_hci_cmd_buf[i]);
}
- printf("\n");
+ printf(COL_OFF "\n");
#endif
mp_bluetooth_hci_uart_write(mp_bluetooth_hci_cmd_buf, len);
if (len > 0) {
- // Allow modbluetooth bindings to hook "sent packet" (e.g. to unstall l2cap channels).
+ // Allow modbluetooth bindings to hook "sent packet" (e.g. to un-stall l2cap channels).
mp_bluetooth_nimble_sent_hci_packet();
}
}
@@ -92,7 +95,7 @@ int hal_uart_close(uint32_t port) {
STATIC void mp_bluetooth_hci_uart_char_cb(uint8_t chr) {
#if HCI_TRACE
- printf("> %02x\n", chr);
+ printf(COL_BLUE "> [% 8d] %02x" COL_OFF "\n", (int)mp_hal_ticks_ms(), chr);
#endif
hal_uart_rx_cb(hal_uart_rx_arg, chr);
}
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
index fce99bcdf5bf6..e23ffbf0f9814 100644
--- a/extmod/nimble/modbluetooth_nimble.c
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -652,7 +652,7 @@ int mp_bluetooth_init(void) {
// By default, just register the default gap/gatt service.
ble_svc_gap_init();
ble_svc_gatt_init();
- // The preceeding two calls allocate service definitions on the heap,
+ // The preceding two calls allocate service definitions on the heap,
// then we must now call gatts_start to register those services
// and free the heap memory.
// Otherwise it will be realloc'ed on the next stack startup.
@@ -851,6 +851,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle,
switch (ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR:
case BLE_GATT_ACCESS_OP_READ_DSC: {
+ DEBUG_printf("write for %d %d (op=%d)\n", conn_handle, value_handle, ctxt->op);
// Allow Python code to override (by using gatts_write), or deny (by returning false) the read.
// Note this will be a no-op if the ringbuffer implementation is being used (i.e. the stack isn't
// run in the scheduler). The ringbuffer is not used on STM32 and Unix-H4 only.
@@ -872,6 +873,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle,
}
case BLE_GATT_ACCESS_OP_WRITE_CHR:
case BLE_GATT_ACCESS_OP_WRITE_DSC:
+ DEBUG_printf("write for %d %d (op=%d)\n", conn_handle, value_handle, ctxt->op);
entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle);
if (!entry) {
return BLE_ATT_ERR_ATTR_NOT_FOUND;
@@ -963,7 +965,14 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index], NULL);
descriptors[j].access_cb = characteristic_access_cb;
// NimBLE doesn't support security/privacy options on descriptors.
- descriptors[j].att_flags = (uint8_t)descriptor_flags[descriptor_index];
+ uint8_t desc_att_flags = 0;
+ if (descriptor_flags[descriptor_index] & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) {
+ desc_att_flags |= BLE_ATT_F_READ;
+ }
+ if (descriptor_flags[descriptor_index] & (MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE | MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE)) {
+ desc_att_flags |= BLE_ATT_F_WRITE;
+ }
+ descriptors[j].att_flags = desc_att_flags;
descriptors[j].min_key_size = 0;
// Unlike characteristic, Nimble doesn't provide an automatic way to remember the handle, so use the arg.
descriptors[j].arg = &handles[handle_index];
@@ -1008,7 +1017,7 @@ int mp_bluetooth_gap_disconnect(uint16_t conn_handle) {
return ble_hs_err_to_errno(ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM));
}
-int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) {
+int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len) {
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
@@ -1026,35 +1035,40 @@ int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t
return err;
}
-// TODO: Could use ble_gatts_chr_updated to send to all subscribed centrals.
-
-int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) {
+int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len) {
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- // Confusingly, notify/notify_custom/indicate are "gattc" function (even though they're used by peripherals (i.e. gatt servers)).
- // See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html
- return ble_hs_err_to_errno(ble_gattc_notify(conn_handle, value_handle));
-}
-int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len) {
- if (!mp_bluetooth_is_active()) {
- return ERRNO_BLUETOOTH_NOT_ACTIVE;
- }
- struct os_mbuf *om = ble_hs_mbuf_from_flat(value, value_len);
- if (om == NULL) {
- return MP_ENOMEM;
+ int err = BLE_HS_EINVAL;
+
+ // NULL om in the _custom methods means "use DB value" (NimBLE will call
+ // back into mp_bluetooth_gatts_read for us).
+ struct os_mbuf *om = NULL;
+
+ if (value) {
+ om = ble_hs_mbuf_from_flat(value, value_len);
+ if (om == NULL) {
+ return MP_ENOMEM;
+ }
}
- return ble_hs_err_to_errno(ble_gattc_notify_custom(conn_handle, value_handle, om));
-}
-int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
- if (!mp_bluetooth_is_active()) {
- return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ // Note: Confusingly, Nimble's notify/notify_custom and indicate/indicate_custom
+ // are "gattc" functions (even though they're used by peripherals, i.e. gatt servers).
+ // See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html
+
+ switch (gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = ble_gattc_notify_custom(conn_handle, value_handle, om);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ // This will raise BLE_GAP_EVENT_NOTIFY_TX with a status when it is
+ // acknowledged (or timeout/error).
+ err = ble_gattc_indicate_custom(conn_handle, value_handle, om);
+ break;
}
- // This will raise BLE_GAP_EVENT_NOTIFY_TX with a status when it is
- // acknowledged (or timeout/error).
- return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle));
+
+ return ble_hs_err_to_errno(err);
}
int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {
@@ -1310,15 +1324,51 @@ int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_
return ble_hs_err_to_errno(err);
}
+STATIC bool match_char_uuid(const mp_obj_bluetooth_uuid_t *filter_uuid, const ble_uuid_any_t *result_uuid) {
+ if (!filter_uuid) {
+ return true;
+ }
+ ble_uuid_any_t filter_uuid_nimble;
+ create_nimble_uuid(filter_uuid, &filter_uuid_nimble);
+ return ble_uuid_cmp(&result_uuid->u, &filter_uuid_nimble.u) == 0;
+}
+
STATIC int ble_gattc_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) {
DEBUG_printf("ble_gattc_characteristic_cb: conn_handle=%d status=%d def_handle=%d val_handle=%d\n", conn_handle, error->status, characteristic ? characteristic->def_handle : -1, characteristic ? characteristic->val_handle : -1);
if (!mp_bluetooth_is_active()) {
return 0;
}
+
+ mp_bluetooth_nimble_pending_characteristic_t *pending = &MP_STATE_PORT(bluetooth_nimble_root_pointers)->pending_char_result;
+ if (pending->ready) {
+ // If there's a pending characteristic, we now know what it's end handle is, report it up to modbluetooth.
+ pending->ready = 0;
+
+ // The end handle will either be the end of the query range (there are
+ // no more results), or one before the current result's definition
+ // handle.
+ uint16_t end_handle = MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle;
+ if (error->status == 0) {
+ end_handle = characteristic->def_handle - 1;
+ }
+
+ // Assume same conn_handle because we're limiting to a single active discovery.
+ mp_bluetooth_gattc_on_characteristic_result(conn_handle, pending->value_handle, end_handle, pending->properties, &pending->uuid);
+ }
+
if (error->status == 0) {
- mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid);
- mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid);
+ // If there's no filter, or the filter matches, then save this result.
+ if (match_char_uuid(MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid, &characteristic->uuid)) {
+ pending->value_handle = characteristic->val_handle;
+ pending->properties = characteristic->properties;
+ pending->uuid = create_mp_uuid(&characteristic->uuid);
+ pending->ready = 1;
+ }
} else {
+ // Finished (or failed). Allow another characteristic discovery to start.
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = 0;
+
+ // Report completion.
mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE, conn_handle, error->status == BLE_HS_EDONE ? 0 : error->status);
}
return 0;
@@ -1328,13 +1378,29 @@ int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t s
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- int err;
- if (uuid) {
- ble_uuid_any_t nimble_uuid;
- create_nimble_uuid(uuid, &nimble_uuid);
- err = ble_gattc_disc_chrs_by_uuid(conn_handle, start_handle, end_handle, &nimble_uuid.u, &ble_gattc_characteristic_cb, NULL);
- } else {
- err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL);
+
+ // The implementation of characteristic discovery queries for all
+ // characteristics, and then UUID filtering is applied by NimBLE on each
+ // characteristic. Unfortunately, each characteristic result does not
+ // include its end handle, so you need to know the next characteristic
+ // before you can raise the previous one to modbluetooth. But if we let
+ // NimBLE do the filtering, then we don't necessarily see the next one.
+ // So we make NimBLE return all results and do the filtering here instead.
+
+ if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle) {
+ // Only allow a single discovery (otherwise we'd need to track a
+ // pending characteristic per conn handle).
+ return MP_EBUSY;
+ }
+
+ // Set the uuid filter (if any). This needs to be a root pointer,
+ // otherwise we'd use ble_gattc_disc_all_chrs's arg param.
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid = uuid;
+
+ int err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL);
+ if (!err) {
+ // Lock out concurrent characteristic discovery.
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = end_handle;
}
return ble_hs_err_to_errno(err);
}
@@ -1394,15 +1460,15 @@ STATIC int ble_gattc_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_e
}
// Write the value to the remote peripheral.
-int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) {
+int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len, unsigned int mode) {
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
int err;
if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) {
- err = ble_gattc_write_no_rsp_flat(conn_handle, value_handle, value, *value_len);
+ err = ble_gattc_write_no_rsp_flat(conn_handle, value_handle, value, value_len);
} else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) {
- err = ble_gattc_write_flat(conn_handle, value_handle, value, *value_len, &ble_gattc_attr_write_cb, NULL);
+ err = ble_gattc_write_flat(conn_handle, value_handle, value, value_len, &ble_gattc_attr_write_cb, NULL);
} else {
err = BLE_HS_EINVAL;
}
@@ -1471,7 +1537,7 @@ STATIC void destroy_l2cap_channel() {
STATIC void unstall_l2cap_channel(void) {
// Whenever we send an HCI packet and the sys mempool is now less than 1/4 full,
- // we can unstall the L2CAP channel if it was marked as "mem_stalled" by
+ // we can un-stall the L2CAP channel if it was marked as "mem_stalled" by
// mp_bluetooth_l2cap_send. (This happens if the pool is half-empty).
mp_bluetooth_nimble_l2cap_channel_t *chan = MP_STATE_PORT(bluetooth_nimble_root_pointers)->l2cap_chan;
if (!chan || !chan->mem_stalled) {
@@ -1578,7 +1644,7 @@ STATIC int l2cap_channel_event(struct ble_l2cap_event *event, void *arg) {
case BLE_L2CAP_EVENT_COC_TX_UNSTALLED: {
DEBUG_printf("l2cap_channel_event: tx_unstalled: conn_handle=%d status=%d\n", event->tx_unstalled.conn_handle, event->tx_unstalled.status);
assert(event->tx_unstalled.conn_handle == chan->chan->conn_handle);
- // Don't unstall if we're still waiting for room in the sys pool.
+ // Don't un-stall if we're still waiting for room in the sys pool.
if (!chan->mem_stalled) {
ble_l2cap_get_chan_info(event->receive.chan, &info);
// Map status to {0,1} (i.e. "sent everything", or "partial send").
@@ -1736,7 +1802,7 @@ int mp_bluetooth_l2cap_send(uint16_t conn_handle, uint16_t cid, const uint8_t *b
err = ble_l2cap_send(chan->chan, sdu_tx);
if (err == BLE_HS_ESTALLED) {
// Stalled means that this one will still send but any future ones
- // will fail until we receive an unstalled event.
+ // will fail until we receive an un-stalled event.
DEBUG_printf("mp_bluetooth_l2cap_send: credit stall\n");
*stalled = true;
err = 0;
@@ -1966,4 +2032,9 @@ STATIC int ble_secret_store_delete(int obj_type, const union ble_store_key *key)
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
+#if !MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY
+MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory);
+#endif
+MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers);
+
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
diff --git a/extmod/nimble/modbluetooth_nimble.h b/extmod/nimble/modbluetooth_nimble.h
index 15648a9959a60..d9bef649201ce 100644
--- a/extmod/nimble/modbluetooth_nimble.h
+++ b/extmod/nimble/modbluetooth_nimble.h
@@ -31,6 +31,13 @@
#define MP_BLUETOOTH_NIMBLE_MAX_SERVICES (8)
+typedef struct _mp_bluetooth_nimble_pending_characteristic_t {
+ uint16_t value_handle;
+ uint8_t properties;
+ mp_obj_bluetooth_uuid_t uuid;
+ uint8_t ready;
+} mp_bluetooth_nimble_pending_characteristic_t;
+
typedef struct _mp_bluetooth_nimble_root_pointers_t {
// Characteristic (and descriptor) value storage.
mp_gatts_db_t gatts_db;
@@ -44,6 +51,14 @@ typedef struct _mp_bluetooth_nimble_root_pointers_t {
struct _mp_bluetooth_nimble_l2cap_channel_t *l2cap_chan;
bool l2cap_listening;
#endif
+
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ // Workaround to allow us to get the end_handle of each characteristic
+ // during discovery. See mp_bluetooth_gattc_discover_characteristics().
+ uint16_t char_disc_end_handle;
+ const mp_obj_bluetooth_uuid_t *char_filter_uuid;
+ mp_bluetooth_nimble_pending_characteristic_t pending_char_result;
+ #endif
} mp_bluetooth_nimble_root_pointers_t;
enum {
diff --git a/extmod/nimble/nimble.mk b/extmod/nimble/nimble.mk
index 806630074eb87..fc1709f0e50ab 100644
--- a/extmod/nimble/nimble.mk
+++ b/extmod/nimble/nimble.mk
@@ -5,33 +5,35 @@ ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
EXTMOD_DIR = extmod
NIMBLE_EXTMOD_DIR = $(EXTMOD_DIR)/nimble
-EXTMOD_SRC_C += $(NIMBLE_EXTMOD_DIR)/modbluetooth_nimble.c
+SRC_EXTMOD_C += $(NIMBLE_EXTMOD_DIR)/modbluetooth_nimble.c
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_NIMBLE=1
# Use NimBLE from the submodule in lib/mynewt-nimble by default,
# allowing a port to use their own system version (e.g. ESP32).
MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY ?= 0
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=$(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY)
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=$(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY)
ifeq ($(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY),0)
+GIT_SUBMODULES += lib/mynewt-nimble
+
# On all ports where we provide the full implementation (i.e. not just
# bindings like on ESP32), then we don't need to use the ringbuffer. In this
# case, all NimBLE events are run by the MicroPython scheduler. On Unix, the
# scheduler is also responsible for polling the UART, whereas on STM32 the
# UART is also polled by the RX IRQ.
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
# Without the ringbuffer, and with the full implementation, we can also
# enable pairing and bonding. This requires both synchronous events and
# some customisation of the key store.
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
NIMBLE_LIB_DIR = lib/mynewt-nimble
-LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
+SRC_THIRDPARTY_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
$(addprefix ext/tinycrypt/src/, \
aes_encrypt.c \
cmac_mode.c \
@@ -96,7 +98,7 @@ LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
)
# nimble/host/store/ram/src/ble_store_ram.c \
-EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \
+SRC_THIRDPARTY_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \
nimble/nimble_npl_os.c \
hal/hal_uart.c \
)
diff --git a/extmod/os_dupterm.c b/extmod/os_dupterm.c
new file mode 100644
index 0000000000000..cfd1c62616497
--- /dev/null
+++ b/extmod/os_dupterm.c
@@ -0,0 +1,207 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2017-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include "py/mpconfig.h"
+
+#include "py/runtime.h"
+#include "py/objtuple.h"
+#include "py/objarray.h"
+#include "py/stream.h"
+#include "extmod/misc.h"
+
+#if MICROPY_PY_OS_DUPTERM
+
+#include "shared/runtime/interrupt_char.h"
+
+void mp_os_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
+ mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]);
+ MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL;
+ mp_printf(&mp_plat_print, msg);
+ if (exc != MP_OBJ_NULL) {
+ mp_obj_print_exception(&mp_plat_print, exc);
+ }
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_stream_close(term);
+ nlr_pop();
+ } else {
+ // Ignore any errors during stream closing
+ }
+}
+
+uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags) {
+ uintptr_t poll_flags_out = 0;
+
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ mp_obj_t s = MP_STATE_VM(dupterm_objs[idx]);
+ if (s == MP_OBJ_NULL) {
+ continue;
+ }
+
+ int errcode = 0;
+ mp_uint_t ret = 0;
+ const mp_stream_p_t *stream_p = mp_get_stream(s);
+ #if MICROPY_PY_OS_DUPTERM_BUILTIN_STREAM
+ if (mp_os_dupterm_is_builtin_stream(s)) {
+ ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode);
+ } else
+ #endif
+ {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode);
+ nlr_pop();
+ } else {
+ // Ignore error with ioctl
+ }
+ }
+
+ if (ret != MP_STREAM_ERROR) {
+ poll_flags_out |= ret;
+ if (poll_flags_out == poll_flags) {
+ // Finish early if all requested flags are set
+ break;
+ }
+ }
+ }
+
+ return poll_flags_out;
+}
+
+int mp_os_dupterm_rx_chr(void) {
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
+ continue;
+ }
+
+ #if MICROPY_PY_OS_DUPTERM_BUILTIN_STREAM
+ if (mp_os_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
+ byte buf[1];
+ int errcode = 0;
+ const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
+ mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
+ if (errcode == 0 && out_sz != 0) {
+ return buf[0];
+ } else {
+ continue;
+ }
+ }
+ #endif
+
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ byte buf[1];
+ int errcode;
+ const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
+ mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
+ if (out_sz == 0) {
+ nlr_pop();
+ mp_os_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
+ } else if (out_sz == MP_STREAM_ERROR) {
+ // errcode is valid
+ if (mp_is_nonblocking_error(errcode)) {
+ nlr_pop();
+ } else {
+ mp_raise_OSError(errcode);
+ }
+ } else {
+ // read 1 byte
+ nlr_pop();
+ if (buf[0] == mp_interrupt_char) {
+ // Signal keyboard interrupt to be raised as soon as the VM resumes
+ mp_sched_keyboard_interrupt();
+ return -2;
+ }
+ return buf[0];
+ }
+ } else {
+ mp_os_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
+ }
+ }
+
+ // No chars available
+ return -1;
+}
+
+void mp_os_dupterm_tx_strn(const char *str, size_t len) {
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
+ continue;
+ }
+
+ #if MICROPY_PY_OS_DUPTERM_BUILTIN_STREAM
+ if (mp_os_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
+ int errcode = 0;
+ const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
+ stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode);
+ continue;
+ }
+ #endif
+
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
+ nlr_pop();
+ } else {
+ mp_os_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
+ }
+ }
+}
+
+STATIC mp_obj_t mp_os_dupterm(size_t n_args, const mp_obj_t *args) {
+ mp_int_t idx = 0;
+ if (n_args == 2) {
+ idx = mp_obj_get_int(args[1]);
+ }
+
+ if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid dupterm index"));
+ }
+
+ mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]);
+ if (previous_obj == MP_OBJ_NULL) {
+ previous_obj = mp_const_none;
+ }
+ if (args[0] == mp_const_none) {
+ MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
+ } else {
+ mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
+ MP_STATE_VM(dupterm_objs[idx]) = args[0];
+ }
+
+ #if MICROPY_PY_OS_DUPTERM_STREAM_DETACHED_ATTACHED
+ mp_os_dupterm_stream_detached_attached(previous_obj, args[0]);
+ #endif
+
+ return previous_obj;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_dupterm_obj, 1, 2, mp_os_dupterm);
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]);
+
+#endif // MICROPY_PY_OS_DUPTERM
diff --git a/extmod/uasyncio/__init__.py b/extmod/uasyncio/__init__.py
deleted file mode 100644
index fa64438f6b2a0..0000000000000
--- a/extmod/uasyncio/__init__.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# MicroPython uasyncio module
-# MIT license; Copyright (c) 2019 Damien P. George
-
-from .core import *
-
-__version__ = (3, 0, 0)
-
-_attrs = {
- "wait_for": "funcs",
- "wait_for_ms": "funcs",
- "gather": "funcs",
- "Event": "event",
- "ThreadSafeFlag": "event",
- "Lock": "lock",
- "open_connection": "stream",
- "start_server": "stream",
- "StreamReader": "stream",
- "StreamWriter": "stream",
-}
-
-# Lazy loader, effectively does:
-# global attr
-# from .mod import attr
-def __getattr__(attr):
- mod = _attrs.get(attr, None)
- if mod is None:
- raise AttributeError(attr)
- value = getattr(__import__(mod, None, None, True, 1), attr)
- globals()[attr] = value
- return value
diff --git a/extmod/uasyncio/manifest.py b/extmod/uasyncio/manifest.py
deleted file mode 100644
index f5fa27bfcaa35..0000000000000
--- a/extmod/uasyncio/manifest.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# This list of frozen files doesn't include task.py because that's provided by the C module.
-freeze(
- "..",
- (
- "uasyncio/__init__.py",
- "uasyncio/core.py",
- "uasyncio/event.py",
- "uasyncio/funcs.py",
- "uasyncio/lock.py",
- "uasyncio/stream.py",
- ),
- opt=3,
-)
diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c
deleted file mode 100644
index e18d133b913a2..0000000000000
--- a/extmod/uos_dupterm.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016 Paul Sokolovsky
- * Copyright (c) 2017-2019 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include "py/mpconfig.h"
-
-#include "py/runtime.h"
-#include "py/objtuple.h"
-#include "py/objarray.h"
-#include "py/stream.h"
-#include "extmod/misc.h"
-#include "shared/runtime/interrupt_char.h"
-
-#if MICROPY_PY_OS_DUPTERM
-
-void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
- mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]);
- MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL;
- mp_printf(&mp_plat_print, msg);
- if (exc != MP_OBJ_NULL) {
- mp_obj_print_exception(&mp_plat_print, exc);
- }
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- mp_stream_close(term);
- nlr_pop();
- } else {
- // Ignore any errors during stream closing
- }
-}
-
-uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags) {
- uintptr_t poll_flags_out = 0;
-
- for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
- mp_obj_t s = MP_STATE_VM(dupterm_objs[idx]);
- if (s == MP_OBJ_NULL) {
- continue;
- }
-
- int errcode = 0;
- mp_uint_t ret = 0;
- const mp_stream_p_t *stream_p = mp_get_stream(s);
- #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM
- if (mp_uos_dupterm_is_builtin_stream(s)) {
- ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode);
- } else
- #endif
- {
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode);
- nlr_pop();
- } else {
- // Ignore error with ioctl
- }
- }
-
- if (ret != MP_STREAM_ERROR) {
- poll_flags_out |= ret;
- if (poll_flags_out == poll_flags) {
- // Finish early if all requested flags are set
- break;
- }
- }
- }
-
- return poll_flags_out;
-}
-
-int mp_uos_dupterm_rx_chr(void) {
- for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
- if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
- continue;
- }
-
- #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM
- if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
- byte buf[1];
- int errcode = 0;
- const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
- mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
- if (errcode == 0 && out_sz != 0) {
- return buf[0];
- } else {
- continue;
- }
- }
- #endif
-
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- byte buf[1];
- int errcode;
- const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
- mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
- if (out_sz == 0) {
- nlr_pop();
- mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
- } else if (out_sz == MP_STREAM_ERROR) {
- // errcode is valid
- if (mp_is_nonblocking_error(errcode)) {
- nlr_pop();
- } else {
- mp_raise_OSError(errcode);
- }
- } else {
- // read 1 byte
- nlr_pop();
- if (buf[0] == mp_interrupt_char) {
- // Signal keyboard interrupt to be raised as soon as the VM resumes
- mp_sched_keyboard_interrupt();
- return -2;
- }
- return buf[0];
- }
- } else {
- mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
- }
- }
-
- // No chars available
- return -1;
-}
-
-void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
- for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
- if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
- continue;
- }
-
- #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM
- if (mp_uos_dupterm_is_builtin_stream(MP_STATE_VM(dupterm_objs[idx]))) {
- int errcode = 0;
- const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_VM(dupterm_objs[idx]));
- stream_p->write(MP_STATE_VM(dupterm_objs[idx]), str, len, &errcode);
- continue;
- }
- #endif
-
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- mp_stream_write(MP_STATE_VM(dupterm_objs[idx]), str, len, MP_STREAM_RW_WRITE);
- nlr_pop();
- } else {
- mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", MP_OBJ_FROM_PTR(nlr.ret_val));
- }
- }
-}
-
-STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
- mp_int_t idx = 0;
- if (n_args == 2) {
- idx = mp_obj_get_int(args[1]);
- }
-
- if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid dupterm index"));
- }
-
- mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]);
- if (previous_obj == MP_OBJ_NULL) {
- previous_obj = mp_const_none;
- }
- if (args[0] == mp_const_none) {
- MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
- } else {
- mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
- MP_STATE_VM(dupterm_objs[idx]) = args[0];
- }
-
- #if MICROPY_PY_UOS_DUPTERM_STREAM_DETACHED_ATTACHED
- mp_uos_dupterm_stream_detached_attached(previous_obj, args[0]);
- #endif
-
- return previous_obj;
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm);
-
-#endif
diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c
deleted file mode 100644
index 3d1cdfd820629..0000000000000
--- a/extmod/utime_mphal.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013-2016 Damien P. George
- * Copyright (c) 2016 Paul Sokolovsky
- *
- * 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_UTIME_MP_HAL
-
-#include
-
-#include "py/obj.h"
-#include "py/mphal.h"
-#include "py/smallint.h"
-#include "py/runtime.h"
-#include "extmod/utime_mphal.h"
-
-STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
- #if MICROPY_PY_BUILTINS_FLOAT
- mp_hal_delay_ms((mp_uint_t)(1000 * mp_obj_get_float(seconds_o)));
- #else
- mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
- #endif
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
-
-STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
- mp_int_t ms = mp_obj_get_int(arg);
- if (ms >= 0) {
- mp_hal_delay_ms(ms);
- }
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms);
-
-STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
- mp_int_t us = mp_obj_get_int(arg);
- if (us > 0) {
- mp_hal_delay_us(us);
- }
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us);
-
-STATIC mp_obj_t time_ticks_ms(void) {
- return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
-}
-MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms);
-
-STATIC mp_obj_t time_ticks_us(void) {
- return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
-}
-MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj, time_ticks_us);
-
-STATIC mp_obj_t time_ticks_cpu(void) {
- return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
-}
-MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj, time_ticks_cpu);
-
-STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) {
- // we assume that the arguments come from ticks_xx so are small ints
- mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
- mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
- // Optimized formula avoiding if conditions. We adjust difference "forward",
- // wrap it around and adjust back.
- mp_int_t diff = ((end - start + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
- - MICROPY_PY_UTIME_TICKS_PERIOD / 2;
- return MP_OBJ_NEW_SMALL_INT(diff);
-}
-MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff);
-
-STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {
- // we assume that first argument come from ticks_xx so is small int
- mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
- mp_uint_t delta = mp_obj_get_int(delta_in);
- return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
-}
-MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);
-
-// Returns the number of nanoseconds since the Epoch, as an integer.
-STATIC mp_obj_t time_time_ns(void) {
- return mp_obj_new_int_from_ull(mp_hal_time_ns());
-}
-MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_time_ns_obj, time_time_ns);
-
-#endif // MICROPY_PY_UTIME_MP_HAL
diff --git a/extmod/utime_mphal.h b/extmod/utime_mphal.h
index 57fc348832812..8b137891791fe 100644
--- a/extmod/utime_mphal.h
+++ b/extmod/utime_mphal.h
@@ -1,42 +1 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013-2016 Damien P. George
- * Copyright (c) 2016 Paul Sokolovsky
- *
- * 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_EXTMOD_UTIME_MPHAL_H
-#define MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
-#include "py/obj.h"
-
-MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_obj);
-MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj);
-MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj);
-MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj);
-MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj);
-MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj);
-MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj);
-MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj);
-MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_time_ns_obj);
-
-#endif // MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
diff --git a/extmod/vfs.c b/extmod/vfs.c
index 8e5e036326625..af63ceb37eb19 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -100,6 +100,8 @@ STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) {
if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) {
*path_out = mp_obj_new_str_of_type(mp_obj_get_type(path_in),
(const byte *)p_out, strlen(p_out));
+ } else {
+ *path_out = MP_OBJ_NULL;
}
return vfs;
}
@@ -130,8 +132,9 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) {
}
// If the mounted object has the VFS protocol, call its import_stat helper
- const mp_vfs_proto_t *proto = mp_obj_get_type(vfs->obj)->protocol;
- if (proto != NULL) {
+ const mp_obj_type_t *type = mp_obj_get_type(vfs->obj);
+ if (MP_OBJ_TYPE_HAS_SLOT(type, protocol)) {
+ const mp_vfs_proto_t *proto = MP_OBJ_TYPE_GET_SLOT(type, protocol);
return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out);
}
@@ -170,7 +173,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) {
#if MICROPY_VFS_LFS1
if (memcmp(&buf[32], "littlefs", 8) == 0) {
// LFS1
- mp_obj_t vfs = mp_type_vfs_lfs1.make_new(&mp_type_vfs_lfs1, 1, 0, &bdev_obj);
+ mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs1, make_new)(&mp_type_vfs_lfs1, 1, 0, &bdev_obj);
nlr_pop();
return vfs;
}
@@ -178,7 +181,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) {
#if MICROPY_VFS_LFS2
if (memcmp(&buf[0], "littlefs", 8) == 0) {
// LFS2
- mp_obj_t vfs = mp_type_vfs_lfs2.make_new(&mp_type_vfs_lfs2, 1, 0, &bdev_obj);
+ mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs2, make_new)(&mp_type_vfs_lfs2, 1, 0, &bdev_obj);
nlr_pop();
return vfs;
}
@@ -191,7 +194,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) {
#endif
#if MICROPY_VFS_FAT
- return mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &bdev_obj);
+ return MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new)(&mp_fat_vfs_type, 1, 0, &bdev_obj);
#endif
// no filesystem found
@@ -310,7 +313,7 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
#if MICROPY_VFS_POSIX
// If the file is an integer then delegate straight to the POSIX handler
if (mp_obj_is_small_int(args[ARG_file].u_obj)) {
- return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj);
+ return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj);
}
#endif
@@ -358,7 +361,7 @@ mp_obj_t mp_vfs_getcwd(void) {
if (!(cwd[0] == '/' && cwd[1] == 0)) {
vstr_add_str(&vstr, cwd);
}
- return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
+ return mp_obj_new_str_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd);
@@ -545,4 +548,7 @@ int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point) {
return ret;
}
+MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_cur);
+MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_mount_table);
+
#endif // MICROPY_VFS
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index 27681ca77012a..efb6bf7e9815d 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -28,6 +28,10 @@
#include "py/mpconfig.h"
#if MICROPY_VFS_FAT
+#if !MICROPY_ENABLE_FINALISER
+#error "MICROPY_VFS_FAT requires MICROPY_ENABLE_FINALISER"
+#endif
+
#if !MICROPY_VFS
#error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_VFS"
#endif
@@ -118,6 +122,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mk
typedef struct _mp_vfs_fat_ilistdir_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
+ mp_fun_1_t finaliser;
bool is_str;
FF_DIR dir;
} mp_vfs_fat_ilistdir_it_t;
@@ -162,6 +167,13 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
return MP_OBJ_STOP_ITERATION;
}
+STATIC mp_obj_t mp_vfs_fat_ilistdir_it_del(mp_obj_t self_in) {
+ mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
+ // ignore result / error because we may be closing a second time.
+ f_closedir(&self->dir);
+ return mp_const_none;
+}
+
STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]);
bool is_str_type = true;
@@ -176,8 +188,10 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
}
// Create a new iterator object to list the dir
- mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter);
+ mp_vfs_fat_ilistdir_it_t *iter = m_new_obj_with_finaliser(mp_vfs_fat_ilistdir_it_t);
+ iter->base.type = &mp_type_polymorph_iter_with_finaliser;
iter->iternext = mp_vfs_fat_ilistdir_it_iternext;
+ iter->finaliser = mp_vfs_fat_ilistdir_it_del;
iter->is_str = is_str_type;
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);
if (res != FR_OK) {
@@ -417,13 +431,13 @@ STATIC const mp_vfs_proto_t fat_vfs_proto = {
.import_stat = fat_vfs_import_stat,
};
-const mp_obj_type_t mp_fat_vfs_type = {
- { &mp_type_type },
- .name = MP_QSTR_VfsFat,
- .make_new = fat_vfs_make_new,
- .protocol = &fat_vfs_proto,
- .locals_dict = (mp_obj_dict_t *)&fat_vfs_locals_dict,
-
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_fat_vfs_type,
+ MP_QSTR_VfsFat,
+ MP_TYPE_FLAG_NONE,
+ make_new, fat_vfs_make_new,
+ protocol, &fat_vfs_proto,
+ locals_dict, &fat_vfs_locals_dict
+ );
#endif // MICROPY_VFS_FAT
diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c
index 537101d00f406..07e6df9bf9595 100644
--- a/extmod/vfs_fat_file.c
+++ b/extmod/vfs_fat_file.c
@@ -151,18 +151,63 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
}
}
-// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO,
-// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor
-STATIC const mp_arg_t file_open_args[] = {
- { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} },
- { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
+// TODO gc hook to close the file if not already closed
+
+STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) },
+ { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) },
};
-#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
-STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) {
+STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table);
+
+STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = {
+ .read = file_obj_read,
+ .write = file_obj_write,
+ .ioctl = file_obj_ioctl,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_fat_fileio,
+ MP_QSTR_FileIO,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, file_obj_print,
+ protocol, &vfs_fat_fileio_stream_p,
+ locals_dict, &vfs_fat_rawfile_locals_dict
+ );
+
+STATIC const mp_stream_p_t vfs_fat_textio_stream_p = {
+ .read = file_obj_read,
+ .write = file_obj_write,
+ .ioctl = file_obj_ioctl,
+ .is_text = true,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_fat_textio,
+ MP_QSTR_TextIOWrapper,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, file_obj_print,
+ protocol, &vfs_fat_textio_stream_p,
+ locals_dict, &vfs_fat_rawfile_locals_dict
+ );
+
+// Factory function for I/O stream classes
+STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) {
+ fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
+
+ const mp_obj_type_t *type = &mp_type_vfs_fat_textio;
int mode = 0;
- const char *mode_s = mp_obj_str_get_str(args[1].u_obj);
+ const char *mode_s = mp_obj_str_get_str(mode_in);
// TODO make sure only one of r, w, x, a, and b, t are specified
while (*mode_s) {
switch (*mode_s++) {
@@ -181,11 +226,9 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
case '+':
mode |= FA_READ | FA_WRITE;
break;
- #if MICROPY_PY_IO_FILEIO
case 'b':
type = &mp_type_vfs_fat_fileio;
break;
- #endif
case 't':
type = &mp_type_vfs_fat_textio;
break;
@@ -195,9 +238,8 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t);
o->base.type = type;
- const char *fname = mp_obj_str_get_str(args[0].u_obj);
- assert(vfs != NULL);
- FRESULT res = f_open(&vfs->fatfs, &o->fp, fname, mode);
+ const char *fname = mp_obj_str_get_str(path_in);
+ FRESULT res = f_open(&self->fatfs, &o->fp, fname, mode);
if (res != FR_OK) {
m_del_obj(pyb_file_obj_t, o);
mp_raise_OSError(fresult_to_errno_table[res]);
@@ -210,79 +252,6 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
return MP_OBJ_FROM_PTR(o);
}
-
-STATIC mp_obj_t file_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
- mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals);
- return file_open(NULL, type, arg_vals);
-}
-
-// TODO gc hook to close the file if not already closed
-
-STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_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_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) },
- { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
- { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
- { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
- { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) },
- { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
- { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
- { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
- { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table);
-
-#if MICROPY_PY_IO_FILEIO
-STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = {
- .read = file_obj_read,
- .write = file_obj_write,
- .ioctl = file_obj_ioctl,
-};
-
-const mp_obj_type_t mp_type_vfs_fat_fileio = {
- { &mp_type_type },
- .name = MP_QSTR_FileIO,
- .print = file_obj_print,
- .make_new = file_obj_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_fat_fileio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict,
-};
-#endif
-
-STATIC const mp_stream_p_t vfs_fat_textio_stream_p = {
- .read = file_obj_read,
- .write = file_obj_write,
- .ioctl = file_obj_ioctl,
- .is_text = true,
-};
-
-const mp_obj_type_t mp_type_vfs_fat_textio = {
- { &mp_type_type },
- .name = MP_QSTR_TextIOWrapper,
- .print = file_obj_print,
- .make_new = file_obj_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_fat_textio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict,
-};
-
-// Factory function for I/O stream classes
-STATIC mp_obj_t fatfs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode) {
- // TODO: analyze buffering args and instantiate appropriate type
- fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
- mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
- arg_vals[0].u_obj = path;
- arg_vals[1].u_obj = mode;
- arg_vals[2].u_obj = mp_const_none;
- return file_open(self, &mp_type_vfs_fat_textio, arg_vals);
-}
-MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self);
+MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fat_vfs_open);
#endif // MICROPY_VFS && MICROPY_VFS_FAT
diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c
index f6a9a24623a93..4fb86b89b76c3 100644
--- a/extmod/vfs_lfs.c
+++ b/extmod/vfs_lfs.c
@@ -26,12 +26,13 @@
#include "py/runtime.h"
#include "py/mphal.h"
+
+#if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2)
+
#include "shared/timeutils/timeutils.h"
#include "extmod/vfs.h"
#include "extmod/vfs_lfs.h"
-#if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2)
-
enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead, LFS_MAKE_ARG_mtime };
static const mp_arg_t lfs_make_allowed_args[] = {
diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c
index dbd32338cfd9f..fe0731eced2a8 100644
--- a/extmod/vfs_lfsx.c
+++ b/extmod/vfs_lfsx.c
@@ -24,6 +24,9 @@
* THE SOFTWARE.
*/
+// This file should be compiled when included from vfs_lfs.c.
+#if defined(LFS_BUILD_VERSION)
+
#include
#include
@@ -36,6 +39,10 @@
#include "extmod/vfs.h"
#include "shared/timeutils/timeutils.h"
+#if !MICROPY_ENABLE_FINALISER
+#error "MICROPY_VFS_LFS requires MICROPY_ENABLE_FINALISER"
+#endif
+
STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, int arg, bool must_return_int) {
mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg);
int ret_i = 0;
@@ -155,6 +162,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open));
typedef struct MP_VFS_LFSx (_ilistdir_it_t) {
mp_obj_base_t base;
mp_fun_1_t iternext;
+ mp_fun_1_t finaliser;
bool is_str;
MP_OBJ_VFS_LFSx *vfs;
LFSx_API(dir_t) dir;
@@ -163,11 +171,16 @@ typedef struct MP_VFS_LFSx (_ilistdir_it_t) {
STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) {
MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in);
+ if (self->vfs == NULL) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
struct LFSx_API (info) info;
for (;;) {
int ret = LFSx_API(dir_read)(&self->vfs->lfs, &self->dir, &info);
if (ret == 0) {
LFSx_API(dir_close)(&self->vfs->lfs, &self->dir);
+ self->vfs = NULL;
return MP_OBJ_STOP_ITERATION;
}
if (!(info.name[0] == '.' && (info.name[1] == '\0'
@@ -190,6 +203,14 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) {
return MP_OBJ_FROM_PTR(t);
}
+STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_del)(mp_obj_t self_in) {
+ MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in);
+ if (self->vfs != NULL) {
+ LFSx_API(dir_close)(&self->vfs->lfs, &self->dir);
+ }
+ return mp_const_none;
+}
+
STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) {
MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(args[0]);
bool is_str_type = true;
@@ -203,14 +224,17 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args)
path = vstr_null_terminated_str(&self->cur_dir);
}
- MP_VFS_LFSx(ilistdir_it_t) * iter = mp_obj_malloc(MP_VFS_LFSx(ilistdir_it_t), &mp_type_polymorph_iter);
+ MP_VFS_LFSx(ilistdir_it_t) * iter = m_new_obj_with_finaliser(MP_VFS_LFSx(ilistdir_it_t));
+ iter->base.type = &mp_type_polymorph_iter_with_finaliser;
+
iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext);
+ iter->finaliser = MP_VFS_LFSx(ilistdir_it_del);
iter->is_str = is_str_type;
- iter->vfs = self;
int ret = LFSx_API(dir_open)(&self->lfs, &iter->dir, path);
if (ret < 0) {
mp_raise_OSError(-ret);
}
+ iter->vfs = self;
return MP_OBJ_FROM_PTR(iter);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func));
@@ -299,7 +323,7 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) {
size_t from = 1;
char *cwd = vstr_str(&self->cur_dir);
while (from < CWD_LEN) {
- for (; cwd[from] == '/' && from < CWD_LEN; ++from) {
+ for (; from < CWD_LEN && cwd[from] == '/'; ++from) {
// Scan for the start
}
if (from > to) {
@@ -307,7 +331,7 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) {
vstr_cut_out_bytes(&self->cur_dir, to, from - to);
from = to;
}
- for (; cwd[from] != '/' && from < CWD_LEN; ++from) {
+ for (; from < CWD_LEN && cwd[from] != '/'; ++from) {
// Scan for the next /
}
if ((from - to) == 1 && cwd[to] == '.') {
@@ -481,14 +505,21 @@ STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = {
.import_stat = MP_VFS_LFSx(import_stat),
};
-const mp_obj_type_t MP_TYPE_VFS_LFSx = {
- { &mp_type_type },
- #if LFS_BUILD_VERSION == 1
- .name = MP_QSTR_VfsLfs1,
- #else
- .name = MP_QSTR_VfsLfs2,
- #endif
- .make_new = MP_VFS_LFSx(make_new),
- .protocol = &MP_VFS_LFSx(proto),
- .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(locals_dict),
-};
+#if LFS_BUILD_VERSION == 1
+#define VFS_LFSx_QSTR MP_QSTR_VfsLfs1
+#else
+#define VFS_LFSx_QSTR MP_QSTR_VfsLfs2
+#endif
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ MP_TYPE_VFS_LFSx,
+ VFS_LFSx_QSTR,
+ MP_TYPE_FLAG_NONE,
+ make_new, MP_VFS_LFSx(make_new),
+ protocol, &MP_VFS_LFSx(proto),
+ locals_dict, &MP_VFS_LFSx(locals_dict)
+ );
+
+#undef VFS_LFSx_QSTR
+
+#endif // defined(LFS_BUILD_VERSION)
diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c
index bc1a37b90bdb8..5f0155d3c5c04 100644
--- a/extmod/vfs_lfsx_file.c
+++ b/extmod/vfs_lfsx_file.c
@@ -24,6 +24,9 @@
* THE SOFTWARE.
*/
+// This file should be compiled when included from vfs_lfs.c.
+#if defined(LFS_BUILD_VERSION)
+
#include
#include
@@ -68,11 +71,9 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod
case '+':
flags |= LFSx_MACRO(_O_RDWR);
break;
- #if MICROPY_PY_IO_FILEIO
case 'b':
type = &MP_TYPE_VFS_LFSx_(_fileio);
break;
- #endif
case 't':
type = &MP_TYPE_VFS_LFSx_(_textio);
break;
@@ -216,23 +217,20 @@ STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = {
};
STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table));
-#if MICROPY_PY_IO_FILEIO
STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = {
.read = MP_VFS_LFSx(file_read),
.write = MP_VFS_LFSx(file_write),
.ioctl = MP_VFS_LFSx(file_ioctl),
};
-const mp_obj_type_t MP_TYPE_VFS_LFSx_(_fileio) = {
- { &mp_type_type },
- .name = MP_QSTR_FileIO,
- .print = MP_VFS_LFSx(file_print),
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &MP_VFS_LFSx(fileio_stream_p),
- .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict),
-};
-#endif
+MP_DEFINE_CONST_OBJ_TYPE(
+ MP_TYPE_VFS_LFSx_(_fileio),
+ MP_QSTR_FileIO,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, MP_VFS_LFSx(file_print),
+ protocol, &MP_VFS_LFSx(fileio_stream_p),
+ locals_dict, &MP_VFS_LFSx(file_locals_dict)
+ );
STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = {
.read = MP_VFS_LFSx(file_read),
@@ -241,12 +239,13 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = {
.is_text = true,
};
-const mp_obj_type_t MP_TYPE_VFS_LFSx_(_textio) = {
- { &mp_type_type },
- .name = MP_QSTR_TextIOWrapper,
- .print = MP_VFS_LFSx(file_print),
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &MP_VFS_LFSx(textio_stream_p),
- .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict),
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ MP_TYPE_VFS_LFSx_(_textio),
+ MP_QSTR_TextIOWrapper,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, MP_VFS_LFSx(file_print),
+ protocol, &MP_VFS_LFSx(textio_stream_p),
+ locals_dict, &MP_VFS_LFSx(file_locals_dict)
+ );
+
+#endif // defined(LFS_BUILD_VERSION)
diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c
index 1ada596d137c1..d63bb5be7bff4 100644
--- a/extmod/vfs_posix.c
+++ b/extmod/vfs_posix.c
@@ -33,9 +33,15 @@
#if MICROPY_VFS_POSIX
+#if !MICROPY_ENABLE_FINALISER
+#error "MICROPY_VFS_POSIX requires MICROPY_ENABLE_FINALISER"
+#endif
+
+#include
#include
#include
#include
+#include
#include
#ifdef _MSC_VER
#include // For mkdir etc.
@@ -138,7 +144,7 @@ STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode
if (!mp_obj_is_small_int(path_in)) {
path_in = vfs_posix_get_path_obj(self, path_in);
}
- return mp_vfs_posix_file_open(&mp_type_textio, path_in, mode_in);
+ return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, path_in, mode_in);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_open_obj, vfs_posix_open);
@@ -162,6 +168,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd);
typedef struct _vfs_posix_ilistdir_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
+ mp_fun_1_t finaliser;
bool is_str;
DIR *dir;
} vfs_posix_ilistdir_it_t;
@@ -185,7 +192,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
MP_THREAD_GIL_ENTER();
const char *fn = dirent->d_name;
- if (fn[0] == '.' && (fn[1] == 0 || fn[1] == '.')) {
+ if (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0))) {
// skip . and ..
continue;
}
@@ -226,10 +233,22 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
}
}
+STATIC mp_obj_t vfs_posix_ilistdir_it_del(mp_obj_t self_in) {
+ vfs_posix_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->dir != NULL) {
+ MP_THREAD_GIL_EXIT();
+ closedir(self->dir);
+ MP_THREAD_GIL_ENTER();
+ }
+ return mp_const_none;
+}
+
STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
- vfs_posix_ilistdir_it_t *iter = mp_obj_malloc(vfs_posix_ilistdir_it_t, &mp_type_polymorph_iter);
+ vfs_posix_ilistdir_it_t *iter = m_new_obj_with_finaliser(vfs_posix_ilistdir_it_t);
+ iter->base.type = &mp_type_polymorph_iter_with_finaliser;
iter->iternext = vfs_posix_ilistdir_it_iternext;
+ iter->finaliser = vfs_posix_ilistdir_it_del;
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
const char *path = vfs_posix_get_path_str(self, path_in);
if (path[0] == '\0') {
@@ -313,7 +332,7 @@ STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat);
-#if MICROPY_PY_UOS_STATVFS
+#if MICROPY_PY_OS_STATVFS
#ifdef __ANDROID__
#define USE_STATFS 1
@@ -371,7 +390,7 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_posix_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_posix_rmdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_posix_stat_obj) },
- #if MICROPY_PY_UOS_STATVFS
+ #if MICROPY_PY_OS_STATVFS
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_posix_statvfs_obj) },
#endif
};
@@ -381,12 +400,13 @@ STATIC const mp_vfs_proto_t vfs_posix_proto = {
.import_stat = mp_vfs_posix_import_stat,
};
-const mp_obj_type_t mp_type_vfs_posix = {
- { &mp_type_type },
- .name = MP_QSTR_VfsPosix,
- .make_new = vfs_posix_make_new,
- .protocol = &vfs_posix_proto,
- .locals_dict = (mp_obj_dict_t *)&vfs_posix_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_posix,
+ MP_QSTR_VfsPosix,
+ MP_TYPE_FLAG_NONE,
+ make_new, vfs_posix_make_new,
+ protocol, &vfs_posix_proto,
+ locals_dict, &vfs_posix_locals_dict
+ );
#endif // MICROPY_VFS_POSIX
diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c
index 837c5489b0e14..1d89e3ca09737 100644
--- a/extmod/vfs_posix_file.c
+++ b/extmod/vfs_posix_file.c
@@ -30,7 +30,7 @@
#include "py/stream.h"
#include "extmod/vfs_posix.h"
-#if MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE
+#if MICROPY_VFS_POSIX
#include
#include
@@ -46,7 +46,7 @@ typedef struct _mp_obj_vfs_posix_file_t {
int fd;
} mp_obj_vfs_posix_file_t;
-#ifdef MICROPY_CPYTHON_COMPAT
+#if MICROPY_CPYTHON_COMPAT
STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) {
if (o->fd < 0) {
mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file"));
@@ -63,7 +63,7 @@ STATIC void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_p
}
mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) {
- mp_obj_vfs_posix_file_t *o = m_new_obj(mp_obj_vfs_posix_file_t);
+ mp_obj_vfs_posix_file_t *o = m_new_obj_with_finaliser(mp_obj_vfs_posix_file_t);
const char *mode_s = mp_obj_str_get_str(mode_in);
int mode_rw = 0, mode_x = 0;
@@ -83,15 +83,12 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
case '+':
mode_rw = O_RDWR;
break;
- #if MICROPY_PY_IO_FILEIO
- // If we don't have io.FileIO, then files are in text mode implicitly
case 'b':
type = &mp_type_vfs_posix_fileio;
break;
case 't':
type = &mp_type_vfs_posix_textio;
break;
- #endif
}
}
@@ -111,17 +108,6 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
return MP_OBJ_FROM_PTR(o);
}
-STATIC mp_obj_t vfs_posix_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} },
- };
-
- mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals);
- return mp_vfs_posix_file_open(type, arg_vals[0].u_obj, arg_vals[1].u_obj);
-}
-
STATIC mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) {
mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in);
check_fd_is_open(self);
@@ -199,16 +185,16 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
return 0;
}
case MP_STREAM_CLOSE:
- MP_THREAD_GIL_EXIT();
- close(o->fd);
- MP_THREAD_GIL_ENTER();
- #ifdef MICROPY_CPYTHON_COMPAT
+ if (o->fd >= 0) {
+ MP_THREAD_GIL_EXIT();
+ close(o->fd);
+ MP_THREAD_GIL_ENTER();
+ }
o->fd = -1;
- #endif
return 0;
case MP_STREAM_GET_FILENO:
return o->fd;
- #if MICROPY_PY_USELECT
+ #if MICROPY_PY_SELECT
case MP_STREAM_POLL: {
#ifdef _WIN32
mp_raise_NotImplementedError(MP_ERROR_TEXT("poll on file not available on win32"));
@@ -251,30 +237,27 @@ STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) },
};
STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table);
-#if MICROPY_PY_IO_FILEIO
STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = {
.read = vfs_posix_file_read,
.write = vfs_posix_file_write,
.ioctl = vfs_posix_file_ioctl,
};
-const mp_obj_type_t mp_type_vfs_posix_fileio = {
- { &mp_type_type },
- .name = MP_QSTR_FileIO,
- .print = vfs_posix_file_print,
- .make_new = vfs_posix_file_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_posix_fileio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict,
-};
-#endif
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_posix_fileio,
+ MP_QSTR_FileIO,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, vfs_posix_file_print,
+ protocol, &vfs_posix_fileio_stream_p,
+ locals_dict, &vfs_posix_rawfile_locals_dict
+ );
STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
.read = vfs_posix_file_read,
@@ -283,19 +266,17 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
.is_text = true,
};
-const mp_obj_type_t mp_type_vfs_posix_textio = {
- { &mp_type_type },
- .name = MP_QSTR_TextIOWrapper,
- .print = vfs_posix_file_print,
- .make_new = vfs_posix_file_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_posix_textio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_posix_textio,
+ MP_QSTR_TextIOWrapper,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, vfs_posix_file_print,
+ protocol, &vfs_posix_textio_stream_p,
+ locals_dict, &vfs_posix_rawfile_locals_dict
+ );
-const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_textio}, STDIN_FILENO};
-const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_textio}, STDOUT_FILENO};
-const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_textio}, STDERR_FILENO};
+const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO};
+const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO};
+const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO};
-#endif // MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE
+#endif // MICROPY_VFS_POSIX
diff --git a/extmod/virtpin.c b/extmod/virtpin.c
index 71a11232d4339..cd0b9f92f830e 100644
--- a/extmod/virtpin.c
+++ b/extmod/virtpin.c
@@ -28,12 +28,12 @@
int mp_virtual_pin_read(mp_obj_t pin) {
mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin);
- mp_pin_p_t *pin_p = (mp_pin_p_t *)s->type->protocol;
+ mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL);
}
void mp_virtual_pin_write(mp_obj_t pin, int value) {
mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin);
- mp_pin_p_t *pin_p = (mp_pin_p_t *)s->type->protocol;
+ mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL);
}
diff --git a/extmod/webrepl/manifest.py b/extmod/webrepl/manifest.py
deleted file mode 100644
index 6eceb3eeb6c56..0000000000000
--- a/extmod/webrepl/manifest.py
+++ /dev/null
@@ -1 +0,0 @@
-freeze(".", ("webrepl.py", "webrepl_setup.py", "websocket_helper.py"))
diff --git a/extmod/webrepl/webrepl.py b/extmod/webrepl/webrepl.py
deleted file mode 100644
index 0de813cda18c7..0000000000000
--- a/extmod/webrepl/webrepl.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# This module should be imported from REPL, not run from command line.
-import socket
-import uos
-import network
-import uwebsocket
-import websocket_helper
-import _webrepl
-
-listen_s = None
-client_s = None
-
-
-def setup_conn(port, accept_handler):
- global listen_s
- listen_s = socket.socket()
- listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
- ai = socket.getaddrinfo("0.0.0.0", port)
- addr = ai[0][4]
-
- listen_s.bind(addr)
- listen_s.listen(1)
- if accept_handler:
- listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
- for i in (network.AP_IF, network.STA_IF):
- iface = network.WLAN(i)
- if iface.active():
- print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port))
- return listen_s
-
-
-def accept_conn(listen_sock):
- global client_s
- cl, remote_addr = listen_sock.accept()
- prev = uos.dupterm(None)
- uos.dupterm(prev)
- if prev:
- print("\nConcurrent WebREPL connection from", remote_addr, "rejected")
- cl.close()
- return
- print("\nWebREPL connection from:", remote_addr)
- client_s = cl
- websocket_helper.server_handshake(cl)
- ws = uwebsocket.websocket(cl, True)
- ws = _webrepl._webrepl(ws)
- cl.setblocking(False)
- # notify REPL on socket incoming data (ESP32/ESP8266-only)
- if hasattr(uos, "dupterm_notify"):
- cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify)
- uos.dupterm(ws)
-
-
-def stop():
- global listen_s, client_s
- uos.dupterm(None)
- if client_s:
- client_s.close()
- if listen_s:
- listen_s.close()
-
-
-def start(port=8266, password=None, accept_handler=accept_conn):
- stop()
- webrepl_pass = password
- if webrepl_pass is None:
- try:
- import webrepl_cfg
-
- webrepl_pass = webrepl_cfg.PASS
- except:
- print("WebREPL is not configured, run 'import webrepl_setup'")
-
- _webrepl.password(webrepl_pass)
- s = setup_conn(port, accept_handler)
-
- if accept_handler is None:
- print("Starting webrepl in foreground mode")
- accept_conn(s)
- elif password is None:
- print("Started webrepl in normal mode")
- else:
- print("Started webrepl in manual override mode")
-
-
-def start_foreground(port=8266, password=None):
- start(port, password, None)
diff --git a/extmod/webrepl/webrepl_setup.py b/extmod/webrepl/webrepl_setup.py
deleted file mode 100644
index ffc9c77fc0deb..0000000000000
--- a/extmod/webrepl/webrepl_setup.py
+++ /dev/null
@@ -1,108 +0,0 @@
-import sys
-
-# import uos as os
-import os
-import machine
-
-RC = "./boot.py"
-CONFIG = "./webrepl_cfg.py"
-
-
-def input_choice(prompt, choices):
- while 1:
- resp = input(prompt)
- if resp in choices:
- return resp
-
-
-def getpass(prompt):
- return input(prompt)
-
-
-def input_pass():
- while 1:
- passwd1 = getpass("New password (4-9 chars): ")
- if len(passwd1) < 4 or len(passwd1) > 9:
- print("Invalid password length")
- continue
- passwd2 = getpass("Confirm password: ")
- if passwd1 == passwd2:
- return passwd1
- print("Passwords do not match")
-
-
-def exists(fname):
- try:
- with open(fname):
- pass
- return True
- except OSError:
- return False
-
-
-def get_daemon_status():
- with open(RC) as f:
- for l in f:
- if "webrepl" in l:
- if l.startswith("#"):
- return False
- return True
- return None
-
-
-def change_daemon(action):
- LINES = ("import webrepl", "webrepl.start()")
- with open(RC) as old_f, open(RC + ".tmp", "w") as new_f:
- found = False
- for l in old_f:
- for patt in LINES:
- if patt in l:
- found = True
- if action and l.startswith("#"):
- l = l[1:]
- elif not action and not l.startswith("#"):
- l = "#" + l
- new_f.write(l)
- if not found:
- new_f.write("import webrepl\nwebrepl.start()\n")
- # FatFs rename() is not POSIX compliant, will raise OSError if
- # dest file exists.
- os.remove(RC)
- os.rename(RC + ".tmp", RC)
-
-
-def main():
- status = get_daemon_status()
-
- print("WebREPL daemon auto-start status:", "enabled" if status else "disabled")
- print("\nWould you like to (E)nable or (D)isable it running on boot?")
- print("(Empty line to quit)")
- resp = input("> ").upper()
-
- if resp == "E":
- if exists(CONFIG):
- resp2 = input_choice(
- "Would you like to change WebREPL password? (y/n) ", ("y", "n", "")
- )
- else:
- print("To enable WebREPL, you must set password for it")
- resp2 = "y"
-
- if resp2 == "y":
- passwd = input_pass()
- with open(CONFIG, "w") as f:
- f.write("PASS = %r\n" % passwd)
-
- if resp not in ("D", "E") or (resp == "D" and not status) or (resp == "E" and status):
- print("No further action required")
- sys.exit()
-
- change_daemon(resp == "E")
-
- print("Changes will be activated after reboot")
- resp = input_choice("Would you like to reboot now? (y/n) ", ("y", "n", ""))
- if resp == "y":
- machine.reset()
-
-
-main()
diff --git a/extmod/webrepl/websocket_helper.py b/extmod/webrepl/websocket_helper.py
deleted file mode 100644
index 3260acc52f377..0000000000000
--- a/extmod/webrepl/websocket_helper.py
+++ /dev/null
@@ -1,85 +0,0 @@
-try:
- import usys as sys
-except ImportError:
- import sys
-
-try:
- import ubinascii as binascii
-except:
- import binascii
-try:
- import uhashlib as hashlib
-except:
- import hashlib
-
-DEBUG = 0
-
-
-def server_handshake(sock):
- clr = sock.makefile("rwb", 0)
- l = clr.readline()
- # sys.stdout.write(repr(l))
-
- webkey = None
-
- while 1:
- l = clr.readline()
- if not l:
- raise OSError("EOF in headers")
- if l == b"\r\n":
- break
- # sys.stdout.write(l)
- h, v = [x.strip() for x in l.split(b":", 1)]
- if DEBUG:
- print((h, v))
- if h == b"Sec-WebSocket-Key":
- webkey = v
-
- if not webkey:
- raise OSError("Not a websocket request")
-
- if DEBUG:
- print("Sec-WebSocket-Key:", webkey, len(webkey))
-
- d = hashlib.sha1(webkey)
- d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
- respkey = d.digest()
- respkey = binascii.b2a_base64(respkey)[:-1]
- if DEBUG:
- print("respkey:", respkey)
-
- sock.send(
- b"""\
-HTTP/1.1 101 Switching Protocols\r
-Upgrade: websocket\r
-Connection: Upgrade\r
-Sec-WebSocket-Accept: """
- )
- sock.send(respkey)
- sock.send("\r\n\r\n")
-
-
-# Very simplified client handshake, works for MicroPython's
-# websocket server implementation, but probably not for other
-# servers.
-def client_handshake(sock):
- cl = sock.makefile("rwb", 0)
- cl.write(
- b"""\
-GET / HTTP/1.1\r
-Host: echo.websocket.org\r
-Connection: Upgrade\r
-Upgrade: websocket\r
-Sec-WebSocket-Key: foo\r
-\r
-"""
- )
- l = cl.readline()
- # print(l)
- while 1:
- l = cl.readline()
- if l == b"\r\n":
- break
-
-
-# sys.stdout.write(l)
diff --git a/lib/btstack b/lib/btstack
index c8b9823f68c6a..77e752abd6a09 160000
--- a/lib/btstack
+++ b/lib/btstack
@@ -1 +1 @@
-Subproject commit c8b9823f68c6af0fa52e2c4e009aba4dbf257232
+Subproject commit 77e752abd6a0992334047a48038a5a3960e5c6bc
diff --git a/lib/cyw43-driver b/lib/cyw43-driver
new file mode 160000
index 0000000000000..8ef38a6d32c54
--- /dev/null
+++ b/lib/cyw43-driver
@@ -0,0 +1 @@
+Subproject commit 8ef38a6d32c54f850bff8f189bdca19ded33792a
diff --git a/lib/fsp b/lib/fsp
index 55bffd3a71cbe..e78939d32d1cc 160000
--- a/lib/fsp
+++ b/lib/fsp
@@ -1 +1 @@
-Subproject commit 55bffd3a71cbeed2104cf30e7a39b641d8c1ff48
+Subproject commit e78939d32d1ccea9f0ba8bb42c51aceffd386b9b
diff --git a/lib/libm/thumb_vfp_sqrtf.c b/lib/libm/thumb_vfp_sqrtf.c
index 12ffebf827090..25b8823163c6c 100644
--- a/lib/libm/thumb_vfp_sqrtf.c
+++ b/lib/libm/thumb_vfp_sqrtf.c
@@ -3,7 +3,7 @@
#include
float sqrtf(float x) {
- asm volatile (
+ __asm__ volatile (
"vsqrt.f32 %[r], %[x]\n"
: [r] "=t" (x)
: [x] "t" (x));
diff --git a/lib/libm_dbl/thumb_vfp_sqrt.c b/lib/libm_dbl/thumb_vfp_sqrt.c
index dd37a07b053c5..ccd33e97960f4 100644
--- a/lib/libm_dbl/thumb_vfp_sqrt.c
+++ b/lib/libm_dbl/thumb_vfp_sqrt.c
@@ -2,7 +2,7 @@
double sqrt(double x) {
double ret;
- asm volatile (
+ __asm__ volatile (
"vsqrt.f64 %P0, %P1\n"
: "=w" (ret)
: "w" (x));
diff --git a/lib/lwip b/lib/lwip
index 159e31b689577..6ca936f6b588c 160000
--- a/lib/lwip
+++ b/lib/lwip
@@ -1 +1 @@
-Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10
+Subproject commit 6ca936f6b588cee702c638eee75c2436e6cf75de
diff --git a/lib/mbedtls b/lib/mbedtls
index 1bc2c9cb8b8fe..981743de6fcdb 160000
--- a/lib/mbedtls
+++ b/lib/mbedtls
@@ -1 +1 @@
-Subproject commit 1bc2c9cb8b8fe4659bd94b8ebba5a4c02029b7fa
+Subproject commit 981743de6fcdbe672e482b6fd724d31d0a0d2476
diff --git a/lib/mbedtls_errors/error.fmt b/lib/mbedtls_errors/error.fmt
index 5beeb6e7c96b0..15889128d44c9 100644
--- a/lib/mbedtls_errors/error.fmt
+++ b/lib/mbedtls_errors/error.fmt
@@ -110,7 +110,7 @@ void mbedtls_strerror(int ret, char *buf, size_t buflen) {
if (got_hl) {
use_ret = ret & 0xFF80;
- // special case
+ // special case, don't try to translate low level code
#if defined(MBEDTLS_SSL_TLS_C)
if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
diff --git a/lib/mbedtls_errors/esp32_mbedtls_errors.c b/lib/mbedtls_errors/esp32_mbedtls_errors.c
new file mode 100644
index 0000000000000..c56f8a19ffb15
--- /dev/null
+++ b/lib/mbedtls_errors/esp32_mbedtls_errors.c
@@ -0,0 +1,710 @@
+/*
+ * Error message information
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+#include "mbedtls/error.h"
+#include
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#define mbedtls_snprintf snprintf
+#define mbedtls_time_t time_t
+#endif
+
+#if defined(MBEDTLS_ERROR_C)
+
+#include
+
+#if defined(MBEDTLS_AES_C)
+#include "mbedtls/aes.h"
+#endif
+
+#if defined(MBEDTLS_ARC4_C)
+#include "mbedtls/arc4.h"
+#endif
+
+#if defined(MBEDTLS_ARIA_C)
+#include "mbedtls/aria.h"
+#endif
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+#include "mbedtls/asn1.h"
+#endif
+
+#if defined(MBEDTLS_BASE64_C)
+#include "mbedtls/base64.h"
+#endif
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+#if defined(MBEDTLS_BLOWFISH_C)
+#include "mbedtls/blowfish.h"
+#endif
+
+#if defined(MBEDTLS_CAMELLIA_C)
+#include "mbedtls/camellia.h"
+#endif
+
+#if defined(MBEDTLS_CCM_C)
+#include "mbedtls/ccm.h"
+#endif
+
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
+#if defined(MBEDTLS_CIPHER_C)
+#include "mbedtls/cipher.h"
+#endif
+
+#if defined(MBEDTLS_CMAC_C)
+#include "mbedtls/cmac.h"
+#endif
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+#include "mbedtls/ctr_drbg.h"
+#endif
+
+#if defined(MBEDTLS_DES_C)
+#include "mbedtls/des.h"
+#endif
+
+#if defined(MBEDTLS_DHM_C)
+#include "mbedtls/dhm.h"
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+#include "mbedtls/ecp.h"
+#endif
+
+#if defined(MBEDTLS_ENTROPY_C)
+#include "mbedtls/entropy.h"
+#endif
+
+#if defined(MBEDTLS_GCM_C)
+#include "mbedtls/gcm.h"
+#endif
+
+#if defined(MBEDTLS_HKDF_C)
+#include "mbedtls/hkdf.h"
+#endif
+
+#if defined(MBEDTLS_HMAC_DRBG_C)
+#include "mbedtls/hmac_drbg.h"
+#endif
+
+#if defined(MBEDTLS_MD_C)
+#include "mbedtls/md.h"
+#endif
+
+#if defined(MBEDTLS_MD2_C)
+#include "mbedtls/md2.h"
+#endif
+
+#if defined(MBEDTLS_MD4_C)
+#include "mbedtls/md4.h"
+#endif
+
+#if defined(MBEDTLS_MD5_C)
+#include "mbedtls/md5.h"
+#endif
+
+#if defined(MBEDTLS_NET_C)
+#include "mbedtls/net_sockets.h"
+#endif
+
+#if defined(MBEDTLS_OID_C)
+#include "mbedtls/oid.h"
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C)
+#include "mbedtls/padlock.h"
+#endif
+
+#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
+#include "mbedtls/pem.h"
+#endif
+
+#if defined(MBEDTLS_PK_C)
+#include "mbedtls/pk.h"
+#endif
+
+#if defined(MBEDTLS_PKCS12_C)
+#include "mbedtls/pkcs12.h"
+#endif
+
+#if defined(MBEDTLS_PKCS5_C)
+#include "mbedtls/pkcs5.h"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#endif
+
+#if defined(MBEDTLS_POLY1305_C)
+#include "mbedtls/poly1305.h"
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+#include "mbedtls/ripemd160.h"
+#endif
+
+#if defined(MBEDTLS_RSA_C)
+#include "mbedtls/rsa.h"
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+#include "mbedtls/sha1.h"
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+#include "mbedtls/sha256.h"
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+#include "mbedtls/sha512.h"
+#endif
+
+#if defined(MBEDTLS_SSL_TLS_C)
+#include "mbedtls/ssl.h"
+#endif
+
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
+#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
+#include "mbedtls/x509.h"
+#endif
+
+#if defined(MBEDTLS_XTEA_C)
+#include "mbedtls/xtea.h"
+#endif
+
+
+// Error code table type
+struct ssl_errs {
+ int16_t errnum;
+ const char *errstr;
+};
+
+// Table of high level error codes
+static const struct ssl_errs mbedtls_high_level_error_tab[] = {
+// BEGIN generated code
+#if defined(MBEDTLS_CIPHER_C)
+ { -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE), "CIPHER_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA), "CIPHER_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED), "CIPHER_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_CIPHER_INVALID_PADDING), "CIPHER_INVALID_PADDING" },
+ { -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED), "CIPHER_FULL_BLOCK_EXPECTED" },
+ { -(MBEDTLS_ERR_CIPHER_AUTH_FAILED), "CIPHER_AUTH_FAILED" },
+ { -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT), "CIPHER_INVALID_CONTEXT" },
+ { -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED), "CIPHER_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CIPHER_C */
+
+#if defined(MBEDTLS_DHM_C)
+ { -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA), "DHM_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED), "DHM_READ_PARAMS_FAILED" },
+ { -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED), "DHM_MAKE_PARAMS_FAILED" },
+ { -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED), "DHM_READ_PUBLIC_FAILED" },
+ { -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED), "DHM_MAKE_PUBLIC_FAILED" },
+ { -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED), "DHM_CALC_SECRET_FAILED" },
+ { -(MBEDTLS_ERR_DHM_INVALID_FORMAT), "DHM_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_DHM_ALLOC_FAILED), "DHM_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_DHM_FILE_IO_ERROR), "DHM_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED), "DHM_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED), "DHM_SET_GROUP_FAILED" },
+#endif /* MBEDTLS_DHM_C */
+
+#if defined(MBEDTLS_ECP_C)
+ { -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA), "ECP_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL), "ECP_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE), "ECP_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_ECP_VERIFY_FAILED), "ECP_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_ECP_ALLOC_FAILED), "ECP_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_ECP_RANDOM_FAILED), "ECP_RANDOM_FAILED" },
+ { -(MBEDTLS_ERR_ECP_INVALID_KEY), "ECP_INVALID_KEY" },
+ { -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH), "ECP_SIG_LEN_MISMATCH" },
+ { -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED), "ECP_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_ECP_IN_PROGRESS), "ECP_IN_PROGRESS" },
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_MD_C)
+ { -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE), "MD_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_MD_BAD_INPUT_DATA), "MD_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_MD_ALLOC_FAILED), "MD_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_MD_FILE_IO_ERROR), "MD_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED), "MD_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD_C */
+
+#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
+ { -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT), "PEM_NO_HEADER_FOOTER_PRESENT" },
+ { -(MBEDTLS_ERR_PEM_INVALID_DATA), "PEM_INVALID_DATA" },
+ { -(MBEDTLS_ERR_PEM_ALLOC_FAILED), "PEM_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_PEM_INVALID_ENC_IV), "PEM_INVALID_ENC_IV" },
+ { -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG), "PEM_UNKNOWN_ENC_ALG" },
+ { -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED), "PEM_PASSWORD_REQUIRED" },
+ { -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH), "PEM_PASSWORD_MISMATCH" },
+ { -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE), "PEM_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA), "PEM_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
+
+#if defined(MBEDTLS_PK_C)
+ { -(MBEDTLS_ERR_PK_ALLOC_FAILED), "PK_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_PK_TYPE_MISMATCH), "PK_TYPE_MISMATCH" },
+ { -(MBEDTLS_ERR_PK_BAD_INPUT_DATA), "PK_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_PK_FILE_IO_ERROR), "PK_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION), "PK_KEY_INVALID_VERSION" },
+ { -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT), "PK_KEY_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG), "PK_UNKNOWN_PK_ALG" },
+ { -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED), "PK_PASSWORD_REQUIRED" },
+ { -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH), "PK_PASSWORD_MISMATCH" },
+ { -(MBEDTLS_ERR_PK_INVALID_PUBKEY), "PK_INVALID_PUBKEY" },
+ { -(MBEDTLS_ERR_PK_INVALID_ALG), "PK_INVALID_ALG" },
+ { -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE), "PK_UNKNOWN_NAMED_CURVE" },
+ { -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE), "PK_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH), "PK_SIG_LEN_MISMATCH" },
+ { -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED), "PK_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_PK_C */
+
+#if defined(MBEDTLS_PKCS12_C)
+ { -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA), "PKCS12_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE), "PKCS12_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT), "PKCS12_PBE_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH), "PKCS12_PASSWORD_MISMATCH" },
+#endif /* MBEDTLS_PKCS12_C */
+
+#if defined(MBEDTLS_PKCS5_C)
+ { -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA), "PKCS5_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT), "PKCS5_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE), "PKCS5_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH), "PKCS5_PASSWORD_MISMATCH" },
+#endif /* MBEDTLS_PKCS5_C */
+
+#if defined(MBEDTLS_RSA_C)
+ { -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA), "RSA_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_RSA_INVALID_PADDING), "RSA_INVALID_PADDING" },
+ { -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED), "RSA_KEY_GEN_FAILED" },
+ { -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED), "RSA_KEY_CHECK_FAILED" },
+ { -(MBEDTLS_ERR_RSA_PUBLIC_FAILED), "RSA_PUBLIC_FAILED" },
+ { -(MBEDTLS_ERR_RSA_PRIVATE_FAILED), "RSA_PRIVATE_FAILED" },
+ { -(MBEDTLS_ERR_RSA_VERIFY_FAILED), "RSA_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE), "RSA_OUTPUT_TOO_LARGE" },
+ { -(MBEDTLS_ERR_RSA_RNG_FAILED), "RSA_RNG_FAILED" },
+ { -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION), "RSA_UNSUPPORTED_OPERATION" },
+ { -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED), "RSA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_SSL_TLS_C)
+ { -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE), "SSL_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA), "SSL_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_SSL_INVALID_MAC), "SSL_INVALID_MAC" },
+ { -(MBEDTLS_ERR_SSL_INVALID_RECORD), "SSL_INVALID_RECORD" },
+ { -(MBEDTLS_ERR_SSL_CONN_EOF), "SSL_CONN_EOF" },
+ { -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER), "SSL_UNKNOWN_CIPHER" },
+ { -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN), "SSL_NO_CIPHER_CHOSEN" },
+ { -(MBEDTLS_ERR_SSL_NO_RNG), "SSL_NO_RNG" },
+ { -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE), "SSL_NO_CLIENT_CERTIFICATE" },
+ { -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE), "SSL_CERTIFICATE_TOO_LARGE" },
+ { -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED), "SSL_CERTIFICATE_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED), "SSL_PRIVATE_KEY_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED), "SSL_CA_CHAIN_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE), "SSL_UNEXPECTED_MESSAGE" },
+ { -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED), "SSL_PEER_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY), "SSL_PEER_CLOSE_NOTIFY" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO), "SSL_BAD_HS_CLIENT_HELLO" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO), "SSL_BAD_HS_SERVER_HELLO" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE), "SSL_BAD_HS_CERTIFICATE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST), "SSL_BAD_HS_CERTIFICATE_REQUEST" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE), "SSL_BAD_HS_SERVER_KEY_EXCHANGE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE), "SSL_BAD_HS_SERVER_HELLO_DONE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY), "SSL_BAD_HS_CERTIFICATE_VERIFY" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC), "SSL_BAD_HS_CHANGE_CIPHER_SPEC" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED), "SSL_BAD_HS_FINISHED" },
+ { -(MBEDTLS_ERR_SSL_ALLOC_FAILED), "SSL_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED), "SSL_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH), "SSL_HW_ACCEL_FALLTHROUGH" },
+ { -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED), "SSL_COMPRESSION_FAILED" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION), "SSL_BAD_HS_PROTOCOL_VERSION" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET), "SSL_BAD_HS_NEW_SESSION_TICKET" },
+ { -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED), "SSL_SESSION_TICKET_EXPIRED" },
+ { -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH), "SSL_PK_TYPE_MISMATCH" },
+ { -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY), "SSL_UNKNOWN_IDENTITY" },
+ { -(MBEDTLS_ERR_SSL_INTERNAL_ERROR), "SSL_INTERNAL_ERROR" },
+ { -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING), "SSL_COUNTER_WRAPPING" },
+ { -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO), "SSL_WAITING_SERVER_HELLO_RENEGO" },
+ { -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED), "SSL_HELLO_VERIFY_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL), "SSL_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE), "SSL_NO_USABLE_CIPHERSUITE" },
+ { -(MBEDTLS_ERR_SSL_WANT_READ), "SSL_WANT_READ" },
+ { -(MBEDTLS_ERR_SSL_WANT_WRITE), "SSL_WANT_WRITE" },
+ { -(MBEDTLS_ERR_SSL_TIMEOUT), "SSL_TIMEOUT" },
+ { -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT), "SSL_CLIENT_RECONNECT" },
+ { -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD), "SSL_UNEXPECTED_RECORD" },
+ { -(MBEDTLS_ERR_SSL_NON_FATAL), "SSL_NON_FATAL" },
+ { -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH), "SSL_INVALID_VERIFY_HASH" },
+ { -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING), "SSL_CONTINUE_PROCESSING" },
+ { -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS), "SSL_ASYNC_IN_PROGRESS" },
+ { -(MBEDTLS_ERR_SSL_EARLY_MESSAGE), "SSL_EARLY_MESSAGE" },
+ { -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS), "SSL_CRYPTO_IN_PROGRESS" },
+ { -(MBEDTLS_ERR_SSL_BAD_CONFIG), "SSL_BAD_CONFIG" },
+#endif /* MBEDTLS_SSL_TLS_C */
+
+#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
+ { -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE), "X509_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_X509_UNKNOWN_OID), "X509_UNKNOWN_OID" },
+ { -(MBEDTLS_ERR_X509_INVALID_FORMAT), "X509_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_X509_INVALID_VERSION), "X509_INVALID_VERSION" },
+ { -(MBEDTLS_ERR_X509_INVALID_SERIAL), "X509_INVALID_SERIAL" },
+ { -(MBEDTLS_ERR_X509_INVALID_ALG), "X509_INVALID_ALG" },
+ { -(MBEDTLS_ERR_X509_INVALID_NAME), "X509_INVALID_NAME" },
+ { -(MBEDTLS_ERR_X509_INVALID_DATE), "X509_INVALID_DATE" },
+ { -(MBEDTLS_ERR_X509_INVALID_SIGNATURE), "X509_INVALID_SIGNATURE" },
+ { -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS), "X509_INVALID_EXTENSIONS" },
+ { -(MBEDTLS_ERR_X509_UNKNOWN_VERSION), "X509_UNKNOWN_VERSION" },
+ { -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG), "X509_UNKNOWN_SIG_ALG" },
+ { -(MBEDTLS_ERR_X509_SIG_MISMATCH), "X509_SIG_MISMATCH" },
+ { -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED), "X509_CERT_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT), "X509_CERT_UNKNOWN_FORMAT" },
+ { -(MBEDTLS_ERR_X509_BAD_INPUT_DATA), "X509_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_X509_ALLOC_FAILED), "X509_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_X509_FILE_IO_ERROR), "X509_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL), "X509_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_X509_FATAL_ERROR), "X509_FATAL_ERROR" },
+#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
+// END generated code
+};
+
+static const struct ssl_errs mbedtls_low_level_error_tab[] = {
+// Low level error codes
+//
+// BEGIN generated code
+#if defined(MBEDTLS_AES_C)
+ { -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH), "AES_INVALID_KEY_LENGTH" },
+ { -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH), "AES_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_AES_BAD_INPUT_DATA), "AES_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE), "AES_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED), "AES_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_ARC4_C)
+ { -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED), "ARC4_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_ARC4_C */
+
+#if defined(MBEDTLS_ARIA_C)
+ { -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA), "ARIA_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH), "ARIA_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE), "ARIA_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED), "ARIA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_ARIA_C */
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+ { -(MBEDTLS_ERR_ASN1_OUT_OF_DATA), "ASN1_OUT_OF_DATA" },
+ { -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG), "ASN1_UNEXPECTED_TAG" },
+ { -(MBEDTLS_ERR_ASN1_INVALID_LENGTH), "ASN1_INVALID_LENGTH" },
+ { -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH), "ASN1_LENGTH_MISMATCH" },
+ { -(MBEDTLS_ERR_ASN1_INVALID_DATA), "ASN1_INVALID_DATA" },
+ { -(MBEDTLS_ERR_ASN1_ALLOC_FAILED), "ASN1_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL), "ASN1_BUF_TOO_SMALL" },
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
+#if defined(MBEDTLS_BASE64_C)
+ { -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL), "BASE64_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER), "BASE64_INVALID_CHARACTER" },
+#endif /* MBEDTLS_BASE64_C */
+
+#if defined(MBEDTLS_BIGNUM_C)
+ { -(MBEDTLS_ERR_MPI_FILE_IO_ERROR), "MPI_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA), "MPI_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_MPI_INVALID_CHARACTER), "MPI_INVALID_CHARACTER" },
+ { -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL), "MPI_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE), "MPI_NEGATIVE_VALUE" },
+ { -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO), "MPI_DIVISION_BY_ZERO" },
+ { -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE), "MPI_NOT_ACCEPTABLE" },
+ { -(MBEDTLS_ERR_MPI_ALLOC_FAILED), "MPI_ALLOC_FAILED" },
+#endif /* MBEDTLS_BIGNUM_C */
+
+#if defined(MBEDTLS_BLOWFISH_C)
+ { -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA), "BLOWFISH_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH), "BLOWFISH_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED), "BLOWFISH_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_BLOWFISH_C */
+
+#if defined(MBEDTLS_CAMELLIA_C)
+ { -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA), "CAMELLIA_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH), "CAMELLIA_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED), "CAMELLIA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CAMELLIA_C */
+
+#if defined(MBEDTLS_CCM_C)
+ { -(MBEDTLS_ERR_CCM_BAD_INPUT), "CCM_BAD_INPUT" },
+ { -(MBEDTLS_ERR_CCM_AUTH_FAILED), "CCM_AUTH_FAILED" },
+ { -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED), "CCM_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CCM_C */
+
+#if defined(MBEDTLS_CHACHA20_C)
+ { -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA), "CHACHA20_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE), "CHACHA20_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED), "CHACHA20_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CHACHA20_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ { -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE), "CHACHAPOLY_BAD_STATE" },
+ { -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED), "CHACHAPOLY_AUTH_FAILED" },
+#endif /* MBEDTLS_CHACHAPOLY_C */
+
+#if defined(MBEDTLS_CMAC_C)
+ { -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED), "CMAC_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CMAC_C */
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+ { -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED), "CTR_DRBG_ENTROPY_SOURCE_FAILED" },
+ { -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG), "CTR_DRBG_REQUEST_TOO_BIG" },
+ { -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG), "CTR_DRBG_INPUT_TOO_BIG" },
+ { -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR), "CTR_DRBG_FILE_IO_ERROR" },
+#endif /* MBEDTLS_CTR_DRBG_C */
+
+#if defined(MBEDTLS_DES_C)
+ { -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH), "DES_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED), "DES_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_ENTROPY_C)
+ { -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED), "ENTROPY_SOURCE_FAILED" },
+ { -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES), "ENTROPY_MAX_SOURCES" },
+ { -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED), "ENTROPY_NO_SOURCES_DEFINED" },
+ { -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE), "ENTROPY_NO_STRONG_SOURCE" },
+ { -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR), "ENTROPY_FILE_IO_ERROR" },
+#endif /* MBEDTLS_ENTROPY_C */
+
+#if defined(MBEDTLS_GCM_C)
+ { -(MBEDTLS_ERR_GCM_AUTH_FAILED), "GCM_AUTH_FAILED" },
+ { -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED), "GCM_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_GCM_BAD_INPUT), "GCM_BAD_INPUT" },
+#endif /* MBEDTLS_GCM_C */
+
+#if defined(MBEDTLS_HKDF_C)
+ { -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA), "HKDF_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_HKDF_C */
+
+#if defined(MBEDTLS_HMAC_DRBG_C)
+ { -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG), "HMAC_DRBG_REQUEST_TOO_BIG" },
+ { -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG), "HMAC_DRBG_INPUT_TOO_BIG" },
+ { -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR), "HMAC_DRBG_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED), "HMAC_DRBG_ENTROPY_SOURCE_FAILED" },
+#endif /* MBEDTLS_HMAC_DRBG_C */
+
+#if defined(MBEDTLS_MD2_C)
+ { -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED), "MD2_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD2_C */
+
+#if defined(MBEDTLS_MD4_C)
+ { -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED), "MD4_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD4_C */
+
+#if defined(MBEDTLS_MD5_C)
+ { -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED), "MD5_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD5_C */
+
+#if defined(MBEDTLS_NET_C)
+ { -(MBEDTLS_ERR_NET_SOCKET_FAILED), "NET_SOCKET_FAILED" },
+ { -(MBEDTLS_ERR_NET_CONNECT_FAILED), "NET_CONNECT_FAILED" },
+ { -(MBEDTLS_ERR_NET_BIND_FAILED), "NET_BIND_FAILED" },
+ { -(MBEDTLS_ERR_NET_LISTEN_FAILED), "NET_LISTEN_FAILED" },
+ { -(MBEDTLS_ERR_NET_ACCEPT_FAILED), "NET_ACCEPT_FAILED" },
+ { -(MBEDTLS_ERR_NET_RECV_FAILED), "NET_RECV_FAILED" },
+ { -(MBEDTLS_ERR_NET_SEND_FAILED), "NET_SEND_FAILED" },
+ { -(MBEDTLS_ERR_NET_CONN_RESET), "NET_CONN_RESET" },
+ { -(MBEDTLS_ERR_NET_UNKNOWN_HOST), "NET_UNKNOWN_HOST" },
+ { -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL), "NET_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_NET_INVALID_CONTEXT), "NET_INVALID_CONTEXT" },
+ { -(MBEDTLS_ERR_NET_POLL_FAILED), "NET_POLL_FAILED" },
+ { -(MBEDTLS_ERR_NET_BAD_INPUT_DATA), "NET_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_NET_C */
+
+#if defined(MBEDTLS_OID_C)
+ { -(MBEDTLS_ERR_OID_NOT_FOUND), "OID_NOT_FOUND" },
+ { -(MBEDTLS_ERR_OID_BUF_TOO_SMALL), "OID_BUF_TOO_SMALL" },
+#endif /* MBEDTLS_OID_C */
+
+#if defined(MBEDTLS_PADLOCK_C)
+ { -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED), "PADLOCK_DATA_MISALIGNED" },
+#endif /* MBEDTLS_PADLOCK_C */
+
+#if defined(MBEDTLS_PLATFORM_C)
+ { -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED), "PLATFORM_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED), "PLATFORM_FEATURE_UNSUPPORTED" },
+#endif /* MBEDTLS_PLATFORM_C */
+
+#if defined(MBEDTLS_POLY1305_C)
+ { -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA), "POLY1305_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE), "POLY1305_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED), "POLY1305_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_POLY1305_C */
+
+#if defined(MBEDTLS_RIPEMD160_C)
+ { -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED), "RIPEMD160_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_RIPEMD160_C */
+
+#if defined(MBEDTLS_SHA1_C)
+ { -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED), "SHA1_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA), "SHA1_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_SHA1_C */
+
+#if defined(MBEDTLS_SHA256_C)
+ { -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED), "SHA256_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA), "SHA256_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_SHA256_C */
+
+#if defined(MBEDTLS_SHA512_C)
+ { -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED), "SHA512_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA), "SHA512_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_SHA512_C */
+
+#if defined(MBEDTLS_THREADING_C)
+ { -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE), "THREADING_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA), "THREADING_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_THREADING_MUTEX_ERROR), "THREADING_MUTEX_ERROR" },
+#endif /* MBEDTLS_THREADING_C */
+
+#if defined(MBEDTLS_XTEA_C)
+ { -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH), "XTEA_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED), "XTEA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_XTEA_C */
+// END generated code
+};
+
+static const char *mbedtls_err_prefix = "MBEDTLS_ERR_";
+#define MBEDTLS_ERR_PREFIX_LEN ( sizeof("MBEDTLS_ERR_")-1 )
+
+// copy error text into buffer, ensure null termination, return strlen of result
+static size_t mbedtls_err_to_str(int err, const struct ssl_errs tab[], int tab_len, char *buf, size_t buflen) {
+ if (buflen == 0) return 0;
+
+ // prefix for all error names
+ strncpy(buf, mbedtls_err_prefix, buflen);
+ if (buflen <= MBEDTLS_ERR_PREFIX_LEN+1) {
+ buf[buflen-1] = 0;
+ return buflen-1;
+ }
+
+ // append error name from table
+ for (int i = 0; i < tab_len; i++) {
+ if (tab[i].errnum == err) {
+ strncpy(buf+MBEDTLS_ERR_PREFIX_LEN, tab[i].errstr, buflen-MBEDTLS_ERR_PREFIX_LEN);
+ buf[buflen-1] = 0;
+ return strlen(buf);
+ }
+ }
+
+ mbedtls_snprintf(buf+MBEDTLS_ERR_PREFIX_LEN, buflen-MBEDTLS_ERR_PREFIX_LEN, "UNKNOWN (0x%04X)",
+ err);
+ return strlen(buf);
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+void mbedtls_strerror(int ret, char *buf, size_t buflen) {
+ int use_ret;
+
+ if (buflen == 0) return;
+
+ buf[buflen-1] = 0;
+
+ if (ret < 0) ret = -ret;
+
+ //
+ // High-level error codes
+ //
+ uint8_t got_hl = (ret & 0xFF80) != 0;
+ if (got_hl) {
+ use_ret = ret & 0xFF80;
+
+ // special case
+#if defined(MBEDTLS_SSL_TLS_C)
+ if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
+ strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
+ buf[buflen-1] = 0;
+ return;
+ }
+#endif
+
+ size_t len = mbedtls_err_to_str(use_ret, mbedtls_high_level_error_tab,
+ ARRAY_SIZE(mbedtls_high_level_error_tab), buf, buflen);
+
+ buf += len;
+ buflen -= len;
+ if (buflen == 0) return;
+ }
+
+ //
+ // Low-level error codes
+ //
+ use_ret = ret & ~0xFF80;
+
+ if (use_ret == 0) return;
+
+ // If high level code is present, make a concatenation between both error strings.
+ if (got_hl) {
+ if (buflen < 2) return;
+ *buf++ = '+';
+ buflen--;
+ }
+
+ mbedtls_err_to_str(use_ret, mbedtls_low_level_error_tab,
+ ARRAY_SIZE(mbedtls_low_level_error_tab), buf, buflen);
+}
+
+#else /* MBEDTLS_ERROR_C */
+
+#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+
+/*
+ * Provide an non-function in case MBEDTLS_ERROR_C is not defined
+ */
+void mbedtls_strerror( int ret, char *buf, size_t buflen )
+{
+ ((void) ret);
+
+ if( buflen > 0 )
+ buf[0] = '\0';
+}
+
+#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
+
+#endif /* MBEDTLS_ERROR_C */
diff --git a/lib/mbedtls_errors/generate_errors.diff b/lib/mbedtls_errors/generate_errors.diff
index ad24c372faed7..bea47cd66fbac 100644
--- a/lib/mbedtls_errors/generate_errors.diff
+++ b/lib/mbedtls_errors/generate_errors.diff
@@ -1,22 +1,29 @@
---- generate_errors_orig.pl 2020-06-20 08:40:38.819060379 -0700
-+++ generate_errors.pl 2020-06-20 08:47:26.511163591 -0700
-@@ -162,16 +162,12 @@
-
- if ($error_name eq "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE")
+--- generate_errors_orig.pl 2023-04-30 17:58:23.503070758 +1000
++++ generate_errors.py 2023-04-30 17:58:20.826338349 +1000
+@@ -162,7 +162,7 @@
{
-- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
-- "${white_space}\{\n".
-- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n".
-- "${white_space} return;\n".
-- "${white_space}}\n"
-+ # no-op, this case is hard-coded in error.fmt
+ $code_check = \$ll_code_check;
+ $old_define = \$ll_old_define;
+- $white_space = ' ';
++ $white_space = ' ';
}
else
{
-- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
-- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n"
-+ my $error_text = $error_name =~ s/^MBEDTLS_ERR_//r;
-+ ${$code_check} .= "${white_space}{ -($error_name), \"$error_text\" },\n"
+@@ -203,8 +203,15 @@
+ ${$old_define} = $define_name;
}
+
+- ${$code_check} .= "${white_space}case -($error_name):\n".
+- "${white_space} return( \"$module_name - $description\" );\n"
++ if ($error_name eq "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE")
++ {
++ # no-op, this case is hard-coded in error.fmt
++ }
++ else
++ {
++ my $error_text = $error_name =~ s/^MBEDTLS_ERR_//r;
++ ${$code_check} .= "${white_space}{ -($error_name), \"$error_text\" },\n"
++ }
};
+ if ($ll_old_define ne "")
diff --git a/lib/mbedtls_errors/mp_mbedtls_errors.c b/lib/mbedtls_errors/mp_mbedtls_errors.c
index 03a91f0dc9495..fabbb15e4eb6f 100644
--- a/lib/mbedtls_errors/mp_mbedtls_errors.c
+++ b/lib/mbedtls_errors/mp_mbedtls_errors.c
@@ -53,6 +53,10 @@
#include "mbedtls/aria.h"
#endif
+#if defined(MBEDTLS_ASN1_PARSE_C)
+#include "mbedtls/asn1.h"
+#endif
+
#if defined(MBEDTLS_BASE64_C)
#include "mbedtls/base64.h"
#endif
@@ -109,6 +113,10 @@
#include "mbedtls/entropy.h"
#endif
+#if defined(MBEDTLS_ERROR_C)
+#include "mbedtls/error.h"
+#endif
+
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@@ -377,7 +385,10 @@ static const struct ssl_errs mbedtls_high_level_error_tab[] = {
{ -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING), "SSL_CONTINUE_PROCESSING" },
{ -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS), "SSL_ASYNC_IN_PROGRESS" },
{ -(MBEDTLS_ERR_SSL_EARLY_MESSAGE), "SSL_EARLY_MESSAGE" },
+ { -(MBEDTLS_ERR_SSL_UNEXPECTED_CID), "SSL_UNEXPECTED_CID" },
+ { -(MBEDTLS_ERR_SSL_VERSION_MISMATCH), "SSL_VERSION_MISMATCH" },
{ -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS), "SSL_CRYPTO_IN_PROGRESS" },
+ { -(MBEDTLS_ERR_SSL_BAD_CONFIG), "SSL_BAD_CONFIG" },
#endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
@@ -507,6 +518,11 @@ static const struct ssl_errs mbedtls_low_level_error_tab[] = {
{ -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR), "ENTROPY_FILE_IO_ERROR" },
#endif /* MBEDTLS_ENTROPY_C */
+#if defined(MBEDTLS_ERROR_C)
+ { -(MBEDTLS_ERR_ERROR_GENERIC_ERROR), "ERROR_GENERIC_ERROR" },
+ { -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED), "ERROR_CORRUPTION_DETECTED" },
+#endif /* MBEDTLS_ERROR_C */
+
#if defined(MBEDTLS_GCM_C)
{ -(MBEDTLS_ERR_GCM_AUTH_FAILED), "GCM_AUTH_FAILED" },
{ -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED), "GCM_HW_ACCEL_FAILED" },
@@ -650,7 +666,7 @@ void mbedtls_strerror(int ret, char *buf, size_t buflen) {
if (got_hl) {
use_ret = ret & 0xFF80;
- // special case
+ // special case, don't try to translate low level code
#if defined(MBEDTLS_SSL_TLS_C)
if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
diff --git a/lib/micropython-lib b/lib/micropython-lib
new file mode 160000
index 0000000000000..c113611765278
--- /dev/null
+++ b/lib/micropython-lib
@@ -0,0 +1 @@
+Subproject commit c113611765278b2fc8dcf8b2f2c3513b35a69b39
diff --git a/lib/oofatfs/ff.c b/lib/oofatfs/ff.c
index 0c9d04fe746fe..eca5b45bda11e 100644
--- a/lib/oofatfs/ff.c
+++ b/lib/oofatfs/ff.c
@@ -2821,7 +2821,7 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not
if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */
lfn[di++] = wc; /* Store the Unicode character */
}
- while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */
+ if (wc == '/' || wc == '\\') while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */
*path = p; /* Return pointer to the next segment */
cf = (wc < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */
diff --git a/lib/pico-sdk b/lib/pico-sdk
index 2062372d203b3..6a7db34ff6334 160000
--- a/lib/pico-sdk
+++ b/lib/pico-sdk
@@ -1 +1 @@
-Subproject commit 2062372d203b372849d573f252cf7c6dc2800c0a
+Subproject commit 6a7db34ff63345a7badec79ebea3aaef1712f374
diff --git a/lib/re1.5/charclass.c b/lib/re1.5/charclass.c
index 7f6388c93d299..2553b40530c90 100644
--- a/lib/re1.5/charclass.c
+++ b/lib/re1.5/charclass.c
@@ -6,7 +6,15 @@ int _re1_5_classmatch(const char *pc, const char *sp)
int is_positive = (pc[-1] == Class);
int cnt = *pc++;
while (cnt--) {
- if (*sp >= *pc && *sp <= pc[1]) return is_positive;
+ if (*pc == RE15_CLASS_NAMED_CLASS_INDICATOR) {
+ if (_re1_5_namedclassmatch(pc + 1, sp)) {
+ return is_positive;
+ }
+ } else {
+ if (*sp >= *pc && *sp <= pc[1]) {
+ return is_positive;
+ }
+ }
pc += 2;
}
return !is_positive;
diff --git a/lib/re1.5/compilecode.c b/lib/re1.5/compilecode.c
index add4f6ac20859..513a155970ac5 100644
--- a/lib/re1.5/compilecode.c
+++ b/lib/re1.5/compilecode.c
@@ -4,6 +4,9 @@
#include "re1.5.h"
+// Matches: DSWdsw
+#define MATCH_NAMED_CLASS_CHAR(c) (((c) | 0x20) == 'd' || ((c) | 0x24) == 'w')
+
#define INSERT_CODE(at, num, pc) \
((code ? memmove(code + at + num, code + at, pc - at) : 0), pc += num)
#define REL(at, to) (to - at - 2)
@@ -31,7 +34,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
case '\\':
re++;
if (!*re) return NULL; // Trailing backslash
- if ((*re | 0x20) == 'd' || (*re | 0x20) == 's' || (*re | 0x20) == 'w') {
+ if (MATCH_NAMED_CLASS_CHAR(*re)) {
term = PC;
EMIT(PC++, NamedClass);
EMIT(PC++, *re);
@@ -63,14 +66,21 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
PC++; // Skip # of pair byte
prog->len++;
for (cnt = 0; *re != ']'; re++, cnt++) {
- if (*re == '\\') {
+ char c = *re;
+ if (c == '\\') {
++re;
+ c = *re;
+ if (MATCH_NAMED_CLASS_CHAR(c)) {
+ c = RE15_CLASS_NAMED_CLASS_INDICATOR;
+ goto emit_char_pair;
+ }
}
- if (!*re) return NULL;
- EMIT(PC++, *re);
+ if (!c) return NULL;
if (re[1] == '-' && re[2] != ']') {
re += 2;
}
+ emit_char_pair:
+ EMIT(PC++, c);
EMIT(PC++, *re);
}
EMIT_CHECKED(term + 1, cnt);
diff --git a/lib/re1.5/re1.5.h b/lib/re1.5/re1.5.h
index 81f43ed7f5fda..b1ec01cbc5860 100644
--- a/lib/re1.5/re1.5.h
+++ b/lib/re1.5/re1.5.h
@@ -138,6 +138,7 @@ struct Subject {
#define NON_ANCHORED_PREFIX 5
#define HANDLE_ANCHORED(bytecode, is_anchored) ((is_anchored) ? (bytecode) + NON_ANCHORED_PREFIX : (bytecode))
+#define RE15_CLASS_NAMED_CLASS_INDICATOR 0
int re1_5_backtrack(ByteProg*, Subject*, const char**, int, int);
int re1_5_pikevm(ByteProg*, Subject*, const char**, int, int);
diff --git a/lib/stm32lib b/lib/stm32lib
index eb80f0126e506..928df866e4d28 160000
--- a/lib/stm32lib
+++ b/lib/stm32lib
@@ -1 +1 @@
-Subproject commit eb80f0126e50687aac966f4c39a2b5a5deffbe78
+Subproject commit 928df866e4d287ebc3c60726151513ebee609128
diff --git a/lib/tinyusb b/lib/tinyusb
index 4bfab30c02279..868f2bcda092b 160000
--- a/lib/tinyusb
+++ b/lib/tinyusb
@@ -1 +1 @@
-Subproject commit 4bfab30c02279a0530e1a56f4a7c539f2d35a293
+Subproject commit 868f2bcda092b0b8d5f7ac55ffaef2c81316d35e
diff --git a/mpy-cross/.gitignore b/mpy-cross/.gitignore
deleted file mode 100644
index 82a0a7efaab3d..0000000000000
--- a/mpy-cross/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-mpy-cross
diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile
index 2189dff9058ea..7a71577e2bb1a 100644
--- a/mpy-cross/Makefile
+++ b/mpy-cross/Makefile
@@ -19,7 +19,7 @@ INC += -I$(TOP)
# compiler settings
CWARN = -Wall -Werror
CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith
-CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
+CFLAGS += $(INC) $(CWARN) -std=gnu99 $(COPT) $(CFLAGS_EXTRA)
CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables
# Debugging/Optimization
@@ -42,7 +42,7 @@ else
# Use gcc syntax for map file
LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections
endif
-LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
+LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
# source files
SRC_C = \
diff --git a/mpy-cross/main.c b/mpy-cross/main.c
index f3ffff61fdf80..8a4dd5bcbed57 100644
--- a/mpy-cross/main.c
+++ b/mpy-cross/main.c
@@ -73,8 +73,9 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha
#endif
mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT);
- mp_module_context_t *ctx = m_new_obj(mp_module_context_t);
- mp_compiled_module_t cm = mp_compile_to_raw_code(&parse_tree, source_name, false, ctx);
+ mp_compiled_module_t cm;
+ cm.context = m_new_obj(mp_module_context_t);
+ mp_compile_to_raw_code(&parse_tree, source_name, false, &cm);
vstr_t vstr;
vstr_init(&vstr, 16);
@@ -181,6 +182,15 @@ STATIC void pre_process_options(int argc, char **argv) {
}
}
+STATIC char *backslash_to_forwardslash(char *path) {
+ for (char *p = path; p != NULL && *p != '\0'; ++p) {
+ if (*p == '\\') {
+ *p = '/';
+ }
+ }
+ return path;
+}
+
MP_NOINLINE int main_(int argc, char **argv) {
mp_stack_set_limit(40000 * (sizeof(void *) / 4));
@@ -203,19 +213,9 @@ MP_NOINLINE int main_(int argc, char **argv) {
// set default compiler configuration
mp_dynamic_compiler.small_int_bits = 31;
- #if defined(__i386__)
- mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86;
- mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86;
- #elif defined(__x86_64__)
- mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64;
- mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN);
- #elif defined(__arm__) && !defined(__thumb2__)
- mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6;
- mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
- #else
+ // don't support native emitter unless -march is specified
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE;
mp_dynamic_compiler.nlr_buf_num_regs = 0;
- #endif
const char *input_file = NULL;
const char *output_file = NULL;
@@ -228,7 +228,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
a += 1;
} else if (strcmp(argv[a], "--version") == 0) {
printf("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE
- "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "\n");
+ "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "." MP_STRINGIFY(MPY_SUB_VERSION) "\n");
return 0;
} else if (strcmp(argv[a], "-v") == 0) {
mp_verbose_flag++;
@@ -251,7 +251,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
exit(usage(argv));
}
a += 1;
- source_file = argv[a];
+ source_file = backslash_to_forwardslash(argv[a]);
} else if (strncmp(argv[a], "-msmall-int-bits=", sizeof("-msmall-int-bits=") - 1) == 0) {
char *end;
mp_dynamic_compiler.small_int_bits =
@@ -292,6 +292,20 @@ MP_NOINLINE int main_(int argc, char **argv) {
} else if (strcmp(arch, "xtensawin") == 0) {
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSAWIN;
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSAWIN;
+ } else if (strcmp(arch, "host") == 0) {
+ #if defined(__i386__) || defined(_M_IX86)
+ mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86;
+ mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86;
+ #elif defined(__x86_64__) || defined(_M_X64)
+ mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64;
+ mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN);
+ #elif defined(__arm__) && !defined(__thumb2__)
+ mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6;
+ mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
+ #else
+ mp_printf(&mp_stderr_print, "unable to determine host architecture for -march=host\n");
+ exit(1);
+ #endif
} else {
return usage(argv);
}
@@ -303,7 +317,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
mp_printf(&mp_stderr_print, "multiple input files\n");
exit(1);
}
- input_file = argv[a];
+ input_file = backslash_to_forwardslash(argv[a]);
}
}
@@ -330,7 +344,7 @@ int main(int argc, char **argv) {
return main_(argc, argv);
}
-uint mp_import_stat(const char *path) {
+mp_import_stat_t mp_import_stat(const char *path) {
(void)path;
return MP_IMPORT_STAT_NO_EXIST;
}
diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h
index 95922d04ff7b5..4304c552bc45b 100644
--- a/mpy-cross/mpconfigport.h
+++ b/mpy-cross/mpconfigport.h
@@ -119,7 +119,7 @@ typedef long mp_off_t;
#define MP_PLAT_PRINT_STRN(str, len) (void)0
// We need to provide a declaration/definition of alloca()
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__NetBSD__)
#include
#elif defined(_WIN32)
#include
@@ -135,6 +135,7 @@ typedef long mp_off_t;
#define MP_ENDIANNESS_LITTLE (1)
#define NORETURN __declspec(noreturn)
#define MP_NOINLINE __declspec(noinline)
+#define MP_ALWAYSINLINE __forceinline
#define MP_LIKELY(x) (x)
#define MP_UNLIKELY(x) (x)
#define MICROPY_PORT_CONSTANTS { MP_ROM_QSTR(MP_QSTR_dummy), MP_ROM_PTR(NULL) }
diff --git a/mpy-cross/mpy-cross.vcxproj b/mpy-cross/mpy-cross.vcxproj
index 53cb0fa1fec71..322d8c25d109b 100644
--- a/mpy-cross/mpy-cross.vcxproj
+++ b/mpy-cross/mpy-cross.vcxproj
@@ -24,7 +24,6 @@
True$(MSBuildThisFileDirectory)build\$(MSBuildThisFileDirectory)
- $(MSBuildThisFileDirectory)$(MSBuildThisFileDirectory)..\ports\windows\msvc\
diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py
new file mode 100644
index 0000000000000..8eadbc8352c74
--- /dev/null
+++ b/mpy-cross/mpy_cross/__init__.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+#
+# This file is part of the MicroPython project, http://micropython.org/
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2022 Andrew Leech
+# Copyright (c) 2022 Jim Mussared
+#
+# 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.
+
+from __future__ import print_function
+import os
+import re
+import stat
+import subprocess
+
+NATIVE_ARCHS = {
+ "NATIVE_ARCH_NONE": "",
+ "NATIVE_ARCH_X86": "x86",
+ "NATIVE_ARCH_X64": "x64",
+ "NATIVE_ARCH_ARMV6": "armv6",
+ "NATIVE_ARCH_ARMV6M": "armv6m",
+ "NATIVE_ARCH_ARMV7M": "armv7m",
+ "NATIVE_ARCH_ARMV7EM": "armv7em",
+ "NATIVE_ARCH_ARMV7EMSP": "armv7emsp",
+ "NATIVE_ARCH_ARMV7EMDP": "armv7emdp",
+ "NATIVE_ARCH_XTENSA": "xtensa",
+ "NATIVE_ARCH_XTENSAWIN": "xtensawin",
+}
+
+globals().update(NATIVE_ARCHS)
+
+__all__ = ["version", "compile", "run", "CrossCompileError"] + list(NATIVE_ARCHS.keys())
+
+
+class CrossCompileError(Exception):
+ pass
+
+
+_VERSION_RE = re.compile("mpy-cross emitting mpy v([0-9]+)(?:.([0-9]+))?")
+
+
+def _find_mpy_cross_binary(mpy_cross):
+ if mpy_cross:
+ return mpy_cross
+ return os.path.abspath(os.path.join(os.path.dirname(__file__), "../build/mpy-cross"))
+
+
+def mpy_version(mpy_cross=None):
+ """
+ Get the version and sub-version of the .mpy file format generated by this version of mpy-cross.
+
+ Returns: A tuple of `(mpy_version, mpy_sub_version)`
+ Optional keyword arguments:
+ - mpy_cross: Specific mpy-cross binary to use
+ """
+ version_info = run(["--version"], mpy_cross=mpy_cross)
+ match = re.search(_VERSION_RE, version_info)
+ mpy_version, mpy_sub_version = int(match.group(1)), int(match.group(2) or "0")
+ return (
+ mpy_version,
+ mpy_sub_version,
+ )
+
+
+def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, extra_args=None):
+ """
+ Compile the specified .py file with mpy-cross.
+
+ Returns: Standard output from mpy-cross as a string.
+
+ Required arguments:
+ - src: The path to the .py file
+
+ Optional keyword arguments:
+ - dest: The output .mpy file. Defaults to `src` (with .mpy extension)
+ - src_path: The path to embed in the .mpy file (defaults to `src`)
+ - opt: Optimisation level (0-3, default 0)
+ - march: One of the `NATIVE_ARCH_*` constants (defaults to NATIVE_ARCH_NONE)
+ - mpy_cross: Specific mpy-cross binary to use
+ - extra_args: Additional arguments to pass to mpy-cross (e.g. `["-X", "emit=native"]`)
+ """
+ if not src:
+ raise ValueError("src is required")
+ if not os.path.exists(src):
+ raise CrossCompileError("Input .py file not found: {}.".format(src_py))
+
+ args = []
+
+ if src_path:
+ args += ["-s", src_path]
+
+ if dest:
+ args += ["-o", dest]
+
+ if march:
+ args += ["-march=" + march]
+
+ if opt is not None:
+ args += ["-O{}".format(opt)]
+
+ if extra_args:
+ args += extra_args
+
+ args += [src]
+
+ run(args, mpy_cross)
+
+
+def run(args, mpy_cross=None):
+ """
+ Run mpy-cross with the specified command line arguments.
+ Prefer to use `compile()` instead.
+
+ Returns: Standard output from mpy-cross as a string.
+
+ Optional keyword arguments:
+ - mpy_cross: Specific mpy-cross binary to use
+ """
+ mpy_cross = _find_mpy_cross_binary(mpy_cross)
+
+ if not os.path.exists(mpy_cross):
+ raise CrossCompileError("mpy-cross binary not found at {}.".format(mpy_cross))
+
+ try:
+ st = os.stat(mpy_cross)
+ os.chmod(mpy_cross, st.st_mode | stat.S_IEXEC)
+ except OSError:
+ pass
+
+ try:
+ return subprocess.check_output([mpy_cross] + args, stderr=subprocess.STDOUT).decode()
+ except subprocess.CalledProcessError as er:
+ raise CrossCompileError(er.output.decode())
diff --git a/mpy-cross/mpy_cross/__main__.py b/mpy-cross/mpy_cross/__main__.py
new file mode 100644
index 0000000000000..2b6b81c333362
--- /dev/null
+++ b/mpy-cross/mpy_cross/__main__.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+#
+# This file is part of the MicroPython project, http://micropython.org/
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2022 Andrew Leech
+# Copyright (c) 2022 Jim Mussared
+#
+# 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.
+
+from __future__ import print_function
+import argparse
+import sys
+
+from . import run, CrossCompileError
+
+try:
+ print(run(sys.argv[1:]))
+except CrossCompileError as er:
+ print(er.args[0], file=sys.stderr)
+ raise SystemExit(1)
diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile
index 90be4529d87fa..61af0bfd98445 100644
--- a/ports/cc3200/Makefile
+++ b/ports/cc3200/Makefile
@@ -20,12 +20,14 @@ include ../../py/mkenv.mk
CROSS_COMPILE ?= arm-none-eabi-
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion
-CFLAGS = -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
+CFLAGS += -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
CFLAGS += -Iboards/$(BOARD)
-CFLAGS += $(CFLAGS_MOD)
-LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map
+# Workaround gcc 12.1 bug.
+CFLAGS += -Wno-array-bounds
+
+LDFLAGS += -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map
FLASH_SIZE_WIPY = 2M
FLASH_SIZE_LAUNCHXL = 1M
diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk
index 25a9925ea00ea..5021e4ff3cb1a 100644
--- a/ports/cc3200/application.mk
+++ b/ports/cc3200/application.mk
@@ -78,10 +78,9 @@ APP_MISC_SRC_C = $(addprefix misc/,\
APP_MODS_SRC_C = $(addprefix mods/,\
modmachine.c \
modnetwork.c \
- moduos.c \
- modusocket.c \
- modussl.c \
- modutime.c \
+ modos.c \
+ modsocket.c \
+ modssl.c \
modwipy.c \
modwlan.c \
pybadc.c \
@@ -162,11 +161,11 @@ APP_STM_SRC_C = $(addprefix ports/stm32/,\
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_SHARED_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o))
-OBJ += $(BUILD)/shared/runtime/gchelper_m3.o
+OBJ += $(BUILD)/shared/runtime/gchelper_thumb2.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) $(APP_SHARED_SRC_C)
+SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) $(APP_SHARED_SRC_C) $(APP_HAL_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/boards/make-pins.py b/ports/cc3200/boards/make-pins.py
index 0cf0d565606f2..6608be438a218 100644
--- a/ports/cc3200/boards/make-pins.py
+++ b/ports/cc3200/boards/make-pins.py
@@ -124,7 +124,7 @@ def parse_af_file(self, filename, pin_col, pinname_col, af_start_col):
continue
if not row[pin_col].isdigit():
raise ValueError(
- "Invalid pin number {:s} in row {:s}".format(row[pin_col]), row
+ "Invalid pin number {:s} in row {:s}".format(row[pin_col], row)
)
# Pin numbers must start from 0 when used with the TI API
pin_num = int(row[pin_col]) - 1
diff --git a/ports/cc3200/bootmgr/bootloader.mk b/ports/cc3200/bootmgr/bootloader.mk
index e5b817391d2fc..3aeda062ce422 100644
--- a/ports/cc3200/bootmgr/bootloader.mk
+++ b/ports/cc3200/bootmgr/bootloader.mk
@@ -134,3 +134,7 @@ $(HEADER_BUILD)/mpversion.h: | $(HEADER_BUILD)
# Create an empty "moduledefs.h" needed by py/mkrules.mk
$(HEADER_BUILD)/moduledefs.h: | $(HEADER_BUILD)
touch $@
+
+# Create an empty "root_pointers.h" needed by py/mkrules.mk
+$(HEADER_BUILD)/root_pointers.h: | $(HEADER_BUILD)
+ touch $@
diff --git a/ports/cc3200/bootmgr/main.c b/ports/cc3200/bootmgr/main.c
index cfb8dec21d38e..6feeec79a3b8b 100644
--- a/ports/cc3200/bootmgr/main.c
+++ b/ports/cc3200/bootmgr/main.c
@@ -256,7 +256,7 @@ static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force
_u32 count;
for (count = 0; (force_wait || MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) &&
((period * count) < wait_time); count++) {
- // toogle the led
+ // toggle the led
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
UtilsDelay(UTILS_DELAY_US_TO_COUNT(period * 1000));
}
diff --git a/ports/cc3200/fatfs/src/drivers/sd_diskio.c b/ports/cc3200/fatfs/src/drivers/sd_diskio.c
index 0a1379181b45b..329ae04b99104 100644
--- a/ports/cc3200/fatfs/src/drivers/sd_diskio.c
+++ b/ports/cc3200/fatfs/src/drivers/sd_diskio.c
@@ -269,7 +269,7 @@ DSTATUS sd_disk_init (void) {
// Fill in the RCA
sd_disk_info.usRCA = (ulResp[0] >> 16);
- // Get tha card capacity
+ // Get the card capacity
CardCapacityGet(&sd_disk_info);
}
diff --git a/ports/cc3200/ftp/ftp.c b/ports/cc3200/ftp/ftp.c
index d999e810d9e0a..5d4fc6fb5f2d0 100644
--- a/ports/cc3200/ftp/ftp.c
+++ b/ports/cc3200/ftp/ftp.c
@@ -42,13 +42,13 @@
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
-#include "modusocket.h"
+#include "modsocket.h"
#include "debug.h"
#include "serverstask.h"
#include "fifo.h"
#include "socketfifo.h"
#include "updater.h"
-#include "moduos.h"
+#include "modos.h"
/******************************************************************************
DEFINE PRIVATE CONSTANTS
@@ -97,7 +97,7 @@ typedef enum {
typedef struct {
bool uservalid : 1;
bool passvalid : 1;
-} ftp_loggin_t;
+} ftp_login_t;
typedef enum {
E_FTP_NOTHING_OPEN = 0,
@@ -127,8 +127,8 @@ typedef struct {
uint8_t state;
uint8_t substate;
uint8_t txRetries;
- uint8_t logginRetries;
- ftp_loggin_t loggin;
+ uint8_t loginRetries;
+ ftp_login_t login;
uint8_t e_open;
bool closechild;
bool enabled;
@@ -329,10 +329,10 @@ void ftp_run (void) {
if (ftp_data.c_sd < 0 && ftp_data.substate == E_FTP_STE_SUB_DISCONNECTED) {
if (E_FTP_RESULT_OK == ftp_wait_for_connection(ftp_data.lc_sd, &ftp_data.c_sd)) {
ftp_data.txRetries = 0;
- ftp_data.logginRetries = 0;
+ ftp_data.loginRetries = 0;
ftp_data.ctimeout = 0;
- ftp_data.loggin.uservalid = false;
- ftp_data.loggin.passvalid = false;
+ ftp_data.login.uservalid = false;
+ ftp_data.login.passvalid = false;
strcpy (ftp_path, "/");
ftp_send_reply (220, "MicroPython FTP Server");
break;
@@ -684,7 +684,7 @@ static void ftp_process_cmd (void) {
if (E_FTP_RESULT_OK == (result = ftp_recv_non_blocking(ftp_data.c_sd, ftp_cmd_buffer, FTP_MAX_PARAM_SIZE + FTP_CMD_SIZE_MAX, &len))) {
// bufptr is moved as commands are being popped
ftp_cmd_index_t cmd = ftp_pop_command(&bufptr);
- if (!ftp_data.loggin.passvalid && (cmd != E_FTP_CMD_USER && cmd != E_FTP_CMD_PASS && cmd != E_FTP_CMD_QUIT && cmd != E_FTP_CMD_FEAT)) {
+ if (!ftp_data.login.passvalid && (cmd != E_FTP_CMD_USER && cmd != E_FTP_CMD_PASS && cmd != E_FTP_CMD_QUIT && cmd != E_FTP_CMD_FEAT)) {
ftp_send_reply(332, NULL);
return;
}
@@ -754,16 +754,16 @@ static void ftp_process_cmd (void) {
case E_FTP_CMD_USER:
ftp_pop_param (&bufptr, ftp_scratch_buffer);
if (!memcmp(ftp_scratch_buffer, servers_user, MAX(strlen(ftp_scratch_buffer), strlen(servers_user)))) {
- ftp_data.loggin.uservalid = true && (strlen(servers_user) == strlen(ftp_scratch_buffer));
+ ftp_data.login.uservalid = true && (strlen(servers_user) == strlen(ftp_scratch_buffer));
}
ftp_send_reply(331, NULL);
break;
case E_FTP_CMD_PASS:
ftp_pop_param (&bufptr, ftp_scratch_buffer);
if (!memcmp(ftp_scratch_buffer, servers_pass, MAX(strlen(ftp_scratch_buffer), strlen(servers_pass))) &&
- ftp_data.loggin.uservalid) {
- ftp_data.loggin.passvalid = true && (strlen(servers_pass) == strlen(ftp_scratch_buffer));
- if (ftp_data.loggin.passvalid) {
+ ftp_data.login.uservalid) {
+ ftp_data.login.passvalid = true && (strlen(servers_pass) == strlen(ftp_scratch_buffer));
+ if (ftp_data.login.passvalid) {
ftp_send_reply(230, NULL);
break;
}
diff --git a/ports/cc3200/hal/cc3200_hal.c b/ports/cc3200/hal/cc3200_hal.c
index 3a35e39e1f55e..4d9d7647d3dec 100644
--- a/ports/cc3200/hal/cc3200_hal.c
+++ b/ports/cc3200/hal/cc3200_hal.c
@@ -49,7 +49,7 @@
#include "pybuart.h"
#include "utils.h"
#include "irq.h"
-#include "moduos.h"
+#include "modos.h"
#ifdef USE_FREERTOS
#include "FreeRTOS.h"
@@ -195,3 +195,5 @@ static void hal_TickInit (void) {
MAP_SysTickEnable();
}
#endif
+
+MP_REGISTER_ROOT_POINTER(struct _os_term_dup_obj_t *os_term_dup_obj);
diff --git a/ports/cc3200/hal/cc3200_hal.h b/ports/cc3200/hal/cc3200_hal.h
index 3d0d632d519b4..9e57d39e2e708 100644
--- a/ports/cc3200/hal/cc3200_hal.h
+++ b/ports/cc3200/hal/cc3200_hal.h
@@ -67,3 +67,4 @@ extern void mp_hal_set_interrupt_char (int c);
#define mp_hal_stdio_poll(poll_flags) (0) // not implemented
#define mp_hal_delay_us(usec) UtilsDelay(UTILS_DELAY_US_TO_COUNT(usec))
#define mp_hal_ticks_cpu() (SysTickPeriodGet() - SysTickValueGet())
+#define mp_hal_time_ns() (0) // not implemented
diff --git a/ports/cc3200/misc/help.c b/ports/cc3200/misc/help.c
index ea0c9501dbce0..213950c8ed6b0 100644
--- a/ports/cc3200/misc/help.c
+++ b/ports/cc3200/misc/help.c
@@ -28,5 +28,5 @@
#include "py/builtin.h"
const char cc3200_help_text[] = "Welcome to MicroPython!\n"
- "For online help please visit http://micropython.org/help/.\n"
+ "For online docs please visit http://docs.micropython.org/\n"
"For further help on a specific object, type help(obj)\n";
diff --git a/ports/cc3200/misc/mperror.c b/ports/cc3200/misc/mperror.c
index 082d940e2f3ac..6d6c0ff0bae8a 100644
--- a/ports/cc3200/misc/mperror.c
+++ b/ports/cc3200/misc/mperror.c
@@ -127,7 +127,7 @@ void mperror_deinit_sfe_pin (void) {
void mperror_signal_error (void) {
uint32_t count = 0;
while ((MPERROR_TOOGLE_MS * count++) < MPERROR_SIGNAL_ERROR_MS) {
- // toogle the led
+ // toggle the led
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
UtilsDelay(UTILS_DELAY_US_TO_COUNT(MPERROR_TOOGLE_MS * 1000));
}
diff --git a/ports/cc3200/misc/mpirq.c b/ports/cc3200/misc/mpirq.c
index de30ebc499683..eb813fa4c6f2a 100644
--- a/ports/cc3200/misc/mpirq.c
+++ b/ports/cc3200/misc/mpirq.c
@@ -190,10 +190,12 @@ STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table);
-const mp_obj_type_t mp_irq_type = {
- { &mp_type_type },
- .name = MP_QSTR_irq,
- .call = mp_irq_call,
- .locals_dict = (mp_obj_t)&mp_irq_locals_dict,
-};
-
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_irq_type,
+ MP_QSTR_irq,
+ MP_TYPE_FLAG_NONE,
+ call, mp_irq_call,
+ locals_dict, &mp_irq_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_irq_obj_list);
diff --git a/ports/cc3200/mods/modhashlib.c b/ports/cc3200/mods/modhashlib.c
new file mode 100644
index 0000000000000..de56e114af796
--- /dev/null
+++ b/ports/cc3200/mods/modhashlib.c
@@ -0,0 +1,209 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Paul Sokolovsky
+ * 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 "py/mpconfig.h"
+#include MICROPY_HAL_H
+#include "py/runtime.h"
+#include "inc/hw_types.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_nvic.h"
+#include "inc/hw_shamd5.h"
+#include "inc/hw_dthe.h"
+#include "hw_memmap.h"
+#include "rom_map.h"
+#include "prcm.h"
+#include "shamd5.h"
+#include "cryptohash.h"
+
+
+/******************************************************************************
+ DEFINE PRIVATE TYPES
+ ******************************************************************************/
+typedef struct _mp_obj_hash_t {
+ mp_obj_base_t base;
+ uint8_t *buffer;
+ uint32_t b_size;
+ uint32_t c_size;
+ uint8_t algo;
+ uint8_t h_size;
+ bool fixedlen;
+ bool digested;
+ uint8_t hash[32];
+} mp_obj_hash_t;
+
+/******************************************************************************
+ DECLARE PRIVATE FUNCTIONS
+ ******************************************************************************/
+STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest);
+STATIC mp_obj_t hash_read (mp_obj_t self_in);
+
+/******************************************************************************
+ DEFINE PRIVATE FUNCTIONS
+ ******************************************************************************/
+STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) {
+ mp_obj_hash_t *self = self_in;
+ mp_buffer_info_t bufinfo;
+
+ if (data) {
+ mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
+ }
+
+ if (digest) {
+ CRYPTOHASH_SHAMD5Start (self->algo, self->b_size);
+ }
+
+ if (self->c_size < self->b_size || !data || !self->fixedlen) {
+ if (digest || self->fixedlen) {
+ // no data means we want to process our internal buffer
+ CRYPTOHASH_SHAMD5Update (data ? bufinfo.buf : self->buffer, data ? bufinfo.len : self->b_size);
+ self->c_size += data ? bufinfo.len : 0;
+ } else {
+ self->buffer = m_renew(byte, self->buffer, self->b_size, self->b_size + bufinfo.len);
+ mp_seq_copy((byte*)self->buffer + self->b_size, bufinfo.buf, bufinfo.len, byte);
+ self->b_size += bufinfo.len;
+ self->digested = false;
+ }
+ } else {
+ mp_raise_OSError(MP_EPERM);
+ }
+}
+
+STATIC mp_obj_t hash_read (mp_obj_t self_in) {
+ mp_obj_hash_t *self = self_in;
+
+ if (!self->fixedlen) {
+ if (!self->digested) {
+ hash_update_internal(self, MP_OBJ_NULL, true);
+ }
+ } else if (self->c_size < self->b_size) {
+ // it's a fixed len block which is still incomplete
+ mp_raise_OSError(MP_EPERM);
+ }
+
+ if (!self->digested) {
+ CRYPTOHASH_SHAMD5Read ((uint8_t *)self->hash);
+ self->digested = true;
+ }
+ return mp_obj_new_bytes(self->hash, self->h_size);
+}
+
+/******************************************************************************/
+// MicroPython bindings
+
+/// \classmethod \constructor([data[, block_size]])
+/// initial data must be given if block_size wants to be passed
+STATIC mp_obj_t hash_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 0, 2, false);
+ mp_obj_hash_t *self = m_new0(mp_obj_hash_t, 1);
+ self->base.type = type_in;
+ if (self->base.type->name == MP_QSTR_sha1) {
+ self->algo = SHAMD5_ALGO_SHA1;
+ self->h_size = 20;
+ } else /* if (self->base.type->name == MP_QSTR_sha256) */ {
+ self->algo = SHAMD5_ALGO_SHA256;
+ self->h_size = 32;
+ } /* else {
+ self->algo = SHAMD5_ALGO_MD5;
+ self->h_size = 32;
+ } */
+
+ if (n_args) {
+ // CPython extension to avoid buffering the data before digesting it
+ // Note: care must be taken to provide all intermediate blocks as multiple
+ // of four bytes, otherwise the resulting hash will be incorrect.
+ // the final block can be of any length
+ if (n_args > 1) {
+ // block size given, we will feed the data directly into the hash engine
+ self->fixedlen = true;
+ self->b_size = mp_obj_get_int(args[1]);
+ hash_update_internal(self, args[0], true);
+ } else {
+ hash_update_internal(self, args[0], false);
+ }
+ }
+ return self;
+}
+
+STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg) {
+ mp_obj_hash_t *self = self_in;
+ hash_update_internal(self, arg, false);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(hash_update_obj, hash_update);
+
+STATIC mp_obj_t hash_digest(mp_obj_t self_in) {
+ return hash_read(self_in);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(hash_digest_obj, hash_digest);
+
+STATIC const mp_rom_map_elem_t hash_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hash_update_obj) },
+ { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hash_digest_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(hash_locals_dict, hash_locals_dict_table);
+
+//STATIC const mp_obj_type_t md5_type = {
+// { &mp_type_type },
+// .name = MP_QSTR_md5,
+// .make_new = hash_make_new,
+// .locals_dict = (mp_obj_t)&hash_locals_dict,
+//};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ sha1_type,
+ MP_QSTR_sha1,
+ MP_TYPE_FLAG_NONE,
+ make_new, hash_make_new,
+ locals_dict, &hash_locals_dict
+ );
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ sha256_type,
+ MP_QSTR_sha256,
+ MP_TYPE_FLAG_NONE,
+ make_new, hash_make_new,
+ locals_dict, &hash_locals_dict
+ );
+
+STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hashlib) },
+ //{ MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&md5_type) },
+ { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&sha1_type) },
+ { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&sha256_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table);
+
+const mp_obj_module_t mp_module_hashlib = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mp_module_hashlib_globals,
+};
+
diff --git a/ports/cc3200/mods/modmachine.c b/ports/cc3200/mods/modmachine.c
index 782ccc55a1d2f..bdf963c31a601 100644
--- a/ports/cc3200/mods/modmachine.c
+++ b/ports/cc3200/mods/modmachine.c
@@ -43,7 +43,7 @@
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
-#include "moduos.h"
+#include "modos.h"
#include "FreeRTOS.h"
#include "portable.h"
#include "task.h"
@@ -162,7 +162,7 @@ STATIC mp_obj_t machine_wake_reason (void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_wake_reason_obj, machine_wake_reason);
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
#ifdef DEBUG
@@ -214,4 +214,5 @@ const mp_obj_module_t mp_module_machine = {
.globals = (mp_obj_dict_t*)&machine_module_globals,
};
-MP_REGISTER_MODULE(MP_QSTR_umachine, mp_module_machine);
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_machine, mp_module_machine);
+MP_REGISTER_ROOT_POINTER(mp_obj_t machine_config_main);
diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c
index d6ccc7c6a04d7..590e872683930 100644
--- a/ports/cc3200/mods/modnetwork.c
+++ b/ports/cc3200/mods/modnetwork.c
@@ -171,10 +171,11 @@ STATIC const mp_rom_map_elem_t network_server_locals_dict_table[] = {
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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ network_server_type,
+ MP_QSTR_Server,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_server_make_new,
+ locals_dict, &network_server_locals_dict
+ );
#endif
diff --git a/ports/cc3200/mods/modnetwork.h b/ports/cc3200/mods/modnetwork.h
index 6ec90a2bac189..9bc2c71c29335 100644
--- a/ports/cc3200/mods/modnetwork.h
+++ b/ports/cc3200/mods/modnetwork.h
@@ -35,10 +35,6 @@
/******************************************************************************
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 {
@@ -63,7 +59,7 @@ typedef struct _mod_network_socket_obj_t {
/******************************************************************************
EXPORTED DATA
******************************************************************************/
-extern const mod_network_nic_type_t mod_network_nic_type_wlan;
+extern const mp_obj_type_t mod_network_nic_type_wlan;
/******************************************************************************
DECLARE FUNCTIONS
diff --git a/ports/cc3200/mods/modos.c b/ports/cc3200/mods/modos.c
new file mode 100644
index 0000000000000..1a854750f2340
--- /dev/null
+++ b/ports/cc3200/mods/modos.c
@@ -0,0 +1,183 @@
+/*
+ * 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 "py/objtuple.h"
+#include "py/objstr.h"
+#include "py/runtime.h"
+#include "shared/timeutils/timeutils.h"
+#include "lib/oofatfs/ff.h"
+#include "lib/oofatfs/diskio.h"
+#include "genhdr/mpversion.h"
+#include "modos.h"
+#include "sflash_diskio.h"
+#include "extmod/vfs.h"
+#include "extmod/vfs_fat.h"
+#include "random.h"
+#include "version.h"
+#include "pybsd.h"
+#include "pybuart.h"
+
+/// \module os - basic "operating system" services
+///
+/// The `os` module contains functions for filesystem access and `urandom`.
+///
+/// The filesystem has `/` as the root directory, and the available physical
+/// drives are accessible from here. They are currently:
+///
+/// /flash -- the serial flash filesystem
+///
+/// On boot up, the current directory is `/flash`.
+
+/******************************************************************************
+ DECLARE PRIVATE DATA
+ ******************************************************************************/
+STATIC os_term_dup_obj_t os_term_dup_obj;
+
+/******************************************************************************
+ DEFINE PUBLIC FUNCTIONS
+ ******************************************************************************/
+
+void osmount_unmount_all (void) {
+ //TODO
+ /*
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
+ os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
+ unmount(mount_obj);
+ }
+ */
+}
+
+/******************************************************************************/
+// MicroPython bindings
+//
+
+STATIC const qstr os_uname_info_fields[] = {
+ MP_QSTR_sysname, MP_QSTR_nodename,
+ MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
+};
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, WIPY_SW_VERSION_NUMBER);
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
+STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
+STATIC MP_DEFINE_ATTRTUPLE(
+ os_uname_info_obj,
+ os_uname_info_fields,
+ 5,
+ (mp_obj_t)&os_uname_info_sysname_obj,
+ (mp_obj_t)&os_uname_info_nodename_obj,
+ (mp_obj_t)&os_uname_info_release_obj,
+ (mp_obj_t)&os_uname_info_version_obj,
+ (mp_obj_t)&os_uname_info_machine_obj
+);
+
+STATIC mp_obj_t os_uname(void) {
+ return (mp_obj_t)&os_uname_info_obj;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
+
+STATIC mp_obj_t os_sync(void) {
+ sflash_disk_flush();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
+
+STATIC mp_obj_t os_urandom(mp_obj_t num) {
+ mp_int_t n = mp_obj_get_int(num);
+ vstr_t vstr;
+ vstr_init_len(&vstr, n);
+ for (int i = 0; i < n; i++) {
+ vstr.buf[i] = rng_get();
+ }
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
+
+STATIC mp_obj_t os_dupterm(uint n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ if (MP_STATE_PORT(os_term_dup_obj) == MP_OBJ_NULL) {
+ return mp_const_none;
+ } else {
+ return MP_STATE_PORT(os_term_dup_obj)->stream_o;
+ }
+ } else {
+ mp_obj_t stream_o = args[0];
+ if (stream_o == mp_const_none) {
+ MP_STATE_PORT(os_term_dup_obj) = MP_OBJ_NULL;
+ } else {
+ if (!mp_obj_is_type(stream_o, &pyb_uart_type)) {
+ // must be a stream-like object providing at least read and write methods
+ mp_load_method(stream_o, MP_QSTR_read, os_term_dup_obj.read);
+ mp_load_method(stream_o, MP_QSTR_write, os_term_dup_obj.write);
+ }
+ os_term_dup_obj.stream_o = stream_o;
+ MP_STATE_PORT(os_term_dup_obj) = &os_term_dup_obj;
+ }
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_dupterm_obj, 0, 1, os_dupterm);
+
+STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) },
+
+ { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) },
+ { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove
+
+ { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&os_sync_obj) },
+ { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
+
+ // MicroPython additions
+ // removed: mkfs
+ // renamed: unmount -> umount
+ { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
+ { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
+ { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
+ { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&os_dupterm_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
+
+const mp_obj_module_t mp_module_os = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&os_module_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_os, mp_module_os);
diff --git a/ports/cc3200/mods/modos.h b/ports/cc3200/mods/modos.h
new file mode 100644
index 0000000000000..5fa2a967d4347
--- /dev/null
+++ b/ports/cc3200/mods/modos.h
@@ -0,0 +1,47 @@
+/*
+ * 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_MODOS_H
+#define MICROPY_INCLUDED_CC3200_MODS_MODOS_H
+
+#include "py/obj.h"
+
+/******************************************************************************
+ DEFINE PUBLIC TYPES
+ ******************************************************************************/
+
+typedef struct _os_term_dup_obj_t {
+ mp_obj_t stream_o;
+ mp_obj_t read[3];
+ mp_obj_t write[3];
+} os_term_dup_obj_t;
+
+/******************************************************************************
+ DECLARE PUBLIC FUNCTIONS
+ ******************************************************************************/
+void osmount_unmount_all (void);
+
+#endif // MICROPY_INCLUDED_CC3200_MODS_MODOS_H
diff --git a/ports/cc3200/mods/modsocket.c b/ports/cc3200/mods/modsocket.c
new file mode 100644
index 0000000000000..a107fa7120736
--- /dev/null
+++ b/ports/cc3200/mods/modsocket.c
@@ -0,0 +1,821 @@
+/*
+ * 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 "shared/netutils/netutils.h"
+#include "modnetwork.h"
+#include "modsocket.h"
+
+/******************************************************************************/
+// The following set of macros and functions provide a glue between the CC3100
+// simplelink layer and the functions/methods provided by the socket module.
+// They were historically in a separate file because socket 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 socket 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 = MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT;
+ 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_bytes_from_vstr(&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_bytes_from_vstr(&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 MP_DEFINE_CONST_OBJ_TYPE(
+ socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, socket_make_new,
+ protocol, &socket_stream_p,
+ locals_dict, &socket_locals_dict
+ );
+
+/******************************************************************************/
+// socket module
+
+// function socket.getaddrinfo(host, port)
+/// \function getaddrinfo(host, port)
+STATIC mp_obj_t mod_socket_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_socket_getaddrinfo_obj, mod_socket_getaddrinfo);
+
+STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_socket) },
+
+ { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) },
+ { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_socket_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_socket_globals, mp_module_socket_globals_table);
+
+const mp_obj_module_t mp_module_socket = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mp_module_socket_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_socket, mp_module_socket);
diff --git a/ports/cc3200/mods/modsocket.h b/ports/cc3200/mods/modsocket.h
new file mode 100644
index 0000000000000..8eb4cb50ac6ad
--- /dev/null
+++ b/ports/cc3200/mods/modsocket.h
@@ -0,0 +1,40 @@
+/*
+ * 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_MODSOCKET_H
+#define MICROPY_INCLUDED_CC3200_MODS_MODSOCKET_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_MODSOCKET_H
diff --git a/ports/cc3200/mods/modssl.c b/ports/cc3200/mods/modssl.c
new file mode 100644
index 0000000000000..15c825fcf4dcb
--- /dev/null
+++ b/ports/cc3200/mods/modssl.c
@@ -0,0 +1,163 @@
+/*
+ * 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 "simplelink.h"
+#include "py/mpconfig.h"
+#include "py/obj.h"
+#include "py/objstr.h"
+#include "py/runtime.h"
+#include "modnetwork.h"
+#include "modsocket.h"
+
+/******************************************************************************
+ DEFINE CONSTANTS
+ ******************************************************************************/
+#define SSL_CERT_NONE (0)
+#define SSL_CERT_OPTIONAL (1)
+#define SSL_CERT_REQUIRED (2)
+
+/******************************************************************************
+ DEFINE TYPES
+ ******************************************************************************/
+typedef struct _mp_obj_ssl_socket_t {
+ mp_obj_base_t base;
+ mod_network_socket_base_t sock_base;
+ mp_obj_t o_sock;
+} mp_obj_ssl_socket_t;
+
+/******************************************************************************
+ DECLARE PRIVATE DATA
+ ******************************************************************************/
+STATIC const mp_obj_type_t ssl_socket_type;
+
+/******************************************************************************/
+// MicroPython bindings; SSL class
+
+// ssl sockets inherit from normal socket, so we take its
+// locals and stream methods
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ssl_socket_type,
+ MP_QSTR_ssl,
+ MP_TYPE_FLAG_NONE,
+ protocol, &socket_stream_p,
+ locals_dict, &socket_locals_dict
+ );
+
+STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ STATIC const mp_arg_t allowed_args[] = {
+ { MP_QSTR_sock, MP_ARG_REQUIRED | MP_ARG_OBJ, },
+ { MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} },
+ { MP_QSTR_ssl_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SL_SO_SEC_METHOD_TLSV1} },
+ { MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ // parse arguments
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // check if ca validation is required
+ if (args[4].u_int != SSL_CERT_NONE && args[6].u_obj == mp_const_none) {
+ goto arg_error;
+ }
+
+ // retrieve the file paths (with an 6 byte offset in order to strip it from the '/flash' prefix)
+ const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]);
+ const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]);
+ const char *cafile = (args[6].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
+ NULL : &(mp_obj_str_get_str(args[6].u_obj)[6]);
+
+ // server side requires both certfile and keyfile
+ if (args[3].u_bool && (!keyfile || !certfile)) {
+ goto arg_error;
+ }
+
+ _i16 _errno;
+ _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
+
+ // set the requested SSL method
+ _u8 method = args[5].u_int;
+ if ((_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method))) < 0) {
+ goto socket_error;
+ }
+ if (keyfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, keyfile, strlen(keyfile))) < 0) {
+ goto socket_error;
+ }
+ if (certfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, certfile, strlen(certfile))) < 0) {
+ goto socket_error;
+ }
+ if (cafile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME, cafile, strlen(cafile))) < 0) {
+ goto socket_error;
+ }
+
+ // 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));
+ 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;
+
+ return ssl_sock;
+
+socket_error:
+ mp_raise_OSError(_errno);
+
+arg_error:
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid argument(s) value"));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 0, mod_ssl_wrap_socket);
+
+STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ssl) },
+ { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
+
+ // class exceptions
+ { MP_ROM_QSTR(MP_QSTR_SSLError), MP_ROM_PTR(&mp_type_OSError) },
+
+ // class constants
+ { MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(SSL_CERT_NONE) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(SSL_CERT_OPTIONAL) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(SSL_CERT_REQUIRED) },
+
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_SSLv3), MP_ROM_INT(SL_SO_SEC_METHOD_SSLV3) },
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1) },
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1_1), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1_1) },
+ { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1_2), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1_2) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
+
+const mp_obj_module_t mp_module_ssl = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mp_module_ssl_globals,
+};
+
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_ssl, mp_module_ssl);
diff --git a/ports/cc3200/mods/modtime.c b/ports/cc3200/mods/modtime.c
new file mode 100644
index 0000000000000..6fa98296d2fbd
--- /dev/null
+++ b/ports/cc3200/mods/modtime.c
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2023 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/obj.h"
+#include "shared/timeutils/timeutils.h"
+#include "pybrtc.h"
+
+// Return the localtime as an 8-tuple.
+STATIC mp_obj_t mp_time_localtime_get(void) {
+ timeutils_struct_time_t tm;
+
+ // get the seconds from the RTC
+ timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm);
+ mp_obj_t tuple[8] = {
+ mp_obj_new_int(tm.tm_year),
+ mp_obj_new_int(tm.tm_mon),
+ mp_obj_new_int(tm.tm_mday),
+ mp_obj_new_int(tm.tm_hour),
+ mp_obj_new_int(tm.tm_min),
+ mp_obj_new_int(tm.tm_sec),
+ mp_obj_new_int(tm.tm_wday),
+ mp_obj_new_int(tm.tm_yday)
+ };
+ return mp_obj_new_tuple(8, tuple);
+}
+
+// Returns the number of seconds, as an integer, since the Epoch.
+STATIC mp_obj_t mp_time_time_get(void) {
+ return mp_obj_new_int(pyb_rtc_get_seconds());
+}
diff --git a/ports/cc3200/mods/moduhashlib.c b/ports/cc3200/mods/moduhashlib.c
deleted file mode 100644
index fc11569b7f988..0000000000000
--- a/ports/cc3200/mods/moduhashlib.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Paul Sokolovsky
- * 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 "py/mpconfig.h"
-#include MICROPY_HAL_H
-#include "py/runtime.h"
-#include "inc/hw_types.h"
-#include "inc/hw_ints.h"
-#include "inc/hw_nvic.h"
-#include "inc/hw_shamd5.h"
-#include "inc/hw_dthe.h"
-#include "hw_memmap.h"
-#include "rom_map.h"
-#include "prcm.h"
-#include "shamd5.h"
-#include "cryptohash.h"
-
-
-/******************************************************************************
- DEFINE PRIVATE TYPES
- ******************************************************************************/
-typedef struct _mp_obj_hash_t {
- mp_obj_base_t base;
- uint8_t *buffer;
- uint32_t b_size;
- uint32_t c_size;
- uint8_t algo;
- uint8_t h_size;
- bool fixedlen;
- bool digested;
- uint8_t hash[32];
-} mp_obj_hash_t;
-
-/******************************************************************************
- DECLARE PRIVATE FUNCTIONS
- ******************************************************************************/
-STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest);
-STATIC mp_obj_t hash_read (mp_obj_t self_in);
-
-/******************************************************************************
- DEFINE PRIVATE FUNCTIONS
- ******************************************************************************/
-STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) {
- mp_obj_hash_t *self = self_in;
- mp_buffer_info_t bufinfo;
-
- if (data) {
- mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
- }
-
- if (digest) {
- CRYPTOHASH_SHAMD5Start (self->algo, self->b_size);
- }
-
- if (self->c_size < self->b_size || !data || !self->fixedlen) {
- if (digest || self->fixedlen) {
- // no data means we want to process our internal buffer
- CRYPTOHASH_SHAMD5Update (data ? bufinfo.buf : self->buffer, data ? bufinfo.len : self->b_size);
- self->c_size += data ? bufinfo.len : 0;
- } else {
- self->buffer = m_renew(byte, self->buffer, self->b_size, self->b_size + bufinfo.len);
- mp_seq_copy((byte*)self->buffer + self->b_size, bufinfo.buf, bufinfo.len, byte);
- self->b_size += bufinfo.len;
- self->digested = false;
- }
- } else {
- mp_raise_OSError(MP_EPERM);
- }
-}
-
-STATIC mp_obj_t hash_read (mp_obj_t self_in) {
- mp_obj_hash_t *self = self_in;
-
- if (!self->fixedlen) {
- if (!self->digested) {
- hash_update_internal(self, MP_OBJ_NULL, true);
- }
- } else if (self->c_size < self->b_size) {
- // it's a fixed len block which is still incomplete
- mp_raise_OSError(MP_EPERM);
- }
-
- if (!self->digested) {
- CRYPTOHASH_SHAMD5Read ((uint8_t *)self->hash);
- self->digested = true;
- }
- return mp_obj_new_bytes(self->hash, self->h_size);
-}
-
-/******************************************************************************/
-// MicroPython bindings
-
-/// \classmethod \constructor([data[, block_size]])
-/// initial data must be given if block_size wants to be passed
-STATIC mp_obj_t hash_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- mp_arg_check_num(n_args, n_kw, 0, 2, false);
- mp_obj_hash_t *self = m_new0(mp_obj_hash_t, 1);
- self->base.type = type_in;
- if (self->base.type->name == MP_QSTR_sha1) {
- self->algo = SHAMD5_ALGO_SHA1;
- self->h_size = 20;
- } else /* if (self->base.type->name == MP_QSTR_sha256) */ {
- self->algo = SHAMD5_ALGO_SHA256;
- self->h_size = 32;
- } /* else {
- self->algo = SHAMD5_ALGO_MD5;
- self->h_size = 32;
- } */
-
- if (n_args) {
- // CPython extension to avoid buffering the data before digesting it
- // Note: care must be taken to provide all intermediate blocks as multiple
- // of four bytes, otherwise the resulting hash will be incorrect.
- // the final block can be of any length
- if (n_args > 1) {
- // block size given, we will feed the data directly into the hash engine
- self->fixedlen = true;
- self->b_size = mp_obj_get_int(args[1]);
- hash_update_internal(self, args[0], true);
- } else {
- hash_update_internal(self, args[0], false);
- }
- }
- return self;
-}
-
-STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg) {
- mp_obj_hash_t *self = self_in;
- hash_update_internal(self, arg, false);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_2(hash_update_obj, hash_update);
-
-STATIC mp_obj_t hash_digest(mp_obj_t self_in) {
- return hash_read(self_in);
-}
-MP_DEFINE_CONST_FUN_OBJ_1(hash_digest_obj, hash_digest);
-
-STATIC const mp_rom_map_elem_t hash_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hash_update_obj) },
- { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hash_digest_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(hash_locals_dict, hash_locals_dict_table);
-
-//STATIC const mp_obj_type_t md5_type = {
-// { &mp_type_type },
-// .name = MP_QSTR_md5,
-// .make_new = hash_make_new,
-// .locals_dict = (mp_obj_t)&hash_locals_dict,
-//};
-
-STATIC const mp_obj_type_t sha1_type = {
- { &mp_type_type },
- .name = MP_QSTR_sha1,
- .make_new = hash_make_new,
- .locals_dict = (mp_obj_t)&hash_locals_dict,
-};
-
-STATIC const mp_obj_type_t sha256_type = {
- { &mp_type_type },
- .name = MP_QSTR_sha256,
- .make_new = hash_make_new,
- .locals_dict = (mp_obj_t)&hash_locals_dict,
-};
-
-STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) },
- //{ MP_ROM_QSTR(MP_QSTR_md5), MP_ROM_PTR(&md5_type) },
- { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&sha1_type) },
- { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&sha256_type) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table);
-
-const mp_obj_module_t mp_module_uhashlib = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_hashlib_globals,
-};
-
diff --git a/ports/cc3200/mods/moduos.c b/ports/cc3200/mods/moduos.c
deleted file mode 100644
index cd01b59b35d5c..0000000000000
--- a/ports/cc3200/mods/moduos.c
+++ /dev/null
@@ -1,183 +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 "py/objtuple.h"
-#include "py/objstr.h"
-#include "py/runtime.h"
-#include "shared/timeutils/timeutils.h"
-#include "lib/oofatfs/ff.h"
-#include "lib/oofatfs/diskio.h"
-#include "genhdr/mpversion.h"
-#include "moduos.h"
-#include "sflash_diskio.h"
-#include "extmod/vfs.h"
-#include "extmod/vfs_fat.h"
-#include "random.h"
-#include "version.h"
-#include "pybsd.h"
-#include "pybuart.h"
-
-/// \module os - basic "operating system" services
-///
-/// The `os` module contains functions for filesystem access and `urandom`.
-///
-/// The filesystem has `/` as the root directory, and the available physical
-/// drives are accessible from here. They are currently:
-///
-/// /flash -- the serial flash filesystem
-///
-/// On boot up, the current directory is `/flash`.
-
-/******************************************************************************
- DECLARE PRIVATE DATA
- ******************************************************************************/
-STATIC os_term_dup_obj_t os_term_dup_obj;
-
-/******************************************************************************
- DEFINE PUBLIC FUNCTIONS
- ******************************************************************************/
-
-void osmount_unmount_all (void) {
- //TODO
- /*
- for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
- os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
- unmount(mount_obj);
- }
- */
-}
-
-/******************************************************************************/
-// MicroPython bindings
-//
-
-STATIC const qstr os_uname_info_fields[] = {
- MP_QSTR_sysname, MP_QSTR_nodename,
- MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
-};
-STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
-STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
-STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, WIPY_SW_VERSION_NUMBER);
-STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
-STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
-STATIC MP_DEFINE_ATTRTUPLE(
- os_uname_info_obj,
- os_uname_info_fields,
- 5,
- (mp_obj_t)&os_uname_info_sysname_obj,
- (mp_obj_t)&os_uname_info_nodename_obj,
- (mp_obj_t)&os_uname_info_release_obj,
- (mp_obj_t)&os_uname_info_version_obj,
- (mp_obj_t)&os_uname_info_machine_obj
-);
-
-STATIC mp_obj_t os_uname(void) {
- return (mp_obj_t)&os_uname_info_obj;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
-
-STATIC mp_obj_t os_sync(void) {
- sflash_disk_flush();
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
-
-STATIC mp_obj_t os_urandom(mp_obj_t num) {
- mp_int_t n = mp_obj_get_int(num);
- vstr_t vstr;
- vstr_init_len(&vstr, n);
- for (int i = 0; i < n; i++) {
- vstr.buf[i] = rng_get();
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
-
-STATIC mp_obj_t os_dupterm(uint n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- if (MP_STATE_PORT(os_term_dup_obj) == MP_OBJ_NULL) {
- return mp_const_none;
- } else {
- return MP_STATE_PORT(os_term_dup_obj)->stream_o;
- }
- } else {
- mp_obj_t stream_o = args[0];
- if (stream_o == mp_const_none) {
- MP_STATE_PORT(os_term_dup_obj) = MP_OBJ_NULL;
- } else {
- if (!mp_obj_is_type(stream_o, &pyb_uart_type)) {
- // must be a stream-like object providing at least read and write methods
- mp_load_method(stream_o, MP_QSTR_read, os_term_dup_obj.read);
- mp_load_method(stream_o, MP_QSTR_write, os_term_dup_obj.write);
- }
- os_term_dup_obj.stream_o = stream_o;
- MP_STATE_PORT(os_term_dup_obj) = &os_term_dup_obj;
- }
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_dupterm_obj, 0, 1, os_dupterm);
-
-STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
-
- { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
-
- { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
- { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) },
- { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
- { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
- { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
- { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove
-
- { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&os_sync_obj) },
- { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
-
- // MicroPython additions
- // removed: mkfs
- // renamed: unmount -> umount
- { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
- { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
- { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
- { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&os_dupterm_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
-
-const mp_obj_module_t mp_module_uos = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&os_module_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_uos, mp_module_uos);
diff --git a/ports/cc3200/mods/moduos.h b/ports/cc3200/mods/moduos.h
deleted file mode 100644
index f183715c907ca..0000000000000
--- a/ports/cc3200/mods/moduos.h
+++ /dev/null
@@ -1,47 +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_MODUOS_H
-#define MICROPY_INCLUDED_CC3200_MODS_MODUOS_H
-
-#include "py/obj.h"
-
-/******************************************************************************
- DEFINE PUBLIC TYPES
- ******************************************************************************/
-
-typedef struct _os_term_dup_obj_t {
- mp_obj_t stream_o;
- mp_obj_t read[3];
- mp_obj_t write[3];
-} os_term_dup_obj_t;
-
-/******************************************************************************
- DECLARE PUBLIC FUNCTIONS
- ******************************************************************************/
-void osmount_unmount_all (void);
-
-#endif // MICROPY_INCLUDED_CC3200_MODS_MODUOS_H
diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c
deleted file mode 100644
index 32849c51d47c6..0000000000000
--- a/ports/cc3200/mods/modusocket.c
+++ /dev/null
@@ -1,820 +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 "shared/netutils/netutils.h"
-#include "modnetwork.h"
-#include "modusocket.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 = MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT;
- 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,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_usocket);
diff --git a/ports/cc3200/mods/modusocket.h b/ports/cc3200/mods/modusocket.h
deleted file mode 100644
index aaee04ce1927e..0000000000000
--- a/ports/cc3200/mods/modusocket.h
+++ /dev/null
@@ -1,40 +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_MODUSOCKET_H
-#define MICROPY_INCLUDED_CC3200_MODS_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
diff --git a/ports/cc3200/mods/modussl.c b/ports/cc3200/mods/modussl.c
deleted file mode 100644
index cd2c62dcb82e3..0000000000000
--- a/ports/cc3200/mods/modussl.c
+++ /dev/null
@@ -1,164 +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 "simplelink.h"
-#include "py/mpconfig.h"
-#include "py/obj.h"
-#include "py/objstr.h"
-#include "py/runtime.h"
-#include "modnetwork.h"
-#include "modusocket.h"
-
-/******************************************************************************
- DEFINE CONSTANTS
- ******************************************************************************/
-#define SSL_CERT_NONE (0)
-#define SSL_CERT_OPTIONAL (1)
-#define SSL_CERT_REQUIRED (2)
-
-/******************************************************************************
- DEFINE TYPES
- ******************************************************************************/
-typedef struct _mp_obj_ssl_socket_t {
- mp_obj_base_t base;
- mod_network_socket_base_t sock_base;
- mp_obj_t o_sock;
-} mp_obj_ssl_socket_t;
-
-/******************************************************************************
- DECLARE PRIVATE DATA
- ******************************************************************************/
-STATIC const mp_obj_type_t ssl_socket_type;
-
-/******************************************************************************/
-// MicroPython bindings; SSL class
-
-// ssl sockets inherit from normal socket, so we take its
-// locals and stream methods
-STATIC const mp_obj_type_t ssl_socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_ussl,
- .getiter = NULL,
- .iternext = NULL,
- .protocol = &socket_stream_p,
- .locals_dict = (mp_obj_t)&socket_locals_dict,
-};
-
-STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- STATIC const mp_arg_t allowed_args[] = {
- { MP_QSTR_sock, MP_ARG_REQUIRED | MP_ARG_OBJ, },
- { MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} },
- { MP_QSTR_ssl_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SL_SO_SEC_METHOD_TLSV1} },
- { MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- };
-
- // parse arguments
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- // check if ca validation is required
- if (args[4].u_int != SSL_CERT_NONE && args[6].u_obj == mp_const_none) {
- goto arg_error;
- }
-
- // retrieve the file paths (with an 6 byte offset in order to strip it from the '/flash' prefix)
- const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]);
- const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]);
- const char *cafile = (args[6].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
- NULL : &(mp_obj_str_get_str(args[6].u_obj)[6]);
-
- // server side requires both certfile and keyfile
- if (args[3].u_bool && (!keyfile || !certfile)) {
- goto arg_error;
- }
-
- _i16 _errno;
- _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
-
- // set the requested SSL method
- _u8 method = args[5].u_int;
- if ((_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method))) < 0) {
- goto socket_error;
- }
- if (keyfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, keyfile, strlen(keyfile))) < 0) {
- goto socket_error;
- }
- if (certfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, certfile, strlen(certfile))) < 0) {
- goto socket_error;
- }
- if (cafile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME, cafile, strlen(cafile))) < 0) {
- goto socket_error;
- }
-
- // 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));
- 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;
-
- return ssl_sock;
-
-socket_error:
- mp_raise_OSError(_errno);
-
-arg_error:
- mp_raise_ValueError(MP_ERROR_TEXT("invalid argument(s) value"));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 0, mod_ssl_wrap_socket);
-
-STATIC const mp_rom_map_elem_t mp_module_ussl_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
- { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
-
- // class exceptions
- { MP_ROM_QSTR(MP_QSTR_SSLError), MP_ROM_PTR(&mp_type_OSError) },
-
- // class constants
- { MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(SSL_CERT_NONE) },
- { MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(SSL_CERT_OPTIONAL) },
- { MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(SSL_CERT_REQUIRED) },
-
- { MP_ROM_QSTR(MP_QSTR_PROTOCOL_SSLv3), MP_ROM_INT(SL_SO_SEC_METHOD_SSLV3) },
- { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1) },
- { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1_1), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1_1) },
- { MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLSv1_2), MP_ROM_INT(SL_SO_SEC_METHOD_TLSV1_2) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_ussl_globals, mp_module_ussl_globals_table);
-
-const mp_obj_module_t mp_module_ussl = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_ussl_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_ussl, mp_module_ussl);
diff --git a/ports/cc3200/mods/modutime.c b/ports/cc3200/mods/modutime.c
deleted file mode 100644
index 237a80065057a..0000000000000
--- a/ports/cc3200/mods/modutime.c
+++ /dev/null
@@ -1,159 +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 "py/mpconfig.h"
-#include "py/runtime.h"
-#include "py/obj.h"
-#include "py/smallint.h"
-#include "py/mphal.h"
-#include "shared/timeutils/timeutils.h"
-#include "extmod/utime_mphal.h"
-#include "inc/hw_types.h"
-#include "inc/hw_ints.h"
-#include "inc/hw_memmap.h"
-#include "rom_map.h"
-#include "prcm.h"
-#include "systick.h"
-#include "pybrtc.h"
-#include "utils.h"
-
-/// \module time - time related functions
-///
-/// The `time` module provides functions for getting the current time and date,
-/// and for sleeping.
-
-/******************************************************************************/
-// MicroPython bindings
-
-/// \function localtime([secs])
-/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
-/// contains: (year, month, mday, hour, minute, second, weekday, yearday)
-/// If secs is not provided or None, then the current time from the RTC is used.
-/// year includes the century (for example 2015)
-/// month is 1-12
-/// mday is 1-31
-/// hour is 0-23
-/// minute is 0-59
-/// second is 0-59
-/// weekday is 0-6 for Mon-Sun.
-/// yearday is 1-366
-STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
- if (n_args == 0 || args[0] == mp_const_none) {
- timeutils_struct_time_t tm;
-
- // get the seconds from the RTC
- timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm);
- mp_obj_t tuple[8] = {
- mp_obj_new_int(tm.tm_year),
- mp_obj_new_int(tm.tm_mon),
- mp_obj_new_int(tm.tm_mday),
- mp_obj_new_int(tm.tm_hour),
- mp_obj_new_int(tm.tm_min),
- mp_obj_new_int(tm.tm_sec),
- mp_obj_new_int(tm.tm_wday),
- mp_obj_new_int(tm.tm_yday)
- };
- return mp_obj_new_tuple(8, tuple);
- } else {
- mp_int_t seconds = mp_obj_get_int(args[0]);
- timeutils_struct_time_t tm;
- timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
- mp_obj_t tuple[8] = {
- tuple[0] = mp_obj_new_int(tm.tm_year),
- tuple[1] = mp_obj_new_int(tm.tm_mon),
- tuple[2] = mp_obj_new_int(tm.tm_mday),
- tuple[3] = mp_obj_new_int(tm.tm_hour),
- tuple[4] = mp_obj_new_int(tm.tm_min),
- tuple[5] = mp_obj_new_int(tm.tm_sec),
- tuple[6] = mp_obj_new_int(tm.tm_wday),
- tuple[7] = mp_obj_new_int(tm.tm_yday),
- };
- return mp_obj_new_tuple(8, tuple);
- }
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
-
-STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
- size_t len;
- mp_obj_t *elem;
-
- mp_obj_get_array(tuple, &len, &elem);
-
- // localtime generates a tuple of len 8. CPython uses 9, so we accept both.
- if (len < 8 || len > 9) {
- mp_raise_TypeError(MP_ERROR_TEXT("invalid argument(s) num/type"));
- }
-
- return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),
- mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
-}
-MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
-
-STATIC mp_obj_t time_time(void) {
- return mp_obj_new_int(pyb_rtc_get_seconds());
-}
-MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
-
-STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
- int32_t sleep_s = mp_obj_get_int(seconds_o);
- if (sleep_s > 0) {
- mp_hal_delay_ms(sleep_s * 1000);
- }
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
-
-STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
-
- { MP_ROM_QSTR(MP_QSTR_gmtime), MP_ROM_PTR(&time_localtime_obj) },
- { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) },
- { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) },
- { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&time_sleep_obj) },
-
- // MicroPython additions
- { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
-
-const mp_obj_module_t mp_module_utime = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&time_module_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_utime, mp_module_utime);
diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c
index 920079b589ae6..8d98dd0421de2 100644
--- a/ports/cc3200/mods/modwlan.c
+++ b/ports/cc3200/mods/modwlan.c
@@ -38,7 +38,7 @@
#include "shared/timeutils/timeutils.h"
#include "shared/netutils/netutils.h"
#include "modnetwork.h"
-#include "modusocket.h"
+#include "modsocket.h"
#include "modwlan.h"
#include "pybrtc.h"
#include "debug.h"
@@ -432,7 +432,7 @@ void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth
// switch to the requested mode
wlan_set_mode(mode);
- // stop and start again (we need to in the propper mode from now on)
+ // stop and start again (we need to be in the proper mode from now on)
wlan_reenable(mode);
// Set Tx power level for station or AP mode
@@ -608,7 +608,7 @@ STATIC void wlan_set_ssid (const char *ssid, uint8_t len, bool add_mac) {
// 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)
+ // we can assume that the length 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;
@@ -641,8 +641,8 @@ STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) {
if (key != NULL) {
memcpy(&wlan_obj.key, key, len);
wlan_obj.key[len] = '\0';
+ _u8 wep_key[32];
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;
@@ -1285,14 +1285,13 @@ STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = {
};
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,
- },
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mod_network_nic_type_wlan,
+ MP_QSTR_WLAN,
+ MP_TYPE_FLAG_NONE,
+ make_new, wlan_make_new,
+ locals_dict, &wlan_locals_dict
+ );
STATIC const mp_irq_methods_t wlan_irq_methods = {
.init = wlan_irq,
diff --git a/ports/cc3200/mods/pybadc.c b/ports/cc3200/mods/pybadc.c
index fbdd393cd2ecc..74664282560d2 100644
--- a/ports/cc3200/mods/pybadc.c
+++ b/ports/cc3200/mods/pybadc.c
@@ -233,13 +233,14 @@ STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
-const mp_obj_type_t pyb_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = adc_print,
- .make_new = adc_make_new,
- .locals_dict = (mp_obj_t)&adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, adc_make_new,
+ print, adc_print,
+ locals_dict, &adc_locals_dict
+ );
STATIC void adc_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_adc_channel_obj_t *self = self_in;
@@ -300,10 +301,11 @@ STATIC const mp_rom_map_elem_t adc_channel_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(adc_channel_locals_dict, adc_channel_locals_dict_table);
-STATIC const mp_obj_type_t pyb_adc_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADCChannel,
- .print = adc_channel_print,
- .call = adc_channel_call,
- .locals_dict = (mp_obj_t)&adc_channel_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_adc_channel_type,
+ MP_QSTR_ADCChannel,
+ MP_TYPE_FLAG_NONE,
+ print, adc_channel_print,
+ call, adc_channel_call,
+ locals_dict, &adc_channel_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c
index 9d534608becce..46b7be234f9cb 100644
--- a/ports/cc3200/mods/pybflash.c
+++ b/ports/cc3200/mods/pybflash.c
@@ -84,12 +84,13 @@ STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table);
-const mp_obj_type_t pyb_flash_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .make_new = pyb_flash_make_new,
- .locals_dict = (mp_obj_t)&pyb_flash_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_flash_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_flash_make_new,
+ locals_dict, &pyb_flash_locals_dict
+ );
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;
diff --git a/ports/cc3200/mods/pybi2c.c b/ports/cc3200/mods/pybi2c.c
index 5310176091a96..5d77dc8367c4a 100644
--- a/ports/cc3200/mods/pybi2c.c
+++ b/ports/cc3200/mods/pybi2c.c
@@ -392,7 +392,7 @@ STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map
pyb_i2c_read_into(args, &vstr);
// return the received data
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 3, pyb_i2c_readfrom);
@@ -456,7 +456,7 @@ STATIC mp_obj_t pyb_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp
vstr_t vstr;
pyb_i2c_readmem_into (args, &vstr);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_obj, 1, pyb_i2c_readfrom_mem);
@@ -521,10 +521,11 @@ STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
-const mp_obj_type_t pyb_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = pyb_i2c_print,
- .make_new = pyb_i2c_make_new,
- .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_i2c_make_new,
+ print, pyb_i2c_print,
+ locals_dict, &pyb_i2c_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybpin.c b/ports/cc3200/mods/pybpin.c
index fd2f032e8d7ce..6d10abab570f1 100644
--- a/ports/cc3200/mods/pybpin.c
+++ b/ports/cc3200/mods/pybpin.c
@@ -113,7 +113,7 @@ STATIC pybpin_wake_pin_t pybpin_wake_pin[PYBPIN_NUM_WAKE_PINS] =
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void pin_init0(void) {
-// this initalization also reconfigures the JTAG/SWD pins
+// this initialization also reconfigures the JTAG/SWD pins
#ifndef DEBUG
// assign all pins to the GPIO module so that peripherals can be connected to any
// pins without conflicts after a soft reset
@@ -560,7 +560,7 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, size_t n_args, const mp_obj
}
}
- // get the strenght
+ // get the strength
uint strength = args[3].u_int;
pin_validate_drive(strength);
@@ -931,14 +931,15 @@ STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table);
-const mp_obj_type_t pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = pin_print,
- .make_new = pin_make_new,
- .call = pin_call,
- .locals_dict = (mp_obj_t)&pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, pin_make_new,
+ print, pin_print,
+ call, pin_call,
+ locals_dict, &pin_locals_dict
+ );
STATIC const mp_irq_methods_t pin_irq_methods = {
.init = pin_irq,
@@ -952,10 +953,11 @@ STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in,
mp_printf(print, "", self->name);
}
-const mp_obj_type_t pin_board_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_board,
- .print = pin_named_pins_obj_print,
- .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ print, pin_named_pins_obj_print,
+ locals_dict, &pin_board_pins_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybrtc.c b/ports/cc3200/mods/pybrtc.c
index 6c1918831c8c2..e79fb29d00d00 100644
--- a/ports/cc3200/mods/pybrtc.c
+++ b/ports/cc3200/mods/pybrtc.c
@@ -76,7 +76,7 @@ STATIC void rtc_msec_add(uint16_t msecs_1, uint32_t *secs, uint16_t *msecs_2);
******************************************************************************/
__attribute__ ((section (".boot")))
void pyb_rtc_pre_init(void) {
- // only if comming out of a power-on reset
+ // only if coming out of a power-on reset
if (MAP_PRCMSysResetCauseGet() == PRCM_POWER_ON) {
// Mark the RTC in use first
MAP_PRCMRTCInUseSet();
@@ -118,7 +118,7 @@ void pyb_rtc_repeat_alarm (pyb_rtc_obj_t *self) {
pyb_rtc_get_time(&c_seconds, &c_mseconds);
- // substract the time elapsed between waking up and setting up the alarm again
+ // subtract the time elapsed between waking up and setting up the alarm again
int32_t wake_ms = ((c_seconds * 1000) + c_mseconds) - ((self->alarm_time_s * 1000) + self->alarm_time_ms);
int32_t next_alarm = self->alarm_ms - wake_ms;
next_alarm = next_alarm > 0 ? next_alarm : PYB_RTC_MIN_ALARM_TIME_MS;
@@ -469,12 +469,13 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
-const mp_obj_type_t pyb_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = pyb_rtc_make_new,
- .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_rtc_make_new,
+ locals_dict, &pyb_rtc_locals_dict
+ );
STATIC const mp_irq_methods_t pyb_rtc_irq_methods = {
.init = pyb_rtc_irq,
diff --git a/ports/cc3200/mods/pybsd.c b/ports/cc3200/mods/pybsd.c
index 817127634d898..952a117c4580a 100644
--- a/ports/cc3200/mods/pybsd.c
+++ b/ports/cc3200/mods/pybsd.c
@@ -71,7 +71,7 @@ STATIC mp_obj_t pyb_sd_deinit (mp_obj_t self_in);
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
-/// Initalizes the sd card hardware driver
+/// Initializes the sd card hardware driver
STATIC void pyb_sd_hw_init (pybsd_obj_t *self) {
if (self->pin_clk) {
// Configure the clock pin as output only
@@ -212,9 +212,10 @@ STATIC const mp_rom_map_elem_t pyb_sd_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_sd_locals_dict, pyb_sd_locals_dict_table);
-const mp_obj_type_t pyb_sd_type = {
- { &mp_type_type },
- .name = MP_QSTR_SD,
- .make_new = pyb_sd_make_new,
- .locals_dict = (mp_obj_t)&pyb_sd_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_sd_type,
+ MP_QSTR_SD,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_sd_make_new,
+ locals_dict, &pyb_sd_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c
index 2d4b1ca8a9600..ea2642c260942 100644
--- a/ports/cc3200/mods/pybsleep.c
+++ b/ports/cc3200/mods/pybsleep.c
@@ -125,10 +125,11 @@ STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL};
volatile arm_cm4_core_regs_t vault_arm_registers;
STATIC pybsleep_reset_cause_t pybsleep_reset_cause = PYB_SLP_PWRON_RESET;
STATIC pybsleep_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON;
-STATIC const mp_obj_type_t pyb_sleep_type = {
- { &mp_type_type },
- .name = MP_QSTR_sleep,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_sleep_type,
+ MP_QSTR_sleep,
+ MP_TYPE_FLAG_NONE
+ );
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -159,13 +160,13 @@ void pyb_sleep_init0 (void) {
// register and enable the PRCM interrupt
osi_InterruptRegister(INT_PRCM, (P_OSI_INTR_ENTRY)PRCMInterruptHandler, INT_PRIORITY_LVL_1);
- // disable all LPDS and hibernate wake up sources (WLAN is disabed/enabled before entering LDPS mode)
+ // disable all LPDS and hibernate wake up sources (WLAN is disabled/enabled before entering LDPS mode)
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_GPIO);
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
MAP_PRCMHibernateWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR | PRCM_HIB_GPIO2 | PRCM_HIB_GPIO4 | PRCM_HIB_GPIO13 |
PRCM_HIB_GPIO17 | PRCM_HIB_GPIO11 | PRCM_HIB_GPIO24 | PRCM_HIB_GPIO26);
- // check the reset casue (if it's soft reset, leave it as it is)
+ // check the reset cause (if it's soft reset, leave it as it is)
if (pybsleep_reset_cause != PYB_SLP_SOFT_RESET) {
switch (MAP_PRCMSysResetCauseGet()) {
case PRCM_POWER_ON:
@@ -652,3 +653,4 @@ STATIC bool setup_timer_hibernate_wake (void) {
return false;
}
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_sleep_obj_list);
diff --git a/ports/cc3200/mods/pybspi.c b/ports/cc3200/mods/pybspi.c
index 61b1a6bd11eeb..61086ec2e1d84 100644
--- a/ports/cc3200/mods/pybspi.c
+++ b/ports/cc3200/mods/pybspi.c
@@ -305,7 +305,7 @@ STATIC mp_obj_t pyb_spi_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
// return the received data
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read);
@@ -377,10 +377,11 @@ STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
-const mp_obj_type_t pyb_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = pyb_spi_print,
- .make_new = pyb_spi_make_new,
- .locals_dict = (mp_obj_t)&pyb_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_spi_make_new,
+ print, pyb_spi_print,
+ locals_dict, &pyb_spi_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybtimer.c b/ports/cc3200/mods/pybtimer.c
index 55caa6de137b1..be365f3c92b26 100644
--- a/ports/cc3200/mods/pybtimer.c
+++ b/ports/cc3200/mods/pybtimer.c
@@ -459,13 +459,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
-const mp_obj_type_t pyb_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = pyb_timer_print,
- .make_new = pyb_timer_make_new,
- .locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_timer_make_new,
+ print, pyb_timer_print,
+ locals_dict, &pyb_timer_locals_dict
+ );
STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
.init = pyb_timer_channel_irq,
@@ -721,10 +722,12 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
-STATIC const mp_obj_type_t pyb_timer_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_TimerChannel,
- .print = pyb_timer_channel_print,
- .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_channel_type,
+ MP_QSTR_TimerChannel,
+ MP_TYPE_FLAG_NONE,
+ print, pyb_timer_channel_print,
+ locals_dict, &pyb_timer_channel_locals_dict
+ );
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_timer_channel_obj_list);
diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c
index b8e8cbb682fab..5d6ad075275d5 100644
--- a/ports/cc3200/mods/pybuart.c
+++ b/ports/cc3200/mods/pybuart.c
@@ -50,7 +50,7 @@
#include "pin.h"
#include "pybpin.h"
#include "pins.h"
-#include "moduos.h"
+#include "modos.h"
/// \moduleref pyb
/// \class UART - duplex serial communication bus
@@ -66,6 +66,7 @@
#define PYBUART_TX_MAX_TIMEOUT_MS (5)
#define PYBUART_RX_BUFFER_LEN (256)
+#define PYBUART_TX_BUFFER_LEN (17)
// interrupt triggers
#define UART_TRIGGER_RX_ANY (0x01)
@@ -558,6 +559,17 @@ STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (MAP_UARTBusy(self->reg) == false) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
// instance methods
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
@@ -565,6 +577,7 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_uart_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
/// \method read([nbytes])
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
@@ -574,6 +587,7 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
/// \method write(buf)
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
// class constants
{ MP_ROM_QSTR(MP_QSTR_RX_ANY), MP_ROM_INT(UART_TRIGGER_RX_ANY) },
@@ -635,6 +649,21 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
if ((flags & MP_STREAM_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint64_t timeout = mp_hal_ticks_ms() +
+ (PYBUART_TX_BUFFER_LEN) * 13000 * 2 / self->baudrate;
+
+ do {
+ if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (mp_hal_ticks_ms() < timeout);
+
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -656,13 +685,14 @@ STATIC const mp_irq_methods_t uart_irq_methods = {
.flags = uart_irq_flags
};
-const mp_obj_type_t pyb_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = pyb_uart_print,
- .make_new = pyb_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, pyb_uart_make_new,
+ print, pyb_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &pyb_uart_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_uart_objs[2]);
diff --git a/ports/cc3200/mods/pybwdt.c b/ports/cc3200/mods/pybwdt.c
index 8db096d6b5fcb..589f53cf1275d 100644
--- a/ports/cc3200/mods/pybwdt.c
+++ b/ports/cc3200/mods/pybwdt.c
@@ -150,10 +150,11 @@ STATIC const mp_rom_map_elem_t pybwdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pybwdt_locals_dict, pybwdt_locals_dict_table);
-const mp_obj_type_t pyb_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = pyb_wdt_make_new,
- .locals_dict = (mp_obj_t)&pybwdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_wdt_make_new,
+ locals_dict, &pybwdt_locals_dict
+ );
diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h
index 58ec80a9f5cf5..af10c63531ffa 100644
--- a/ports/cc3200/mpconfigport.h
+++ b/ports/cc3200/mpconfigport.h
@@ -71,13 +71,13 @@
#define MICROPY_FATFS_SYNC_T SemaphoreHandle_t
#define MICROPY_STREAMS_NON_BLOCK (1)
-#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
#define MICROPY_VFS (1)
#define MICROPY_VFS_FAT (1)
#define MICROPY_PY_ASYNC_AWAIT (0)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
+#define MICROPY_PY_BUILTINS_BYTES_HEX (1)
#define MICROPY_PY_BUILTINS_INPUT (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text
@@ -104,53 +104,40 @@
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (1)
-#define MICROPY_PY_IO_FILEIO (1)
-#define MICROPY_PY_UERRNO (1)
-#define MICROPY_PY_UERRNO_ERRORCODE (0)
+#define MICROPY_PY_ERRNO (1)
+#define MICROPY_PY_ERRNO_ERRORCODE (0)
#define MICROPY_PY_THREAD (1)
#define MICROPY_PY_THREAD_GIL (1)
-#define MICROPY_PY_UBINASCII (1)
+#define MICROPY_PY_BINASCII (1)
#define MICROPY_PY_UCTYPES (0)
-#define MICROPY_PY_UZLIB (0)
-#define MICROPY_PY_UJSON (1)
-#define MICROPY_PY_URE (1)
-#define MICROPY_PY_UHEAPQ (0)
-#define MICROPY_PY_UHASHLIB (0)
-#define MICROPY_PY_USELECT (1)
-#define MICROPY_PY_UTIME_MP_HAL (1)
+#define MICROPY_PY_ZLIB (0)
+#define MICROPY_PY_JSON (1)
+#define MICROPY_PY_RE (1)
+#define MICROPY_PY_HEAPQ (0)
+#define MICROPY_PY_HASHLIB (0)
+#define MICROPY_PY_SELECT (1)
+#define MICROPY_PY_TIME (1)
+#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
+#define MICROPY_PY_TIME_TIME_TIME_NS (1)
+#define MICROPY_PY_TIME_INCLUDEFILE "ports/cc3200/mods/modtime.c"
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
#define MICROPY_KBD_EXCEPTION (1)
-// We define our own list of errno constants to include in uerrno module
-#define MICROPY_PY_UERRNO_LIST \
+// We define our own list of errno constants to include in errno module
+#define MICROPY_PY_ERRNO_LIST \
X(EPERM) \
X(EIO) \
X(ENODEV) \
X(EINVAL) \
X(ETIMEDOUT) \
-// TODO these should be generic, not bound to fatfs
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-
// extra constants
#define MICROPY_PORT_CONSTANTS \
- { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \
+ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \
-// vm state and root pointers for the gc
#define MP_STATE_PORT MP_STATE_VM
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- mp_obj_t mp_const_user_interrupt; \
- mp_obj_t machine_config_main; \
- mp_obj_list_t pyb_sleep_obj_list; \
- mp_obj_list_t mp_irq_obj_list; \
- 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; \
-
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
diff --git a/ports/cc3200/mptask.c b/ports/cc3200/mptask.c
index 81f00e5384f0b..abf8484b0d42a 100644
--- a/ports/cc3200/mptask.c
+++ b/ports/cc3200/mptask.c
@@ -55,7 +55,7 @@
#include "mperror.h"
#include "simplelink.h"
#include "modnetwork.h"
-#include "modusocket.h"
+#include "modsocket.h"
#include "modwlan.h"
#include "serverstask.h"
#include "telnet.h"
@@ -70,7 +70,7 @@
#include "cryptohash.h"
#include "mpirq.h"
#include "updater.h"
-#include "moduos.h"
+#include "modos.h"
#include "antenna.h"
#include "task.h"
@@ -158,7 +158,7 @@ void TASK_MicroPython(void *pvParameters) {
// to enable simplelink and leave it as is
wlan_first_start();
} else {
- // only if not comming out of hibernate or a soft reset
+ // only if not coming out of hibernate or a soft reset
mptask_enter_ap_mode();
}
@@ -315,7 +315,7 @@ STATIC void mptask_init_sflash_filesystem(void) {
// create empty main.py
mptask_create_main_py();
} else if (res == FR_OK) {
- // mount sucessful
+ // mount successful
if (FR_OK != f_stat(&vfs_fat->fatfs, "/main.py", &fno)) {
// create empty main.py
mptask_create_main_py();
diff --git a/ports/cc3200/serverstask.c b/ports/cc3200/serverstask.c
index 03eed8eeb0cf4..de782f5e7acd9 100644
--- a/ports/cc3200/serverstask.c
+++ b/ports/cc3200/serverstask.c
@@ -37,7 +37,7 @@
#include "telnet.h"
#include "ftp.h"
#include "pybwdt.h"
-#include "modusocket.h"
+#include "modsocket.h"
#include "modnetwork.h"
#include "modwlan.h"
@@ -111,7 +111,7 @@ void TASK_Servers(void *pvParameters) {
ftp_reset();
}
// and we should also close all user sockets. We do it here
- // for convinience and to save on code size.
+ // for convenience and to save on code size.
modusocket_close_all_user_sockets();
}
diff --git a/ports/cc3200/telnet/telnet.c b/ports/cc3200/telnet/telnet.c
index c4daac3426d1c..86843c78f6c9e 100644
--- a/ports/cc3200/telnet/telnet.c
+++ b/ports/cc3200/telnet/telnet.c
@@ -33,7 +33,7 @@
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
-#include "modusocket.h"
+#include "modsocket.h"
#include "debug.h"
#include "serverstask.h"
#include "genhdr/mpversion.h"
@@ -407,7 +407,7 @@ static void telnet_process (void) {
_i16 rxLen;
_i16 maxLen = (telnet_data.rxWindex >= telnet_data.rxRindex) ? (TELNET_RX_BUFFER_SIZE - telnet_data.rxWindex) :
((telnet_data.rxRindex - telnet_data.rxWindex) - 1);
- // to avoid an overrrun
+ // to avoid an overrun
maxLen = (telnet_data.rxRindex == 0) ? (maxLen - 1) : maxLen;
if (maxLen > 0) {
diff --git a/ports/cc3200/tools/uniflash.py b/ports/cc3200/tools/uniflash.py
index 0ce9d0703a799..83445a12d3438 100644
--- a/ports/cc3200/tools/uniflash.py
+++ b/ports/cc3200/tools/uniflash.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-"""
+r"""
Flash the WiPy (format, update service pack and program).
Example:
diff --git a/ports/cc3200/tools/update-wipy.py b/ports/cc3200/tools/update-wipy.py
index e0e1266f7a376..7f5527a52bb5f 100644
--- a/ports/cc3200/tools/update-wipy.py
+++ b/ports/cc3200/tools/update-wipy.py
@@ -45,7 +45,7 @@ def transfer_file(args):
if "250" in ftp.cwd("/flash"):
if not ftp_directory_exists(ftp, "sys"):
print("/flash/sys directory does not exist")
- if not "550" in ftp.mkd("sys"):
+ if "550" not in ftp.mkd("sys"):
print("/flash/sys directory created")
else:
print("Error: cannot create /flash/sys directory")
@@ -109,7 +109,7 @@ def reset_board(args):
finally:
try:
tn.close()
- except Exception as e:
+ except Exception:
pass
return success
@@ -167,7 +167,7 @@ def find_tag(tag):
finally:
try:
tn.close()
- except Exception as e:
+ except Exception:
pass
return success
diff --git a/ports/cc3200/util/cryptohash.c b/ports/cc3200/util/cryptohash.c
index 909dadc8cf401..ebf12e6e36fe8 100644
--- a/ports/cc3200/util/cryptohash.c
+++ b/ports/cc3200/util/cryptohash.c
@@ -59,7 +59,7 @@ void CRYPTOHASH_SHAMD5Start (uint32_t algo, uint32_t blocklen) {
HWREG(SHAMD5_BASE + SHAMD5_O_MODE) |= SHAMD5_MODE_CLOSE_HASH;
}
- // set the lenght
+ // set the length
HWREG(SHAMD5_BASE + SHAMD5_O_LENGTH) = blocklen;
}
diff --git a/ports/embed/README.md b/ports/embed/README.md
new file mode 100644
index 0000000000000..556cfc749d371
--- /dev/null
+++ b/ports/embed/README.md
@@ -0,0 +1,18 @@
+MicroPython embed port
+======================
+
+This is a port of MicroPython that outputs a set of .c and .h files for embedding
+into a wider project. This port essentially targets the C language, instead of a
+particular hardware architecture or platform.
+
+To use this port in a project there are three main steps:
+
+1. Provide configuration for the project via an `mpconfigport.h` file.
+
+2. Build this embed port against that configuration, using the provided `embed.mk`.
+ The output is a set of self-contained source files for building MicroPython.
+ These files can be placed outside this repository.
+
+3. Build the project. This requires compiling all .c files from the above step.
+
+See `examples/embedding` for an example.
diff --git a/ports/embed/embed.mk b/ports/embed/embed.mk
new file mode 100644
index 0000000000000..84d45accd2d71
--- /dev/null
+++ b/ports/embed/embed.mk
@@ -0,0 +1,65 @@
+# This file is part of the MicroPython project, http://micropython.org/
+# The MIT License (MIT)
+# Copyright (c) 2022-2023 Damien P. George
+#
+# This file is intended to be included by a Makefile in a custom project.
+
+# Set the build output directory for the generated files.
+BUILD = build-embed
+
+# Include the core environment definitions; this will set $(TOP).
+include $(MICROPYTHON_TOP)/py/mkenv.mk
+
+# Include py core make definitions.
+include $(TOP)/py/py.mk
+
+# Set the location of the MicroPython embed port.
+MICROPYTHON_EMBED_PORT = $(MICROPYTHON_TOP)/ports/embed
+
+# Set default makefile-level MicroPython feature configurations.
+MICROPY_ROM_TEXT_COMPRESSION ?= 0
+
+# Set CFLAGS for the MicroPython build.
+CFLAGS += -I. -I$(TOP) -I$(BUILD) -I$(MICROPYTHON_EMBED_PORT)
+CFLAGS += -Wall -Werror -std=c99
+
+# Define the required generated header files.
+GENHDR_OUTPUT = $(addprefix $(BUILD)/genhdr/, \
+ moduledefs.h \
+ mpversion.h \
+ qstrdefs.generated.h \
+ root_pointers.h \
+ )
+
+# Define the top-level target, the generated output files.
+.PHONY: all
+all: micropython-embed-package
+
+clean: clean-micropython-embed-package
+
+.PHONY: clean-micropython-embed-package
+clean-micropython-embed-package:
+ $(RM) -rf $(PACKAGE_DIR)
+
+PACKAGE_DIR ?= micropython_embed
+PACKAGE_DIR_LIST = $(addprefix $(PACKAGE_DIR)/,py extmod shared/runtime genhdr port)
+
+.PHONY: micropython-embed-package
+micropython-embed-package: $(GENHDR_OUTPUT)
+ $(ECHO) "Generate micropython_embed output:"
+ $(Q)$(RM) -rf $(PACKAGE_DIR_LIST)
+ $(Q)$(MKDIR) -p $(PACKAGE_DIR_LIST)
+ $(ECHO) "- py"
+ $(Q)$(CP) $(TOP)/py/*.[ch] $(PACKAGE_DIR)/py
+ $(ECHO) "- extmod"
+ $(Q)$(CP) $(TOP)/extmod/modplatform.h $(PACKAGE_DIR)/extmod
+ $(ECHO) "- shared"
+ $(Q)$(CP) $(TOP)/shared/runtime/gchelper.h $(PACKAGE_DIR)/shared/runtime
+ $(Q)$(CP) $(TOP)/shared/runtime/gchelper_generic.c $(PACKAGE_DIR)/shared/runtime
+ $(ECHO) "- genhdr"
+ $(Q)$(CP) $(GENHDR_OUTPUT) $(PACKAGE_DIR)/genhdr
+ $(ECHO) "- port"
+ $(Q)$(CP) $(MICROPYTHON_EMBED_PORT)/port/*.[ch] $(PACKAGE_DIR)/port
+
+# Include remaining core make rules.
+include $(TOP)/py/mkrules.mk
diff --git a/ports/embed/port/embed_util.c b/ports/embed/port/embed_util.c
new file mode 100644
index 0000000000000..14f50897705e8
--- /dev/null
+++ b/ports/embed/port/embed_util.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-2023 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 "py/compile.h"
+#include "py/gc.h"
+#include "py/persistentcode.h"
+#include "py/runtime.h"
+#include "py/stackctrl.h"
+#include "shared/runtime/gchelper.h"
+#include "port/micropython_embed.h"
+
+// Initialise the runtime.
+void mp_embed_init(void *gc_heap, size_t gc_heap_size) {
+ mp_stack_ctrl_init();
+ gc_init(gc_heap, (uint8_t *)gc_heap + gc_heap_size);
+ mp_init();
+}
+
+#if MICROPY_ENABLE_COMPILER
+// Compile and execute the given source script (Python text).
+void mp_embed_exec_str(const char *src) {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ // Compile, parse and execute the given string.
+ mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
+ qstr source_name = lex->source_name;
+ mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT);
+ mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true);
+ mp_call_function_0(module_fun);
+ nlr_pop();
+ } else {
+ // Uncaught exception: print it out.
+ mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
+ }
+}
+#endif
+
+#if MICROPY_PERSISTENT_CODE_LOAD
+void mp_embed_exec_mpy(const uint8_t *mpy, size_t len) {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ // Execute the given .mpy data.
+ mp_module_context_t *ctx = m_new_obj(mp_module_context_t);
+ ctx->module.globals = mp_globals_get();
+ mp_compiled_module_t cm;
+ cm.context = ctx;
+ mp_raw_code_load_mem(mpy, len, &cm);
+ mp_obj_t f = mp_make_function_from_raw_code(cm.rc, ctx, MP_OBJ_NULL);
+ mp_call_function_0(f);
+ nlr_pop();
+ } else {
+ // Uncaught exception: print it out.
+ mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
+ }
+}
+#endif
+
+// Deinitialise the runtime.
+void mp_embed_deinit(void) {
+ mp_deinit();
+}
+
+#if MICROPY_ENABLE_GC
+// Run a garbage collection cycle.
+void gc_collect(void) {
+ gc_collect_start();
+ gc_helper_collect_regs_and_stack();
+ gc_collect_end();
+}
+#endif
+
+// Called if an exception is raised outside all C exception-catching handlers.
+void nlr_jump_fail(void *val) {
+ for (;;) {
+ }
+}
+
+#ifndef NDEBUG
+// Used when debugging is enabled.
+void __assert_func(const char *file, int line, const char *func, const char *expr) {
+ for (;;) {
+ }
+}
+#endif
diff --git a/ports/embed/port/micropython_embed.h b/ports/embed/port/micropython_embed.h
new file mode 100644
index 0000000000000..bf55d9b2b4454
--- /dev/null
+++ b/ports/embed/port/micropython_embed.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-2023 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_MICROPYTHON_EMBED_H
+#define MICROPY_INCLUDED_MICROPYTHON_EMBED_H
+
+#include
+#include
+
+void mp_embed_init(void *gc_heap, size_t gc_heap_size);
+void mp_embed_deinit(void);
+
+// Only available if MICROPY_ENABLE_COMPILER is enabled.
+void mp_embed_exec_str(const char *src);
+
+// Only available if MICROPY_PERSISTENT_CODE_LOAD is enabled.
+void mp_embed_exec_mpy(const uint8_t *mpy, size_t len);
+
+#endif // MICROPY_INCLUDED_MICROPYTHON_EMBED_H
diff --git a/ports/embed/port/mpconfigport_common.h b/ports/embed/port/mpconfigport_common.h
new file mode 100644
index 0000000000000..69216a7582681
--- /dev/null
+++ b/ports/embed/port/mpconfigport_common.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-2023 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
+
+// Type definitions for the specific machine
+
+typedef intptr_t mp_int_t; // must be pointer size
+typedef uintptr_t mp_uint_t; // must be pointer size
+typedef long mp_off_t;
+
+// Need to provide a declaration/definition of alloca()
+#include
+
+#define MICROPY_MPHALPORT_H "port/mphalport.h"
diff --git a/ports/embed/port/mphalport.c b/ports/embed/port/mphalport.c
new file mode 100644
index 0000000000000..8e76a8e22e1b0
--- /dev/null
+++ b/ports/embed/port/mphalport.c
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-2023 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 "py/mphal.h"
+
+// Send string of given length to stdout, converting \n to \r\n.
+void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
+ printf("%.*s", (int)len, str);
+}
diff --git a/ports/embed/port/mphalport.h b/ports/embed/port/mphalport.h
new file mode 100644
index 0000000000000..49928e154da36
--- /dev/null
+++ b/ports/embed/port/mphalport.h
@@ -0,0 +1,2 @@
+// Define so there's no dependency on extmod/virtpin.h
+#define mp_hal_pin_obj_t
diff --git a/ports/esp32/.gitignore b/ports/esp32/.gitignore
new file mode 100644
index 0000000000000..a78ecd0191c9f
--- /dev/null
+++ b/ports/esp32/.gitignore
@@ -0,0 +1,2 @@
+dependencies.lock
+managed_components/
diff --git a/ports/esp32/CMakeLists.txt b/ports/esp32/CMakeLists.txt
index 7209dd96da4ae..4e29e96109457 100644
--- a/ports/esp32/CMakeLists.txt
+++ b/ports/esp32/CMakeLists.txt
@@ -2,9 +2,6 @@
cmake_minimum_required(VERSION 3.12)
-# Set the location of this port's directory.
-set(MICROPY_PORT_DIR ${CMAKE_SOURCE_DIR})
-
# Set the board if it's not already set.
if(NOT MICROPY_BOARD)
set(MICROPY_BOARD GENERIC)
@@ -12,22 +9,21 @@ endif()
# Set the board directory and check that it exists.
if(NOT MICROPY_BOARD_DIR)
- set(MICROPY_BOARD_DIR ${MICROPY_PORT_DIR}/boards/${MICROPY_BOARD})
+ set(MICROPY_BOARD_DIR ${CMAKE_CURRENT_LIST_DIR}/boards/${MICROPY_BOARD})
endif()
if(NOT EXISTS ${MICROPY_BOARD_DIR}/mpconfigboard.cmake)
message(FATAL_ERROR "Invalid MICROPY_BOARD specified: ${MICROPY_BOARD}")
endif()
-# Include main IDF cmake file.
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-
# Define the output sdkconfig so it goes in the build directory.
set(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig)
# Save the manifest file set from the cmake command line.
set(MICROPY_USER_FROZEN_MANIFEST ${MICROPY_FROZEN_MANIFEST})
-# Include board config; this is expected to set SDKCONFIG_DEFAULTS (among other options).
+# Include board config; this is expected to set (among other options):
+# - SDKCONFIG_DEFAULTS
+# - IDF_TARGET
include(${MICROPY_BOARD_DIR}/mpconfigboard.cmake)
# Set the frozen manifest file. Note if MICROPY_FROZEN_MANIFEST is set from the cmake
@@ -35,14 +31,7 @@ include(${MICROPY_BOARD_DIR}/mpconfigboard.cmake)
if (MICROPY_USER_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_USER_FROZEN_MANIFEST})
elseif (NOT MICROPY_FROZEN_MANIFEST)
- set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
-endif()
-
-# Add sdkconfig fragments that depend on the IDF version.
-if(IDF_VERSION_MAJOR EQUAL 4 AND IDF_VERSION_MINOR LESS 2)
- set(SDKCONFIG_DEFAULTS ${SDKCONFIG_DEFAULTS} boards/sdkconfig.nimble_core0)
-else()
- set(SDKCONFIG_DEFAULTS ${SDKCONFIG_DEFAULTS} boards/sdkconfig.nimble_core1)
+ set(MICROPY_FROZEN_MANIFEST ${CMAKE_CURRENT_LIST_DIR}/boards/manifest.py)
endif()
# Concatenate all sdkconfig files into a combined one for the IDF to use.
@@ -54,5 +43,11 @@ endforeach()
configure_file(${CMAKE_BINARY_DIR}/sdkconfig.combined.in ${CMAKE_BINARY_DIR}/sdkconfig.combined COPYONLY)
set(SDKCONFIG_DEFAULTS ${CMAKE_BINARY_DIR}/sdkconfig.combined)
+# Include main IDF cmake file.
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+
+# Set the location of the main component for the project (one per target).
+list(APPEND EXTRA_COMPONENT_DIRS main_${IDF_TARGET})
+
# Define the project.
project(micropython)
diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile
index c8ca9262c8f16..7c8c225dfb6e9 100644
--- a/ports/esp32/Makefile
+++ b/ports/esp32/Makefile
@@ -2,8 +2,20 @@
#
# This is a simple, convenience wrapper around idf.py (which uses cmake).
-# Select the board to build for, defaulting to GENERIC.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to GENERIC.
BOARD ?= GENERIC
+BOARD_DIR ?= boards/$(BOARD)
+endif
+
+ifeq ($(wildcard $(BOARD_DIR)/.),)
+$(error Invalid BOARD specified: $(BOARD_DIR))
+endif
# If the build directory is not given, make it reflect the board name.
BUILD ?= build-$(BOARD)
@@ -14,7 +26,11 @@ BAUD ?= 460800
PYTHON ?= python3
-GIT_SUBMODULES = lib/berkeley-db-1.xx
+# Would be good to use cmake to discover submodules (see how rp2/Makefile does
+# it), but on ESP32 the same trick doesn't work because "idf.py build" fails
+# on berkeley-db dependency before printing out the submodule list.
+# For now just force the submodule dependencies here.
+GIT_SUBMODULES += lib/berkeley-db-1.xx lib/micropython-lib
.PHONY: all clean deploy erase submodules FORCE
@@ -24,14 +40,20 @@ ifdef USER_C_MODULES
CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES}
endif
-IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -B $(BUILD) $(CMAKE_ARGS)
+IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -D MICROPY_BOARD_DIR=$(abspath $(BOARD_DIR)) -B $(BUILD) $(CMAKE_ARGS)
ifdef FROZEN_MANIFEST
IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST)
endif
+HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m"
+
+define RUN_IDF_PY
+ idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) $(1)
+endef
+
all:
- idf.py $(IDFPY_FLAGS) build
+ idf.py $(IDFPY_FLAGS) build || (echo -e $(HELP_BUILD_ERROR); false)
@$(PYTHON) makeimg.py \
$(BUILD)/sdkconfig \
$(BUILD)/bootloader/bootloader.bin \
@@ -43,13 +65,25 @@ all:
$(BUILD)/bootloader/bootloader.bin $(BUILD)/partition_table/partition-table.bin $(BUILD)/micropython.bin: FORCE
clean:
- idf.py $(IDFPY_FLAGS) fullclean
+ $(call RUN_IDF_PY,fullclean)
deploy:
- idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) flash
+ $(call RUN_IDF_PY,flash)
erase:
- idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) erase_flash
+ $(call RUN_IDF_PY,erase-flash)
+
+monitor:
+ $(call RUN_IDF_PY,monitor)
+
+size:
+ $(call RUN_IDF_PY,size)
+
+size-components:
+ $(call RUN_IDF_PY,size-components)
+
+size-files:
+ $(call RUN_IDF_PY,size-files)
submodules:
- git submodule update --init $(addprefix ../../,$(GIT_SUBMODULES))
+ $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules
diff --git a/ports/esp32/README.md b/ports/esp32/README.md
index c37213b303109..dc9e9f8b723ac 100644
--- a/ports/esp32/README.md
+++ b/ports/esp32/README.md
@@ -22,13 +22,13 @@ Initial development of this ESP32 port was sponsored in part by Microbric Pty Lt
Setting up ESP-IDF and the build environment
--------------------------------------------
-MicroPython on ESP32 requires the Espressif IDF version 4 (IoT development
+MicroPython on ESP32 requires the Espressif IDF version 5 (IoT development
framework, aka SDK). The ESP-IDF includes the libraries and RTOS needed to
manage the ESP32 microcontroller, as well as a way to manage the required
build environment and toolchains needed to build the firmware.
The ESP-IDF changes quickly and MicroPython only supports certain versions.
-Currently MicroPython supports v4.0.2, v4.1.1, v4.2.2, v4.3.2 and v4.4,
+Currently MicroPython supports v5.0.2,
although other IDF v4 versions may also work.
To install the ESP-IDF the full instructions can be found at the
@@ -47,10 +47,10 @@ The steps to take are summarised below.
To check out a copy of the IDF use git clone:
```bash
-$ git clone -b v4.0.2 --recursive https://github.com/espressif/esp-idf.git
+$ git clone -b v5.0.2 --recursive https://github.com/espressif/esp-idf.git
```
-You can replace `v4.0.2` with `v4.2.2` or `v4.4` or any other supported version.
+You can replace `v5.0.2` with any other supported version.
(You don't need a full recursive clone; see the `ci_esp32_setup` function in
`tools/ci.sh` in this repository for more detailed set-up commands.)
@@ -59,7 +59,7 @@ MicroPython and update the submodules using:
```bash
$ cd esp-idf
-$ git checkout v4.2
+$ git checkout v5.0.2
$ git submodule update --init --recursive
```
@@ -75,11 +75,6 @@ $ source export.sh # (or export.bat on Windows)
The `install.sh` step only needs to be done once. You will need to source
`export.sh` for every new session.
-**Note:** If you are building MicroPython for the ESP32-S2, ESP32-C3 or ESP32-S3,
-please ensure you are using the following required IDF versions:
-- ESP32-S3 currently requires `v4.4` or later.
-- ESP32-S2 and ESP32-C3 require `v4.3.1` or later.
-
Building the firmware
---------------------
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/board.json b/ports/esp32/boards/ARDUINO_NANO_ESP32/board.json
new file mode 100644
index 0000000000000..031ee17415b6c
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/board.json
@@ -0,0 +1,20 @@
+{
+ "deploy": [
+ "../deploy_s3.md"
+ ],
+ "docs": "",
+ "features": [
+ "BLE",
+ "WiFi",
+ "USB-C",
+ "RGB LED"
+ ],
+ "images": [
+ "ABX00092_01.iso_1000x750.jpg"
+ ],
+ "mcu": "esp32s3",
+ "product": "Arduino Nano ESP32",
+ "thumbnail": "",
+ "url": "https://store.arduino.cc/products/arduino-nano-esp32",
+ "vendor": "Arduino"
+}
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/board_init.c b/ports/esp32/boards/ARDUINO_NANO_ESP32/board_init.c
new file mode 100644
index 0000000000000..ab03139d9055f
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/board_init.c
@@ -0,0 +1,124 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Arduino SA
+ *
+ * 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 "py/mphal.h"
+
+#include
+#include
+#include
+
+#include "double_tap.h"
+#include "usb.h"
+
+#include "tinyusb.h"
+#include "tusb_cdc_acm.h"
+
+#define LED_RED GPIO_NUM_46
+#define LED_GREEN GPIO_NUM_0
+#define LED_BLUE GPIO_NUM_45
+#define DELAY_US 60000
+
+static bool _recovery_marker_found; // double tap detected
+static bool _recovery_active; // running from factory partition
+
+static void rgb_pulse_delay() {
+ // initialize RGB signals from weak pinstraps
+ mp_hal_pin_output(LED_RED);
+ mp_hal_pin_output(LED_GREEN);
+ mp_hal_pin_output(LED_BLUE);
+
+ static const uint8_t SEQ[] = { 1, 3, 2, 6, 7, 5, 4, 5, 7, 6, 2, 3, 1 };
+ for (int idx = 0; idx < sizeof(SEQ); ++idx) {
+ int v = SEQ[idx & 7];
+ mp_hal_pin_write(LED_RED, !(v & 1));
+ mp_hal_pin_write(LED_GREEN, !(v & 2));
+ mp_hal_pin_write(LED_BLUE, !(v & 4));
+
+ // busy wait, we can't use task delay yet
+ mp_hal_delay_us_fast(DELAY_US);
+ }
+
+ // reset pins to digital HIGH before leaving
+ mp_hal_pin_write(LED_RED, 1);
+ mp_hal_pin_write(LED_GREEN, 1);
+ mp_hal_pin_write(LED_BLUE, 1);
+}
+
+void NANO_ESP32_enter_bootloader(void) {
+ if (!_recovery_active) {
+ // check for valid partition scheme
+ const esp_partition_t *ota_part = esp_ota_get_next_update_partition(NULL);
+ const esp_partition_t *fact_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
+ if (ota_part && fact_part) {
+ // set tokens so the recovery FW will find them
+ double_tap_mark();
+ // invalidate other OTA image
+ esp_partition_erase_range(ota_part, 0, 4096);
+ // activate factory partition
+ esp_ota_set_boot_partition(fact_part);
+ }
+ }
+
+ esp_restart();
+}
+
+void NANO_ESP32_usb_callback_line_state_changed(int itf, void *event_in) {
+ extern void mp_usbd_line_state_cb(uint8_t itf, bool dtr, bool rts);
+ cdcacm_event_t *event = event_in;
+ mp_usbd_line_state_cb(itf, event->line_state_changed_data.dtr, event->line_state_changed_data.rts);
+}
+
+void NANO_ESP32_board_startup(void) {
+ boardctrl_startup();
+
+ // mark current partition as valid
+ const esp_partition_t *running = esp_ota_get_running_partition();
+ esp_ota_img_states_t ota_state;
+ if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
+ if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
+ esp_ota_mark_app_valid_cancel_rollback();
+ }
+ }
+
+ const esp_partition_t *part = esp_ota_get_running_partition();
+ _recovery_active = (part->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY);
+
+ double_tap_init();
+
+ _recovery_marker_found = double_tap_check_match();
+ if (_recovery_marker_found && !_recovery_active) {
+ // double tap detected in user application, reboot to factory
+ NANO_ESP32_enter_bootloader();
+ }
+
+ // delay with mark set then proceed
+ // - for normal startup, to detect first double tap
+ // - in recovery mode, to ignore several short presses
+ double_tap_mark();
+ rgb_pulse_delay();
+ double_tap_invalidate();
+}
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/deploy.md b/ports/esp32/boards/ARDUINO_NANO_ESP32/deploy.md
new file mode 100644
index 0000000000000..b600a55b64e2b
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/deploy.md
@@ -0,0 +1,8 @@
+### Via dfu-util
+
+This board can programmed via DFU bootloader, using e.g. [dfu-util](http://dfu-util.sourceforge.net/).
+To enter the DFU bootloader, double tap the reset (blue) button, or you can use `machine.bootloader()` from the MicroPython REPL.
+
+```bash
+dfu-util -d 0x2341:0x0070 -R -D build-ARDUINO_NANO_ESP32/micropython.bin
+```
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/double_tap.c b/ports/esp32/boards/ARDUINO_NANO_ESP32/double_tap.c
new file mode 100644
index 0000000000000..8f50a32722711
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/double_tap.c
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Arduino SA
+ *
+ * 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 "py/mphal.h"
+
+#include
+
+// for get_extram_data_high()
+#include
+#include
+
+#include "double_tap.h"
+
+#define NUM_TOKENS 3
+static const uint32_t MAGIC_TOKENS[NUM_TOKENS] = {
+ 0xf01681de, 0xbd729b29, 0xd359be7a,
+};
+
+static void *magic_area;
+static uint32_t backup_area[NUM_TOKENS];
+
+// Current IDF does not map external RAM to a fixed address.
+// The actual VMA depends on other enabled devices, so the precise
+// location must be discovered.
+static uintptr_t get_extram_data_high(void) {
+ // get a pointer into SRAM area (only the address is useful)
+ void *psram_ptr = heap_caps_malloc(16, MALLOC_CAP_SPIRAM);
+ heap_caps_free(psram_ptr);
+
+ // keep moving backwards until leaving PSRAM area
+ uintptr_t psram_base_addr = (uintptr_t)psram_ptr;
+ psram_base_addr &= ~(CONFIG_MMU_PAGE_SIZE - 1); // align to start of page
+ while (esp_psram_check_ptr_addr((void *)psram_base_addr)) {
+ psram_base_addr -= CONFIG_MMU_PAGE_SIZE;
+ }
+
+ // offset is one page from start of PSRAM
+ return psram_base_addr + CONFIG_MMU_PAGE_SIZE + esp_psram_get_size();
+}
+
+void double_tap_init(void) {
+ // magic location block ends 0x20 bytes from end of PSRAM
+ magic_area = (void *)(get_extram_data_high() - 0x20 - sizeof(MAGIC_TOKENS));
+}
+
+void double_tap_mark() {
+ memcpy(backup_area, magic_area, sizeof(MAGIC_TOKENS));
+ memcpy(magic_area, MAGIC_TOKENS, sizeof(MAGIC_TOKENS));
+ Cache_WriteBack_Addr((uintptr_t)magic_area, sizeof(MAGIC_TOKENS));
+}
+
+void double_tap_invalidate() {
+ if (memcmp(backup_area, MAGIC_TOKENS, sizeof(MAGIC_TOKENS))) {
+ // different contents: restore backup
+ memcpy(magic_area, backup_area, sizeof(MAGIC_TOKENS));
+ } else {
+ // clear memory
+ memset(magic_area, 0, sizeof(MAGIC_TOKENS));
+ }
+ Cache_WriteBack_Addr((uintptr_t)magic_area, sizeof(MAGIC_TOKENS));
+}
+
+bool double_tap_check_match() {
+ return memcmp(magic_area, MAGIC_TOKENS, sizeof(MAGIC_TOKENS)) == 0;
+}
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/double_tap.h b/ports/esp32/boards/ARDUINO_NANO_ESP32/double_tap.h
new file mode 100644
index 0000000000000..9aa738f2d9f88
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/double_tap.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Arduino SA
+ *
+ * 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_ESP32_DOUBLE_TAP_H
+#define MICROPY_INCLUDED_ESP32_DOUBLE_TAP_H
+
+#include
+
+void double_tap_init(void);
+void double_tap_mark(void);
+void double_tap_invalidate(void);
+bool double_tap_check_match(void);
+
+#endif /* MICROPY_INCLUDED_ESP32_DOUBLE_TAP_H */
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/manifest.py b/ports/esp32/boards/ARDUINO_NANO_ESP32/manifest.py
new file mode 100644
index 0000000000000..e7fc7fe1619f9
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/manifest.py
@@ -0,0 +1,9 @@
+include("$(PORT_DIR)/boards/manifest.py")
+
+# Utils
+require("time")
+require("senml")
+require("logging")
+
+# Bluetooth
+require("aioble")
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake b/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake
new file mode 100644
index 0000000000000..7ae4b38185353
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake
@@ -0,0 +1,23 @@
+if(NOT MICROPY_DIR)
+ get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../.. ABSOLUTE)
+endif()
+
+set(IDF_TARGET esp32s3)
+
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.usb
+ boards/sdkconfig.ble
+ boards/sdkconfig.240mhz
+ boards/sdkconfig.spiram_sx
+ boards/sdkconfig.spiram_oct
+ ${MICROPY_BOARD_DIR}/sdkconfig.board
+)
+
+set(MICROPY_SOURCE_BOARD
+ ${MICROPY_BOARD_DIR}/board_init.c
+ ${MICROPY_BOARD_DIR}/double_tap.c
+ ${MICROPY_DIR}/shared/tinyusb/mp_cdc_common.c
+)
+
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h b/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h
new file mode 100644
index 0000000000000..3e98bb99d7027
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.h
@@ -0,0 +1,32 @@
+#define MICROPY_HW_BOARD_NAME "Arduino Nano ESP32"
+#define MICROPY_HW_MCU_NAME "ESP32S3"
+
+#define MICROPY_PY_MACHINE_DAC (0)
+
+#define MICROPY_HW_I2C0_SCL (12)
+#define MICROPY_HW_I2C0_SDA (11)
+
+#define MICROPY_HW_I2C1_SCL (8)
+#define MICROPY_HW_I2C1_SDA (9)
+
+#define MICROPY_HW_SPI1_MOSI (38)
+#define MICROPY_HW_SPI1_MISO (47)
+#define MICROPY_HW_SPI1_SCK (48)
+
+#define MICROPY_HW_SPI2_MOSI (10)
+#define MICROPY_HW_SPI2_MISO (17)
+#define MICROPY_HW_SPI2_SCK (18)
+
+#define MICROPY_HW_ENABLE_USBDEV (1)
+#define MICROPY_HW_USB_EXTERNAL_TINYUSB (1)
+#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
+#define MICROPY_SCHEDULER_STATIC_NODES (1)
+
+#define MICROPY_HW_USB_CUSTOM_LINE_STATE_CB NANO_ESP32_usb_callback_line_state_changed
+void NANO_ESP32_usb_callback_line_state_changed(int itf, void *event);
+
+#define MICROPY_BOARD_STARTUP NANO_ESP32_board_startup
+void NANO_ESP32_board_startup(void);
+
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) NANO_ESP32_enter_bootloader()
+void NANO_ESP32_enter_bootloader(void);
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/partitions-app3M_fat9M_fact512k_16MiB.csv b/ports/esp32/boards/ARDUINO_NANO_ESP32/partitions-app3M_fat9M_fact512k_16MiB.csv
new file mode 100644
index 0000000000000..13b4414b1d301
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/partitions-app3M_fat9M_fact512k_16MiB.csv
@@ -0,0 +1,10 @@
+# Notes: the offset of the partition table itself is set in
+# $IDF_PATH/components/partition_table/Kconfig.projbuild.
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x5000,
+otadata, data, ota, 0xe000, 0x2000,
+app0, app, ota_0, 0x10000, 0x300000,
+app1, app, ota_1, 0x310000, 0x300000,
+ffat, data, fat, 0x610000, 0x960000,
+factory, app, factory, 0xF70000, 0x80000,
+coredump, data, coredump, 0xFF0000, 0x10000,
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/pins.csv b/ports/esp32/boards/ARDUINO_NANO_ESP32/pins.csv
new file mode 100644
index 0000000000000..b891608d5d89c
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/pins.csv
@@ -0,0 +1,38 @@
+D0,GPIO44
+D1,GPIO43
+D2,GPIO5
+D3,GPIO6
+D4,GPIO7
+D5,GPIO8
+D6,GPIO9
+D7,GPIO10
+D8,GPIO17
+D9,GPIO18
+D10,GPIO21
+D11,GPIO38
+D12,GPIO47
+D13,GPIO48
+LED_RED,GPIO46
+LED_GREEN,GPIO0
+LED_BLUE,GPIO45
+A0,GPIO1
+A1,GPIO2
+A2,GPIO3
+A3,GPIO4
+A4,GPIO11
+A5,GPIO12
+A6,GPIO13
+A7,GPIO14
+LED_BUILTIN,GPIO48
+TX,GPIO43
+RX,GPIO44
+RTS,GPIO45
+CTS,GPIO6
+DTR,GPIO1
+DSR,GPIO7
+SS,GPIO21
+MOSI,GPIO38
+MISO,GPIO47
+SCK,GPIO48
+SDA,GPIO11
+SCL,GPIO12
diff --git a/ports/esp32/boards/ARDUINO_NANO_ESP32/sdkconfig.board b/ports/esp32/boards/ARDUINO_NANO_ESP32/sdkconfig.board
new file mode 100644
index 0000000000000..4d175f7ed77c7
--- /dev/null
+++ b/ports/esp32/boards/ARDUINO_NANO_ESP32/sdkconfig.board
@@ -0,0 +1,22 @@
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="boards/ARDUINO_NANO_ESP32/partitions-app3M_fat9M_fact512k_16MiB.csv"
+
+CONFIG_SPIRAM_TYPE_ESPPSRAM64=y
+CONFIG_SPIRAM_SPEED_80M=y
+CONFIG_SPIRAM_MEMTEST=
+CONFIG_SPIRAM_IGNORE_NOTFOUND=
+
+CONFIG_LWIP_LOCAL_HOSTNAME="nano-esp32"
+
+CONFIG_TINYUSB_DESC_CUSTOM_VID=0x2341
+CONFIG_TINYUSB_DESC_CUSTOM_PID=0x056B
+CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="Arduino"
+CONFIG_TINYUSB_DESC_PRODUCT_STRING="Nano ESP32"
+
+# compatibility with Espressif Arduino core
+CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y
+CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
+CONFIG_ESP_ENABLE_COREDUMP_TO_FLASH=y
diff --git a/ports/esp32/boards/ESP32_S2_WROVER/sdkconfig.board b/ports/esp32/boards/ESP32_S2_WROVER/sdkconfig.board
index 9373a522324db..40a8e3047ccef 100644
--- a/ports/esp32/boards/ESP32_S2_WROVER/sdkconfig.board
+++ b/ports/esp32/boards/ESP32_S2_WROVER/sdkconfig.board
@@ -1,6 +1,5 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
diff --git a/ports/esp32/boards/GENERIC_C3_USB/sdkconfig.board b/ports/esp32/boards/GENERIC_C3_USB/sdkconfig.board
index f0cbad00e4617..d9e7c7f61f620 100644
--- a/ports/esp32/boards/GENERIC_C3_USB/sdkconfig.board
+++ b/ports/esp32/boards/GENERIC_C3_USB/sdkconfig.board
@@ -1,9 +1,7 @@
CONFIG_ESP32C3_REV_MIN_3=y
-CONFIG_ESP32C3_REV_MIN=3
CONFIG_ESP32C3_BROWNOUT_DET=y
CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_7=
CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_4=y
CONFIG_ESP32C3_BROWNOUT_DET_LVL=4
CONFIG_ESP_CONSOLE_UART_DEFAULT=
-CONFIG_ESP_CONSOLE_USB_CDC=
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
diff --git a/ports/esp32/boards/GENERIC_D2WD/sdkconfig.board b/ports/esp32/boards/GENERIC_D2WD/sdkconfig.board
index 07e208a09ae7b..7b4313b7deef1 100644
--- a/ports/esp32/boards/GENERIC_D2WD/sdkconfig.board
+++ b/ports/esp32/boards/GENERIC_D2WD/sdkconfig.board
@@ -1,6 +1,7 @@
# Optimise using -Os to reduce size
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_COMPILER_OPTIMIZATION_PERF=n
+CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
diff --git a/ports/esp32/boards/GENERIC_OTA/sdkconfig.board b/ports/esp32/boards/GENERIC_OTA/sdkconfig.board
index d314860cc9378..7ff939aa991f2 100644
--- a/ports/esp32/boards/GENERIC_OTA/sdkconfig.board
+++ b/ports/esp32/boards/GENERIC_OTA/sdkconfig.board
@@ -1,3 +1,6 @@
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-ota.csv"
+
+# Reduce firmware size to fit in the OTA partition.
+CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
diff --git a/ports/esp32/boards/GENERIC_S3/sdkconfig.board b/ports/esp32/boards/GENERIC_S3/sdkconfig.board
index c9726d4232ed4..a36b971162850 100644
--- a/ports/esp32/boards/GENERIC_S3/sdkconfig.board
+++ b/ports/esp32/boards/GENERIC_S3/sdkconfig.board
@@ -1,10 +1,7 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
-CONFIG_SPIRAM_MEMTEST=
-
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
index b7351b90fe8e4..e0b92dcd2640d 100644
--- a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
@@ -3,6 +3,7 @@ set(IDF_TARGET esp32s3)
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.usb
+ boards/sdkconfig.ble
boards/sdkconfig.spiram_sx
boards/GENERIC_S3_SPIRAM/sdkconfig.board
)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
index f9126c98d76e3..1a8560a2d7ead 100644
--- a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
@@ -1,7 +1,6 @@
#define MICROPY_HW_BOARD_NAME "ESP32S3 module (spiram)"
#define MICROPY_HW_MCU_NAME "ESP32S3"
-#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_PY_MACHINE_DAC (0)
// Enable UART REPL for modules that have an external USB-UART and don't use native USB.
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board b/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board
index c9726d4232ed4..a36b971162850 100644
--- a/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board
@@ -1,10 +1,7 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
-CONFIG_SPIRAM_MEMTEST=
-
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json
new file mode 100644
index 0000000000000..f3ca177ef974a
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json
@@ -0,0 +1,18 @@
+{
+ "deploy": [
+ "../deploy_s3.md"
+ ],
+ "docs": "",
+ "features": [
+ "BLE",
+ "WiFi"
+ ],
+ "images": [
+ "generic_s3.jpg"
+ ],
+ "mcu": "esp32s3",
+ "product": "Generic ESP32-S3 (SPIRAM Octal)",
+ "thumbnail": "",
+ "url": "https://www.espressif.com/en/products/modules",
+ "vendor": "Espressif"
+}
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake
new file mode 100644
index 0000000000000..7a767c49d403f
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake
@@ -0,0 +1,11 @@
+set(IDF_TARGET esp32s3)
+
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.usb
+ boards/sdkconfig.ble
+ boards/sdkconfig.240mhz
+ boards/sdkconfig.spiram_sx
+ boards/sdkconfig.spiram_oct
+ boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board
+)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h
new file mode 100644
index 0000000000000..88f6835c94201
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h
@@ -0,0 +1,10 @@
+#define MICROPY_HW_BOARD_NAME "ESP32S3 module (spiram octal)"
+#define MICROPY_HW_MCU_NAME "ESP32S3"
+
+#define MICROPY_PY_MACHINE_DAC (0)
+
+// Enable UART REPL for modules that have an external USB-UART and don't use native USB.
+#define MICROPY_HW_ENABLE_UART_REPL (1)
+
+#define MICROPY_HW_I2C0_SCL (9)
+#define MICROPY_HW_I2C0_SDA (8)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board
new file mode 100644
index 0000000000000..a36b971162850
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board
@@ -0,0 +1,9 @@
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_AFTER_NORESET=y
+
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
+CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
+CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv"
diff --git a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.cmake
index dcffe5f01e7a0..2e1d799b93b1c 100644
--- a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.cmake
+++ b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.cmake
@@ -2,5 +2,4 @@ set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.ble
boards/sdkconfig.spiram
- boards/GENERIC_SPIRAM/sdkconfig.board
)
diff --git a/ports/esp32/boards/GENERIC_SPIRAM/sdkconfig.board b/ports/esp32/boards/GENERIC_SPIRAM/sdkconfig.board
deleted file mode 100644
index a2859acb5f906..0000000000000
--- a/ports/esp32/boards/GENERIC_SPIRAM/sdkconfig.board
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPIRAM increases the size of the firmware, use -Os to reduce it again to fit in iram
-CONFIG_COMPILER_OPTIMIZATION_SIZE=y
diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.json b/ports/esp32/boards/GENERIC_UNICORE/board.json
new file mode 100644
index 0000000000000..8fed71a018aa5
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/board.json
@@ -0,0 +1,19 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "BLE",
+ "WiFi"
+ ],
+ "id": "esp32-unicore",
+ "images": [
+ "generic_unicore.jpg"
+ ],
+ "mcu": "esp32",
+ "product": "ESP32 Unicore",
+ "thumbnail": "",
+ "url": "https://www.espressif.com/en/products/modules",
+ "vendor": "Espressif"
+}
diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.md b/ports/esp32/boards/GENERIC_UNICORE/board.md
new file mode 100644
index 0000000000000..b41c167498c73
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/board.md
@@ -0,0 +1 @@
+The following files are daily firmware for single-core ESP32-based boards without external SPIRAM.
diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake
new file mode 100644
index 0000000000000..2f34688c8c474
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake
@@ -0,0 +1,5 @@
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.ble
+ boards/GENERIC_UNICORE/sdkconfig.board
+)
diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h
new file mode 100644
index 0000000000000..5d0624b9c3f91
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h
@@ -0,0 +1,2 @@
+#define MICROPY_HW_BOARD_NAME "ESP32 Unicore module"
+#define MICROPY_HW_MCU_NAME "ESP32-UNICORE"
diff --git a/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board b/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board
new file mode 100644
index 0000000000000..f0b0b5e03dd48
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board
@@ -0,0 +1 @@
+CONFIG_FREERTOS_UNICORE=y
diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py
index 0709f8597c07c..e2cd6b3d01519 100644
--- a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py
+++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py
@@ -1,4 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
freeze("modules")
-
-freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
+require("ssd1306")
diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h b/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h
index 1c7b6fd557672..6be22dd0ffc40 100644
--- a/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h
+++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h
@@ -1,2 +1,3 @@
#define MICROPY_HW_BOARD_NAME "LILYGO TTGO LoRa32"
#define MICROPY_HW_MCU_NAME "ESP32"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-ttgo-lora32"
diff --git a/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h b/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h
index 5872bdc8ae5ef..12fd285da1753 100644
--- a/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h
+++ b/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "LOLIN_C3_MINI"
#define MICROPY_HW_MCU_NAME "ESP32-C3FH4"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-c3-mini"
#define MICROPY_HW_ENABLE_SDCARD (0)
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/LOLIN_C3_MINI/sdkconfig.board b/ports/esp32/boards/LOLIN_C3_MINI/sdkconfig.board
index f0cbad00e4617..d9e7c7f61f620 100644
--- a/ports/esp32/boards/LOLIN_C3_MINI/sdkconfig.board
+++ b/ports/esp32/boards/LOLIN_C3_MINI/sdkconfig.board
@@ -1,9 +1,7 @@
CONFIG_ESP32C3_REV_MIN_3=y
-CONFIG_ESP32C3_REV_MIN=3
CONFIG_ESP32C3_BROWNOUT_DET=y
CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_7=
CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_4=y
CONFIG_ESP32C3_BROWNOUT_DET_LVL=4
CONFIG_ESP_CONSOLE_UART_DEFAULT=
-CONFIG_ESP_CONSOLE_USB_CDC=
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
diff --git a/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h b/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h
index e0ef10d1db928..9776b7b478aa1 100644
--- a/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h
+++ b/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "LOLIN_S2_MINI"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-s2-mini"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board b/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board
index 1a7ef3f8b92ad..cbb3ad06d9a1b 100644
--- a/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board
+++ b/ports/esp32/boards/LOLIN_S2_MINI/sdkconfig.board
@@ -1,4 +1,4 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_USB_AND_UART=y
# LWIP
diff --git a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py
index 98d4247c607a9..9ac8ade8275bf 100644
--- a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py
+++ b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py
@@ -1,4 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
freeze("./modules")
-
-freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
+require("ssd1306")
diff --git a/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h b/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h
index 549dd9847c7f3..9241280dec6a3 100644
--- a/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h
+++ b/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "LOLIN_S2_PICO"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-s2-pico"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board b/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board
index bf0f3e780e4d6..eadff2f1b90b0 100644
--- a/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board
+++ b/ports/esp32/boards/LOLIN_S2_PICO/sdkconfig.board
@@ -1,4 +1,4 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_USB_AND_UART=y
# LWIP
diff --git a/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h b/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h
index 4270b19caf966..18a59b15a50a6 100644
--- a/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h
+++ b/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h
@@ -1,2 +1,3 @@
#define MICROPY_HW_BOARD_NAME "M5Stack ATOM"
#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "m5stack-atom"
diff --git a/ports/esp32/boards/M5STACK_ATOM/sdkconfig.board b/ports/esp32/boards/M5STACK_ATOM/sdkconfig.board
index b299822dcb6d7..0026b42344236 100644
--- a/ports/esp32/boards/M5STACK_ATOM/sdkconfig.board
+++ b/ports/esp32/boards/M5STACK_ATOM/sdkconfig.board
@@ -1,4 +1,4 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_ESP32_REV_MIN_1=y
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.json b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json
new file mode 100644
index 0000000000000..84b6680d591b4
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json
@@ -0,0 +1,23 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "BLE",
+ "WiFi",
+ "MicroSD",
+ "Battery Charging",
+ "Ethernet",
+ "PoE",
+ "Breadboard friendly"
+ ],
+ "images": [
+ "ESP32-POE-ISO-1.jpg"
+ ],
+ "mcu": "esp32",
+ "product": "Olimex ESP32 POE",
+ "thumbnail": "",
+ "url": "https://www.olimex.com/",
+ "vendor": "OLIMEX"
+}
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.md b/ports/esp32/boards/OLIMEX_ESP32_POE/board.md
new file mode 100644
index 0000000000000..1e2dbb744a0e3
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.md
@@ -0,0 +1,4 @@
+The following files are daily firmware for Olimex ESP32 boards with Ethernet.
+They match the boards ESP32 ETH-PoE, ESP32 ETH-PoE-ISO and ESP32 Gateway.
+
+This firmware is compiled using ESP-IDF v4.x.
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake
new file mode 100644
index 0000000000000..c460b07d5efac
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake
@@ -0,0 +1,5 @@
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.ble
+ boards/OLIMEX_ESP32_POE/sdkconfig.board
+)
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h
new file mode 100644
index 0000000000000..c8458e35fa0d7
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h
@@ -0,0 +1,2 @@
+#define MICROPY_HW_BOARD_NAME "Olimex ESP32 ETH"
+#define MICROPY_HW_MCU_NAME "ESP32"
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board b/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board
new file mode 100644
index 0000000000000..15ffbf3a67b94
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board
@@ -0,0 +1,4 @@
+CONFIG_ETH_PHY_INTERFACE_RMII=y
+CONFIG_ETH_RMII_CLK_OUTPUT=y
+CONFIG_ETH_RMII_CLK_OUT_GPIO=17
+CONFIG_LWIP_LOCAL_HOSTNAME="ESP32_POE"
diff --git a/ports/esp32/boards/SIL_WESP32/sdkconfig.board b/ports/esp32/boards/SIL_WESP32/sdkconfig.board
index 98eef1d109167..be9e40c4c3ae5 100644
--- a/ports/esp32/boards/SIL_WESP32/sdkconfig.board
+++ b/ports/esp32/boards/SIL_WESP32/sdkconfig.board
@@ -7,7 +7,7 @@ CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
# Fast flash
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESP32_REV_MIN_1=y
diff --git a/ports/esp32/boards/UM_FEATHERS2/manifest.py b/ports/esp32/boards/UM_FEATHERS2/manifest.py
index 82ad0c7e49888..3fda1dd8272cf 100644
--- a/ports/esp32/boards/UM_FEATHERS2/manifest.py
+++ b/ports/esp32/boards/UM_FEATHERS2/manifest.py
@@ -1,3 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
-freeze("$(PORT_DIR)/boards/UM_TINYPICO/modules", "dotstar.py")
+module("dotstar.py", base_path="$(PORT_DIR)/boards/UM_TINYPICO/modules", opt=3)
freeze("modules")
diff --git a/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py b/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py
index 95e1f52681606..df3ac4d299e61 100644
--- a/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py
+++ b/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py
@@ -39,6 +39,7 @@
# Helper functions
+
# LED & Ambient Light Sensor control
def set_led(state):
l = Pin(LED, Pin.OUT)
diff --git a/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h b/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h
index 8d0c9f78c83ae..d8529b6342fe2 100644
--- a/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h
+++ b/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "FeatherS2"
#define MICROPY_HW_MCU_NAME "ESP32-S2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "FeatherS2"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board b/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board
index ccda7bff68129..b23755dea7895 100644
--- a/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board
+++ b/ports/esp32/boards/UM_FEATHERS2/sdkconfig.board
@@ -1,15 +1,11 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
-CONFIG_SPIRAM_MEMTEST=
-
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-16MiB.csv"
-#CONFIG_USB_AND_UART=y
# LWIP
CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS2"
diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py b/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py
index 857c7559d1ac8..d0b99e2f9fe15 100644
--- a/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py
+++ b/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py
@@ -38,6 +38,7 @@
DAC1 = const(17)
DAC2 = const(18)
+
# Helper functions
def set_pixel_power(state):
"""Enable or Disable power to the onboard NeoPixel to either show colour, or to reduce power for deep sleep."""
diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake
index b0b3e3aa992ae..c98ef691769b5 100644
--- a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake
+++ b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.cmake
@@ -3,6 +3,7 @@ set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.spiram_sx
boards/sdkconfig.usb
+ boards/UM_FEATHERS2NEO/sdkconfig.board
)
-set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
\ No newline at end of file
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h
index 5ee6874b87bab..e7e4d37ece95a 100644
--- a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h
+++ b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "FeatherS2 Neo"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "FeatherS2-Neo"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board b/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board
index 87a92892d07e1..b2c6979a70be2 100644
--- a/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board
+++ b/ports/esp32/boards/UM_FEATHERS2NEO/sdkconfig.board
@@ -1,4 +1,4 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_USB_AND_UART=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
diff --git a/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py b/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py
index 801f9cbf46fbf..1ba919ceaeeb5 100644
--- a/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py
+++ b/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py
@@ -32,6 +32,7 @@
# Helper functions
+
# LED & Ambient Light Sensor control
def led_set(state):
"""Set the state of the BLUE LED on IO13"""
diff --git a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h
index 738b32ca1e841..91ea5056d17b7 100644
--- a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h
+++ b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "FeatherS3"
#define MICROPY_HW_MCU_NAME "ESP32-S3"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "FeatherS3"
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board b/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board
index 5e20045125463..804944ab24bec 100644
--- a/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board
+++ b/ports/esp32/boards/UM_FEATHERS3/sdkconfig.board
@@ -1,10 +1,7 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
-CONFIG_SPIRAM_MEMTEST=
-
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
@@ -13,11 +10,9 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-16MiB.csv"
CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS3"
-# CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID is not set
CONFIG_TINYUSB_DESC_CUSTOM_VID=0x303A
-# CONFIG_TINYUSB_DESC_USE_DEFAULT_PID is not set
CONFIG_TINYUSB_DESC_CUSTOM_PID=0x80D7
CONFIG_TINYUSB_DESC_BCD_DEVICE=0x0100
CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="Unexpected Maker"
CONFIG_TINYUSB_DESC_PRODUCT_STRING="FeatherS3"
-CONFIG_TINYUSB_DESC_SERIAL_STRING="_fs3_"
\ No newline at end of file
+CONFIG_TINYUSB_DESC_SERIAL_STRING="_fs3_"
diff --git a/ports/esp32/boards/UM_PROS3/modules/pros3.py b/ports/esp32/boards/UM_PROS3/modules/pros3.py
index 2edf3e42ea58c..7f95902936189 100644
--- a/ports/esp32/boards/UM_PROS3/modules/pros3.py
+++ b/ports/esp32/boards/UM_PROS3/modules/pros3.py
@@ -28,6 +28,7 @@
I2C_SDA = const(8)
I2C_SCL = const(9)
+
# Helper functions
def set_ldo2_power(state):
"""Enable or Disable power to the second LDO"""
diff --git a/ports/esp32/boards/UM_PROS3/mpconfigboard.h b/ports/esp32/boards/UM_PROS3/mpconfigboard.h
index 1522e2aee3adc..ecff1e6570666 100644
--- a/ports/esp32/boards/UM_PROS3/mpconfigboard.h
+++ b/ports/esp32/boards/UM_PROS3/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "ProS3"
#define MICROPY_HW_MCU_NAME "ESP32-S3"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "ProS3"
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/UM_PROS3/sdkconfig.board b/ports/esp32/boards/UM_PROS3/sdkconfig.board
index 06b3a00a1c5a4..71511e3c52983 100644
--- a/ports/esp32/boards/UM_PROS3/sdkconfig.board
+++ b/ports/esp32/boards/UM_PROS3/sdkconfig.board
@@ -1,10 +1,7 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
-CONFIG_SPIRAM_MEMTEST=
-
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
@@ -13,9 +10,7 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-16MiB.csv"
CONFIG_LWIP_LOCAL_HOSTNAME="UMProS3"
-# CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID is not set
CONFIG_TINYUSB_DESC_CUSTOM_VID=0x303A
-# CONFIG_TINYUSB_DESC_USE_DEFAULT_PID is not set
CONFIG_TINYUSB_DESC_CUSTOM_PID=0x80D4
CONFIG_TINYUSB_DESC_BCD_DEVICE=0x0100
CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="Unexpected Maker"
diff --git a/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py b/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py
index 95450788426ad..f6bedfb383cb9 100644
--- a/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py
+++ b/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py
@@ -39,6 +39,7 @@
# Helper functions
+
# Get a *rough* estimate of the current battery voltage
# If the battery is not present, the charge IC will still report it's trying to charge at X voltage
# so it will still show a voltage.
diff --git a/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h b/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h
index 6bf70cc13b580..0bb3fa6184155 100644
--- a/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h
+++ b/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "TinyPICO"
#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "TinyPICO"
#define MICROPY_HW_I2C0_SCL (22)
#define MICROPY_HW_I2C0_SDA (21)
diff --git a/ports/esp32/boards/UM_TINYPICO/sdkconfig.board b/ports/esp32/boards/UM_TINYPICO/sdkconfig.board
index 8ed083e62d1a4..8fa596a25ded9 100644
--- a/ports/esp32/boards/UM_TINYPICO/sdkconfig.board
+++ b/ports/esp32/boards/UM_TINYPICO/sdkconfig.board
@@ -1,8 +1,5 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_ESP32_REV_MIN_1=y
CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyPICO"
-
-# SPIRAM increases the size of the firmware, use -Os to reduce it again to fit in iram
-CONFIG_COMPILER_OPTIMIZATION_SIZE=y
diff --git a/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake b/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake
index e4b7b4a915c94..70cb4a814ff24 100644
--- a/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake
+++ b/ports/esp32/boards/UM_TINYS2/mpconfigboard.cmake
@@ -3,4 +3,7 @@ set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.spiram_sx
boards/sdkconfig.usb
+ boards/UM_TINYS2/sdkconfig.board
)
+
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
diff --git a/ports/esp32/boards/UM_TINYS2/mpconfigboard.h b/ports/esp32/boards/UM_TINYS2/mpconfigboard.h
index 1052f6d79ca2b..e0bde417c8a2a 100644
--- a/ports/esp32/boards/UM_TINYS2/mpconfigboard.h
+++ b/ports/esp32/boards/UM_TINYS2/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "TinyS2"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "TinyS2"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/UM_TINYS2/sdkconfig.board b/ports/esp32/boards/UM_TINYS2/sdkconfig.board
index 48b6749c720db..09e0deb078fa3 100644
--- a/ports/esp32/boards/UM_TINYS2/sdkconfig.board
+++ b/ports/esp32/boards/UM_TINYS2/sdkconfig.board
@@ -1,6 +1,8 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_USB_AND_UART=y
+CONFIG_ESPTOOLPY_AFTER_NORESET=y
+
# LWIP
CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyS2"
# end of LWIP
diff --git a/ports/esp32/boards/UM_TINYS3/modules/tinys3.py b/ports/esp32/boards/UM_TINYS3/modules/tinys3.py
index 4efcfe4b52995..06bbb5ff827c6 100644
--- a/ports/esp32/boards/UM_TINYS3/modules/tinys3.py
+++ b/ports/esp32/boards/UM_TINYS3/modules/tinys3.py
@@ -28,6 +28,7 @@
I2C_SDA = const(8)
I2C_SCL = const(9)
+
# Helper functions
def set_pixel_power(state):
"""Enable or Disable power to the onboard NeoPixel to either show colour, or to reduce power for deep sleep."""
diff --git a/ports/esp32/boards/UM_TINYS3/mpconfigboard.h b/ports/esp32/boards/UM_TINYS3/mpconfigboard.h
index b2638a9847882..c0f81f0c447c8 100644
--- a/ports/esp32/boards/UM_TINYS3/mpconfigboard.h
+++ b/ports/esp32/boards/UM_TINYS3/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "TinyS3"
#define MICROPY_HW_MCU_NAME "ESP32-S3-FN8"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "TinyS3"
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/UM_TINYS3/sdkconfig.board b/ports/esp32/boards/UM_TINYS3/sdkconfig.board
index 2b9ddbebe7b5d..c22e78eaeae7c 100644
--- a/ports/esp32/boards/UM_TINYS3/sdkconfig.board
+++ b/ports/esp32/boards/UM_TINYS3/sdkconfig.board
@@ -1,10 +1,7 @@
-CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
-CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
-CONFIG_SPIRAM_MEMTEST=
-
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
@@ -13,9 +10,7 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv"
CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyS3"
-# CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID is not set
CONFIG_TINYUSB_DESC_CUSTOM_VID=0x303A
-# CONFIG_TINYUSB_DESC_USE_DEFAULT_PID is not set
CONFIG_TINYUSB_DESC_CUSTOM_PID=0x80D1
CONFIG_TINYUSB_DESC_BCD_DEVICE=0x0100
CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="Unexpected Maker"
diff --git a/ports/esp32/boards/make-pins.py b/ports/esp32/boards/make-pins.py
new file mode 100755
index 0000000000000..e0f988549b7f3
--- /dev/null
+++ b/ports/esp32/boards/make-pins.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+
+import argparse
+import sys
+import csv
+import re
+
+MAX_CPU_PINS = 49
+
+
+def parse_pin(name_str):
+ """Parses a string and returns a pin number."""
+ if len(name_str) < 2:
+ raise ValueError("Expecting pin name to be at least 2 characters.")
+ if not name_str.startswith("GPIO"):
+ raise ValueError("Expecting pin name to start with GPIO")
+ return int(re.findall(r"\d+$", name_str)[0])
+
+
+class Pin:
+ def __init__(self, pin):
+ self.pin = pin
+ self.is_board = False
+
+ def cpu_pin_name(self):
+ return "GPIO{:d}".format(self.pin)
+
+ def is_board_pin(self):
+ return self.is_board
+
+ def set_is_board_pin(self):
+ self.is_board = True
+
+
+class NamedPin:
+ def __init__(self, name, pin):
+ self._name = name
+ self._pin = pin
+
+ def pin(self):
+ return self._pin
+
+ def name(self):
+ return self._name
+
+
+class Pins:
+ def __init__(self):
+ self.cpu_pins = [] # list of NamedPin objects
+ self.board_pins = [] # list of NamedPin objects
+
+ def find_pin(self, pin_name):
+ for pin in self.cpu_pins:
+ if pin.name() == pin_name:
+ return pin.pin()
+
+ def create_pins(self):
+ for pin_num in range(MAX_CPU_PINS):
+ pin = Pin(pin_num)
+ self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin))
+
+ def parse_board_file(self, filename):
+ with open(filename, "r") as csvfile:
+ rows = csv.reader(csvfile)
+ for row in rows:
+ if len(row) == 0 or row[0].startswith("#"):
+ # Skip empty lines, and lines starting with "#"
+ continue
+ if len(row) != 2:
+ raise ValueError("Expecting two entries in a row")
+
+ cpu_pin_name = row[1]
+ parse_pin(cpu_pin_name)
+ pin = self.find_pin(cpu_pin_name)
+ if not pin:
+ raise ValueError("Unknown pin {}".format(cpu_pin_name))
+ pin.set_is_board_pin()
+ if row[0]: # Only add board pins that have a name
+ self.board_pins.append(NamedPin(row[0], pin))
+
+ def print_table(self, label, named_pins, out_source):
+ print("", file=out_source)
+ print(
+ "const machine_{}_obj_t machine_{}_obj_table[GPIO_NUM_MAX] = {{".format(label, label),
+ file=out_source,
+ )
+ for pin in named_pins:
+ print(" #if MICROPY_HW_ENABLE_{}".format(pin.name()), file=out_source)
+ print(
+ " [GPIO_NUM_{}] = {{ .base = {{ .type = &machine_{}_type }} }},".format(
+ pin.pin().pin, label
+ ),
+ file=out_source,
+ )
+ print(" #endif", file=out_source)
+ print("};", file=out_source)
+
+ def print_named(self, label, named_pins, out_source):
+ print("", file=out_source)
+ print(
+ "STATIC const mp_rom_map_elem_t machine_pin_{:s}_pins_locals_dict_table[] = {{".format(
+ label
+ ),
+ file=out_source,
+ )
+ for named_pin in named_pins:
+ pin = named_pin.pin()
+ print(
+ " {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},".format(
+ named_pin.name(), pin.cpu_pin_name()
+ ),
+ file=out_source,
+ )
+
+ print("};", file=out_source)
+ print(
+ "MP_DEFINE_CONST_DICT(machine_pin_{:s}_pins_locals_dict, machine_pin_{:s}_pins_locals_dict_table);".format(
+ label, label
+ ),
+ file=out_source,
+ )
+
+ def print_tables(self, out_source):
+ self.print_table("pin", self.cpu_pins, out_source)
+ self.print_table("pin_irq", self.cpu_pins, out_source)
+ self.print_named("board", self.board_pins, out_source)
+
+ def print_header(self, out_header):
+ # Provide #defines for each cpu pin.
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ n = pin.cpu_pin_name()
+ print("#if MICROPY_HW_ENABLE_{}".format(n), file=out_header)
+ print(
+ "#define pin_{:s} (machine_pin_obj_table[{}])".format(n, pin.pin),
+ file=out_header,
+ )
+ print("#endif", file=out_header)
+
+ # Provide #define's mapping board to cpu name.
+ for named_pin in self.board_pins:
+ if named_pin.pin().is_board_pin():
+ print(
+ "#define pin_{:s} pin_{:s}".format(
+ named_pin.name(), named_pin.pin().cpu_pin_name()
+ ),
+ file=out_header,
+ )
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Generate board specific pin file")
+ parser.add_argument("--board-csv")
+ parser.add_argument("--prefix")
+ parser.add_argument("--output-source")
+ parser.add_argument("--output-header")
+ args = parser.parse_args(sys.argv[1:])
+
+ pins = Pins()
+ pins.create_pins()
+
+ if args.board_csv:
+ pins.parse_board_file(args.board_csv)
+
+ with open(args.output_source, "w") as out_source:
+ print("// This file was automatically generated by make-pins.py", file=out_source)
+ print("//", file=out_source)
+
+ if args.board_csv:
+ print("// --board-csv {:s}".format(args.board_csv), file=out_source)
+
+ if args.prefix:
+ print("// --prefix {:s}".format(args.prefix), file=out_source)
+ print("", file=out_source)
+ with open(args.prefix, "r") as prefix_file:
+ print(prefix_file.read(), end="", file=out_source)
+
+ pins.print_tables(out_source)
+
+ with open(args.output_header, "w") as out_header:
+ pins.print_header(out_header)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py
index 1dc1481a420df..290d98c4e499c 100644
--- a/ports/esp32/boards/manifest.py
+++ b/ports/esp32/boards/manifest.py
@@ -1,8 +1,15 @@
freeze("$(PORT_DIR)/modules")
-freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py"))
-freeze("$(MPY_DIR)/ports/esp8266/modules", "ntptime.py")
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-freeze("$(MPY_DIR)/drivers/onewire")
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-include("$(MPY_DIR)/drivers/neopixel/manifest.py")
+include("$(MPY_DIR)/extmod/asyncio")
+
+# Useful networking-related packages.
+require("bundle-networking")
+
+# Require some micropython-lib modules.
+# require("aioespnow")
+require("dht")
+require("ds18x20")
+require("neopixel")
+require("onewire")
+require("umqtt.robust")
+require("umqtt.simple")
+require("upysh")
diff --git a/ports/esp32/boards/manifest_release.py b/ports/esp32/boards/manifest_release.py
deleted file mode 100644
index 8b9bcde6ffa77..0000000000000
--- a/ports/esp32/boards/manifest_release.py
+++ /dev/null
@@ -1,7 +0,0 @@
-include("manifest.py")
-
-freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
-
-freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")
-freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
-freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")
diff --git a/ports/esp32/boards/pins_prefix.c b/ports/esp32/boards/pins_prefix.c
new file mode 100644
index 0000000000000..2733ddaab8654
--- /dev/null
+++ b/ports/esp32/boards/pins_prefix.c
@@ -0,0 +1,4 @@
+#include "py/obj.h"
+#include "machine_pin.h"
+#include "modmachine.h"
+#include "genhdr/pins.h"
diff --git a/ports/esp32/boards/sdkconfig.240mhz b/ports/esp32/boards/sdkconfig.240mhz
index e36884009d1ed..c89a1ed251899 100644
--- a/ports/esp32/boards/sdkconfig.240mhz
+++ b/ports/esp32/boards/sdkconfig.240mhz
@@ -1,5 +1,6 @@
# MicroPython on ESP32, ESP IDF configuration with 240MHz CPU
-CONFIG_ESP32_DEFAULT_CPU_FREQ_80=
-CONFIG_ESP32_DEFAULT_CPU_FREQ_160=
-CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
-CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_40=
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80=
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160=
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
+CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240
diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base
index 6b891aa006b1b..bf6c3f45c5269 100644
--- a/ports/esp32/boards/sdkconfig.base
+++ b/ports/esp32/boards/sdkconfig.base
@@ -4,8 +4,6 @@
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000
# Compiler options: use -O2 and disable assertions to improve performance
-# (CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is for IDF 4.0.2)
-CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
CONFIG_COMPILER_OPTIMIZATION_PERF=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
@@ -21,10 +19,14 @@ CONFIG_LOG_DEFAULT_LEVEL_INFO=n
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
CONFIG_LOG_DEFAULT_LEVEL=1
-# ESP32-specific
+# Main XTAL Config
+# Only on: ESP32
+CONFIG_XTAL_FREQ_AUTO=y
+
+# ESP System Settings
+# Only on: ESP32, ESP32S3
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n
-CONFIG_ESP32_XTAL_FREQ_AUTO=y
# Power Management
CONFIG_PM_ENABLE=y
@@ -44,12 +46,14 @@ CONFIG_LWIP_PPP_PAP_SUPPORT=y
CONFIG_LWIP_PPP_CHAP_SUPPORT=y
# SSL
-# Use 4kiB output buffer instead of default 16kiB (because IDF heap is fragmented in 4.0)
+# Use 4kiB output buffer instead of default 16kiB
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
# ULP coprocessor support
-CONFIG_ESP32_ULP_COPROC_ENABLED=y
-CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=2040
+# Only on: ESP32, ESP32S2, ESP32S3
+CONFIG_ULP_COPROC_ENABLED=y
+CONFIG_ULP_COPROC_TYPE_FSM=y
+CONFIG_ULP_COPROC_RESERVE_MEM=2040
# For cmake build
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
@@ -60,7 +64,16 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_ESP32_WIFI_IRAM_OPT=n
CONFIG_ESP32_WIFI_RX_IRAM_OPT=n
-# ADC calibration
+# Legacy ADC Calibration Configuration
+# Only on: ESP32
CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y
CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y
CONFIG_ADC_CAL_LUT_ENABLE=y
+
+# UART Configuration
+CONFIG_UART_ISR_IN_IRAM=y
+
+# IDF 5 deprecated
+CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y
+CONFIG_RMT_SUPPRESS_DEPRECATE_WARN=y
+CONFIG_I2S_SUPPRESS_DEPRECATE_WARN=y
diff --git a/ports/esp32/boards/sdkconfig.ble b/ports/esp32/boards/sdkconfig.ble
index 08d5e481f4993..91ac3240ebee7 100644
--- a/ports/esp32/boards/sdkconfig.ble
+++ b/ports/esp32/boards/sdkconfig.ble
@@ -1,9 +1,14 @@
-# Note this requires building with IDF 4.x
+CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR=y
CONFIG_BT_ENABLED=y
-CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
-CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=
-CONFIG_BTDM_CTRL_MODE_BTDM=
-
CONFIG_BT_NIMBLE_ENABLED=y
+CONFIG_BT_CONTROLLER_ENABLED=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=4
+
+# Put NimBLE on core 1, and for synchronisation
+# with the ringbuffer and scheduler MP needs to be on the same core.
+# MP on core 1 prevents interference with WiFi for time sensitive operations.
+# Only on: ESP32, ESP32S2, ESP32S3
+CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=n
+CONFIG_BT_NIMBLE_PINNED_TO_CORE_1=y
+CONFIG_BT_NIMBLE_PINNED_TO_CORE=1
diff --git a/ports/esp32/boards/sdkconfig.nimble_core0 b/ports/esp32/boards/sdkconfig.nimble_core0
deleted file mode 100644
index cacaff1197cb3..0000000000000
--- a/ports/esp32/boards/sdkconfig.nimble_core0
+++ /dev/null
@@ -1,6 +0,0 @@
-# For IDF <4.2, we need NimBLE on core 0, and for synchronisation
-# with the ringbuffer and scheduler MP needs to be on the same core.
-# See https://github.com/micropython/micropython/issues/5489
-CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=y
-CONFIG_BT_NIMBLE_PINNED_TO_CORE_1=n
-CONFIG_BT_NIMBLE_PINNED_TO_CORE=0
diff --git a/ports/esp32/boards/sdkconfig.nimble_core1 b/ports/esp32/boards/sdkconfig.nimble_core1
deleted file mode 100644
index 33653cc4b164c..0000000000000
--- a/ports/esp32/boards/sdkconfig.nimble_core1
+++ /dev/null
@@ -1,6 +0,0 @@
-# For IDF >=4.2, we are able to put NimBLE on core 1, and for synchronisation
-# with the ringbuffer and scheduler MP needs to be on the same core.
-# MP on core 1 prevents interference with WiFi for time sensitive operations.
-CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=n
-CONFIG_BT_NIMBLE_PINNED_TO_CORE_1=y
-CONFIG_BT_NIMBLE_PINNED_TO_CORE=1
diff --git a/ports/esp32/boards/sdkconfig.spiram b/ports/esp32/boards/sdkconfig.spiram
index 5b4ce118b890e..74d35f7b4ad4a 100644
--- a/ports/esp32/boards/sdkconfig.spiram
+++ b/ports/esp32/boards/sdkconfig.spiram
@@ -1,6 +1,11 @@
# MicroPython on ESP32, ESP IDF configuration with SPIRAM support
-CONFIG_ESP32_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM=y
CONFIG_SPIRAM_CACHE_WORKAROUND=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
-CONFIG_SPIRAM_USE_MEMMAP=y
+CONFIG_SPIRAM_USE_CAPS_ALLOC=y
+
+# SPIRAM increases the size of the firmware and overflows iram0_0_seg, due
+# to PSRAM bug workarounds. Apply some options to reduce the firmware size.
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
diff --git a/ports/esp32/boards/sdkconfig.spiram_oct b/ports/esp32/boards/sdkconfig.spiram_oct
new file mode 100644
index 0000000000000..aaea64fcd5c08
--- /dev/null
+++ b/ports/esp32/boards/sdkconfig.spiram_oct
@@ -0,0 +1,3 @@
+# MicroPython on ESP32-S2 and ESP32-PAD1_subscript_3, ESP IDF configuration with SPIRAM support in Octal mode
+CONFIG_SPIRAM_MODE_QUAD=
+CONFIG_SPIRAM_MODE_OCT=y
diff --git a/ports/esp32/boards/sdkconfig.spiram_sx b/ports/esp32/boards/sdkconfig.spiram_sx
index ef24e90829e16..329a507337108 100644
--- a/ports/esp32/boards/sdkconfig.spiram_sx
+++ b/ports/esp32/boards/sdkconfig.spiram_sx
@@ -1,15 +1,10 @@
# MicroPython on ESP32-S2 and ESP32-PAD1_subscript_3, ESP IDF configuration with SPIRAM support
-CONFIG_ESP32S2_SPIRAM_SUPPORT=y
-CONFIG_ESP32S3_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_MODE_QUAD=y
CONFIG_SPIRAM_TYPE_AUTO=y
-CONFIG_DEFAULT_PSRAM_CLK_IO=30
-CONFIG_DEFAULT_PSRAM_CS_IO=26
+CONFIG_SPIRAM_CLK_IO=30
+CONFIG_SPIRAM_CS_IO=26
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
-CONFIG_SPIRAM_USE_MEMMAP=y
-CONFIG_SPIRAM_MEMTEST=y
-CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
-CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
+CONFIG_SPIRAM_USE_CAPS_ALLOC=y
diff --git a/ports/esp32/boards/sdkconfig.usb b/ports/esp32/boards/sdkconfig.usb
index 657edbc58059b..4090c710e62e6 100644
--- a/ports/esp32/boards/sdkconfig.usb
+++ b/ports/esp32/boards/sdkconfig.usb
@@ -1,4 +1,4 @@
-CONFIG_USB_ENABLED=y
-CONFIG_USB_CDC_ENABLED=y
-CONFIG_USB_CDC_RX_BUFSIZE=256
-CONFIG_USB_CDC_TX_BUFSIZE=256
+CONFIG_USB_OTG_SUPPORTED=y
+CONFIG_TINYUSB_CDC_ENABLED=y
+CONFIG_TINYUSB_CDC_RX_BUFSIZE=256
+CONFIG_TINYUSB_CDC_TX_BUFSIZE=256
diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake
new file mode 100644
index 0000000000000..37a19316b603d
--- /dev/null
+++ b/ports/esp32/esp32_common.cmake
@@ -0,0 +1,229 @@
+# Set location of base MicroPython directory.
+if(NOT MICROPY_DIR)
+ get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../.. ABSOLUTE)
+endif()
+
+# Set location of the ESP32 port directory.
+if(NOT MICROPY_PORT_DIR)
+ get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
+endif()
+
+# Include core source components.
+include(${MICROPY_DIR}/py/py.cmake)
+
+if(NOT CMAKE_BUILD_EARLY_EXPANSION)
+ # Enable extmod components that will be configured by extmod.cmake.
+ # A board may also have enabled additional components.
+ set(MICROPY_PY_BTREE ON)
+
+ include(${MICROPY_DIR}/py/usermod.cmake)
+ include(${MICROPY_DIR}/extmod/extmod.cmake)
+endif()
+
+list(APPEND MICROPY_QSTRDEFS_PORT
+ ${MICROPY_PORT_DIR}/qstrdefsport.h
+)
+
+list(APPEND MICROPY_SOURCE_SHARED
+ ${MICROPY_DIR}/shared/readline/readline.c
+ ${MICROPY_DIR}/shared/netutils/netutils.c
+ ${MICROPY_DIR}/shared/timeutils/timeutils.c
+ ${MICROPY_DIR}/shared/runtime/interrupt_char.c
+ ${MICROPY_DIR}/shared/runtime/stdout_helpers.c
+ ${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
+ ${MICROPY_DIR}/shared/runtime/pyexec.c
+)
+
+list(APPEND MICROPY_SOURCE_LIB
+ ${MICROPY_DIR}/lib/littlefs/lfs1.c
+ ${MICROPY_DIR}/lib/littlefs/lfs1_util.c
+ ${MICROPY_DIR}/lib/littlefs/lfs2.c
+ ${MICROPY_DIR}/lib/littlefs/lfs2_util.c
+ #${MICROPY_DIR}/lib/mbedtls_errors/esp32_mbedtls_errors.c
+ ${MICROPY_DIR}/lib/oofatfs/ff.c
+ ${MICROPY_DIR}/lib/oofatfs/ffunicode.c
+)
+
+list(APPEND MICROPY_SOURCE_DRIVERS
+ ${MICROPY_DIR}/drivers/bus/softspi.c
+ ${MICROPY_DIR}/drivers/dht/dht.c
+)
+
+list(APPEND MICROPY_SOURCE_PORT
+ main.c
+ ppp_set_auth.c
+ uart.c
+ usb.c
+ usb_serial_jtag.c
+ gccollect.c
+ mphalport.c
+ fatfs_port.c
+ help.c
+ machine_bitstream.c
+ machine_timer.c
+ machine_pin.c
+ machine_touchpad.c
+ machine_adc.c
+ machine_adcblock.c
+ machine_dac.c
+ machine_i2c.c
+ machine_i2s.c
+ machine_uart.c
+ modmachine.c
+ network_common.c
+ network_lan.c
+ network_ppp.c
+ network_wlan.c
+ mpnimbleport.c
+ modsocket.c
+ modesp.c
+ esp32_nvs.c
+ esp32_partition.c
+ esp32_rmt.c
+ esp32_ulp.c
+ modesp32.c
+ machine_hw_spi.c
+ machine_wdt.c
+ mpthreadport.c
+ machine_rtc.c
+ machine_sdcard.c
+ modespnow.c
+)
+list(TRANSFORM MICROPY_SOURCE_PORT PREPEND ${MICROPY_PORT_DIR}/)
+list(APPEND MICROPY_SOURCE_PORT ${CMAKE_BINARY_DIR}/pins.c)
+
+list(APPEND MICROPY_SOURCE_QSTR
+ ${MICROPY_SOURCE_PY}
+ ${MICROPY_SOURCE_EXTMOD}
+ ${MICROPY_SOURCE_USERMOD}
+ ${MICROPY_SOURCE_SHARED}
+ ${MICROPY_SOURCE_LIB}
+ ${MICROPY_SOURCE_PORT}
+ ${MICROPY_SOURCE_BOARD}
+)
+
+list(APPEND IDF_COMPONENTS
+ app_update
+ bootloader_support
+ bt
+ driver
+ esp_adc
+ esp_app_format
+ esp_common
+ esp_eth
+ esp_event
+ esp_hw_support
+ esp_netif
+ esp_partition
+ esp_pm
+ esp_psram
+ esp_ringbuf
+ esp_rom
+ esp_system
+ esp_timer
+ esp_wifi
+ freertos
+ hal
+ heap
+ log
+ lwip
+ mbedtls
+ newlib
+ nvs_flash
+ sdmmc
+ soc
+ spi_flash
+ ulp
+ vfs
+ xtensa
+)
+
+# Register the main IDF component.
+idf_component_register(
+ SRCS
+ ${MICROPY_SOURCE_PY}
+ ${MICROPY_SOURCE_EXTMOD}
+ ${MICROPY_SOURCE_SHARED}
+ ${MICROPY_SOURCE_LIB}
+ ${MICROPY_SOURCE_DRIVERS}
+ ${MICROPY_SOURCE_PORT}
+ ${MICROPY_SOURCE_BOARD}
+ INCLUDE_DIRS
+ ${MICROPY_INC_CORE}
+ ${MICROPY_INC_USERMOD}
+ ${MICROPY_PORT_DIR}
+ ${MICROPY_BOARD_DIR}
+ ${CMAKE_BINARY_DIR}
+ REQUIRES
+ ${IDF_COMPONENTS}
+)
+
+# Set the MicroPython target as the current (main) IDF component target.
+set(MICROPY_TARGET ${COMPONENT_TARGET})
+
+# Define mpy-cross flags, for use with frozen code.
+set(MICROPY_CROSS_FLAGS -march=xtensawin)
+
+# Set compile options for this port.
+target_compile_definitions(${MICROPY_TARGET} PUBLIC
+ ${MICROPY_DEF_CORE}
+ MICROPY_ESP_IDF_4=1
+ MICROPY_VFS_FAT=1
+ MICROPY_VFS_LFS2=1
+ FFCONF_H=\"${MICROPY_OOFATFS_DIR}/ffconf.h\"
+ LFS1_NO_MALLOC LFS1_NO_DEBUG LFS1_NO_WARN LFS1_NO_ERROR LFS1_NO_ASSERT
+ LFS2_NO_MALLOC LFS2_NO_DEBUG LFS2_NO_WARN LFS2_NO_ERROR LFS2_NO_ASSERT
+)
+
+# Disable some warnings to keep the build output clean.
+target_compile_options(${MICROPY_TARGET} PUBLIC
+ -Wno-clobbered
+ -Wno-deprecated-declarations
+ -Wno-missing-field-initializers
+)
+
+# Additional include directories needed for private NimBLE headers.
+target_include_directories(${MICROPY_TARGET} PUBLIC
+ ${IDF_PATH}/components/bt/host/nimble/nimble
+)
+
+# Add additional extmod and usermod components.
+target_link_libraries(${MICROPY_TARGET} micropy_extmod_btree)
+target_link_libraries(${MICROPY_TARGET} usermod)
+
+# Collect all of the include directories and compile definitions for the IDF components,
+# including those added by the IDF Component Manager via idf_components.yaml.
+foreach(comp ${__COMPONENT_NAMES_RESOLVED})
+ micropy_gather_target_properties(__idf_${comp})
+ micropy_gather_target_properties(${comp})
+endforeach()
+
+# Include the main MicroPython cmake rules.
+include(${MICROPY_DIR}/py/mkrules.cmake)
+
+# Generate source files for named pins (requires mkrules.cmake for MICROPY_GENHDR_DIR).
+
+set(GEN_PINS_PREFIX "${MICROPY_PORT_DIR}/boards/pins_prefix.c")
+set(GEN_PINS_MKPINS "${MICROPY_PORT_DIR}/boards/make-pins.py")
+set(GEN_PINS_SRC "${CMAKE_BINARY_DIR}/pins.c")
+set(GEN_PINS_HDR "${MICROPY_GENHDR_DIR}/pins.h")
+
+if(EXISTS "${MICROPY_BOARD_DIR}/pins.csv")
+ set(GEN_PINS_BOARD_CSV "${MICROPY_BOARD_DIR}/pins.csv")
+ set(GEN_PINS_BOARD_CSV_ARG --board-csv "${GEN_PINS_BOARD_CSV}")
+endif()
+
+target_sources(${MICROPY_TARGET} PRIVATE ${GEN_PINS_HDR})
+
+add_custom_command(
+ OUTPUT ${GEN_PINS_SRC} ${GEN_PINS_HDR}
+ COMMAND ${Python3_EXECUTABLE} ${GEN_PINS_MKPINS} ${GEN_PINS_BOARD_CSV_ARG}
+ --prefix ${GEN_PINS_PREFIX} --output-source ${GEN_PINS_SRC} --output-header ${GEN_PINS_HDR}
+ DEPENDS
+ ${MICROPY_MPVERSION}
+ ${GEN_PINS_MKPINS}
+ ${GEN_PINS_BOARD_CSV}
+ ${GEN_PINS_PREFIX}
+ VERBATIM
+ COMMAND_EXPAND_LISTS
+)
diff --git a/ports/esp32/esp32_nvs.c b/ports/esp32/esp32_nvs.c
index 42d65be4a63b2..0b3661918c771 100644
--- a/ports/esp32/esp32_nvs.c
+++ b/ports/esp32/esp32_nvs.c
@@ -141,10 +141,11 @@ STATIC const mp_rom_map_elem_t esp32_nvs_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp32_nvs_locals_dict, esp32_nvs_locals_dict_table);
-const mp_obj_type_t esp32_nvs_type = {
- { &mp_type_type },
- .name = MP_QSTR_NVS,
- .print = esp32_nvs_print,
- .make_new = esp32_nvs_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp32_nvs_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_nvs_type,
+ MP_QSTR_NVS,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_nvs_make_new,
+ print, esp32_nvs_print,
+ locals_dict, &esp32_nvs_locals_dict
+ );
diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c
index 47e769486c9b4..17aa34e560e8a 100644
--- a/ports/esp32/esp32_partition.c
+++ b/ports/esp32/esp32_partition.c
@@ -284,10 +284,11 @@ STATIC const mp_rom_map_elem_t esp32_partition_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp32_partition_locals_dict, esp32_partition_locals_dict_table);
-const mp_obj_type_t esp32_partition_type = {
- { &mp_type_type },
- .name = MP_QSTR_Partition,
- .print = esp32_partition_print,
- .make_new = esp32_partition_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp32_partition_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_partition_type,
+ MP_QSTR_Partition,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_partition_make_new,
+ print, esp32_partition_print,
+ locals_dict, &esp32_partition_locals_dict
+ );
diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c
index ac897e33368a3..f92af636f55a2 100644
--- a/ports/esp32/esp32_rmt.c
+++ b/ports/esp32/esp32_rmt.c
@@ -48,11 +48,7 @@
// and carrier output.
// Last available RMT channel that can transmit.
-#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 4, 0)
-#define RMT_LAST_TX_CHANNEL (RMT_CHANNEL_MAX - 1)
-#else
#define RMT_LAST_TX_CHANNEL (SOC_RMT_TX_CANDIDATES_PER_GROUP - 1)
-#endif
// Forward declaration
extern const mp_obj_type_t esp32_rmt_type;
@@ -326,13 +322,13 @@ STATIC mp_obj_t esp32_rmt_write_pulses(size_t n_args, const mp_obj_t *args) {
check_esp_err(rmt_wait_tx_done(self->channel_id, portMAX_DELAY));
}
- check_esp_err(rmt_write_items(self->channel_id, self->items, num_items, false));
-
if (self->loop_en) {
check_esp_err(rmt_set_tx_intr_en(self->channel_id, false));
check_esp_err(rmt_set_tx_loop_mode(self->channel_id, true));
}
+ check_esp_err(rmt_write_items(self->channel_id, self->items, num_items, false));
+
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_rmt_write_pulses_obj, 2, 3, esp32_rmt_write_pulses);
@@ -372,10 +368,11 @@ STATIC const mp_rom_map_elem_t esp32_rmt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp32_rmt_locals_dict, esp32_rmt_locals_dict_table);
-const mp_obj_type_t esp32_rmt_type = {
- { &mp_type_type },
- .name = MP_QSTR_RMT,
- .print = esp32_rmt_print,
- .make_new = esp32_rmt_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp32_rmt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_rmt_type,
+ MP_QSTR_RMT,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_rmt_make_new,
+ print, esp32_rmt_print,
+ locals_dict, &esp32_rmt_locals_dict
+ );
diff --git a/ports/esp32/esp32_ulp.c b/ports/esp32/esp32_ulp.c
index 8e4ce9c5a41b9..97041c60bd6be 100644
--- a/ports/esp32/esp32_ulp.c
+++ b/ports/esp32/esp32_ulp.c
@@ -26,10 +26,15 @@
#include "py/runtime.h"
-#if CONFIG_IDF_TARGET_ESP32
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+#if CONFIG_IDF_TARGET_ESP32
#include "esp32/ulp.h"
-#include "esp_err.h"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/ulp.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/ulp.h"
+#endif
typedef struct _esp32_ulp_obj_t {
mp_obj_base_t base;
@@ -87,15 +92,16 @@ STATIC const mp_rom_map_elem_t esp32_ulp_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_wakeup_period), MP_ROM_PTR(&esp32_ulp_set_wakeup_period_obj) },
{ MP_ROM_QSTR(MP_QSTR_load_binary), MP_ROM_PTR(&esp32_ulp_load_binary_obj) },
{ MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&esp32_ulp_run_obj) },
- { MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM) },
+ { MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ULP_COPROC_RESERVE_MEM) },
};
STATIC MP_DEFINE_CONST_DICT(esp32_ulp_locals_dict, esp32_ulp_locals_dict_table);
-const mp_obj_type_t esp32_ulp_type = {
- { &mp_type_type },
- .name = MP_QSTR_ULP,
- .make_new = esp32_ulp_make_new,
- .locals_dict = (mp_obj_t)&esp32_ulp_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_ulp_type,
+ MP_QSTR_ULP,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_ulp_make_new,
+ locals_dict, &esp32_ulp_locals_dict
+ );
-#endif // CONFIG_IDF_TARGET_ESP32
+#endif // CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
diff --git a/ports/esp32/gccollect.c b/ports/esp32/gccollect.c
index 403a3c7dfa0fb..6fa287de28c0c 100644
--- a/ports/esp32/gccollect.c
+++ b/ports/esp32/gccollect.c
@@ -34,7 +34,6 @@
#include "py/gc.h"
#include "py/mpthread.h"
#include "gccollect.h"
-#include "soc/cpu.h"
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
@@ -50,7 +49,7 @@ static void gc_collect_inner(int level) {
if (level == XCHAL_NUM_AREGS / 8) {
// get the sp
- volatile uint32_t sp = (uint32_t)get_sp();
+ volatile uint32_t sp = (uint32_t)esp_cpu_get_sp();
gc_collect_root((void **)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t));
return;
}
diff --git a/ports/esp32/help.c b/ports/esp32/help.c
index 2336d97f84416..2351d7dc73943 100644
--- a/ports/esp32/help.c
+++ b/ports/esp32/help.c
@@ -31,7 +31,7 @@
const char esp32_help_text[] =
"Welcome to MicroPython on the ESP32!\n"
"\n"
- "For generic online docs please visit http://docs.micropython.org/\n"
+ "For online docs please visit http://docs.micropython.org/\n"
"\n"
"For access to the hardware use the 'machine' module:\n"
"\n"
diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c
index cb45aab33910c..1e20186b97be9 100644
--- a/ports/esp32/machine_adc.c
+++ b/ports/esp32/machine_adc.c
@@ -256,10 +256,11 @@ STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = madc_print,
- .make_new = madc_make_new,
- .locals_dict = (mp_obj_t)&madc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, madc_make_new,
+ print, madc_print,
+ locals_dict, &madc_locals_dict
+ );
diff --git a/ports/esp32/machine_adcblock.c b/ports/esp32/machine_adcblock.c
index 06c215f8ae73d..afe8fdea40b2a 100644
--- a/ports/esp32/machine_adcblock.c
+++ b/ports/esp32/machine_adcblock.c
@@ -194,10 +194,11 @@ STATIC const mp_rom_map_elem_t madcblock_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(madcblock_locals_dict, madcblock_locals_dict_table);
-const mp_obj_type_t machine_adcblock_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADCBlock,
- .print = madcblock_print,
- .make_new = madcblock_make_new,
- .locals_dict = (mp_obj_t)&madcblock_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adcblock_type,
+ MP_QSTR_ADCBlock,
+ MP_TYPE_FLAG_NONE,
+ make_new, madcblock_make_new,
+ print, madcblock_print,
+ locals_dict, &madcblock_locals_dict
+ );
diff --git a/ports/esp32/machine_adcblock.h b/ports/esp32/machine_adcblock.h
index 0500726d71791..7c9249b072c18 100644
--- a/ports/esp32/machine_adcblock.h
+++ b/ports/esp32/machine_adcblock.h
@@ -3,6 +3,8 @@
#include "esp_adc_cal.h"
+#define ADC_ATTEN_MAX SOC_ADC_ATTEN_NUM
+
typedef struct _madcblock_obj_t {
mp_obj_base_t base;
adc_unit_t unit_id;
diff --git a/ports/esp32/machine_bitstream.c b/ports/esp32/machine_bitstream.c
index 4284b5f8baf77..87a5ae53cfe54 100644
--- a/ports/esp32/machine_bitstream.c
+++ b/ports/esp32/machine_bitstream.c
@@ -28,6 +28,10 @@
#include "py/mphal.h"
#include "modesp32.h"
+#include "rom/gpio.h"
+#include "soc/gpio_reg.h"
+#include "soc/gpio_sig_map.h"
+
#if MICROPY_PY_MACHINE_BITSTREAM
/******************************************************************************/
@@ -52,7 +56,7 @@ STATIC void IRAM_ATTR machine_bitstream_high_low_bitbang(mp_hal_pin_obj_t pin, u
}
// Convert ns to cpu ticks [high_time_0, period_0, high_time_1, period_1].
- uint32_t fcpu_mhz = ets_get_cpu_frequency();
+ uint32_t fcpu_mhz = esp_rom_get_cpu_ticks_per_us();
for (size_t i = 0; i < 4; ++i) {
timing_ns[i] = fcpu_mhz * timing_ns[i] / 1000;
if (timing_ns[i] > NS_TICKS_OVERHEAD) {
@@ -91,27 +95,6 @@ STATIC void IRAM_ATTR machine_bitstream_high_low_bitbang(mp_hal_pin_obj_t pin, u
#include "driver/rmt.h"
-#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 1, 0)
-// This convenience macro was not available in earlier IDF versions.
-#define RMT_DEFAULT_CONFIG_TX(gpio, channel_id) \
- { \
- .rmt_mode = RMT_MODE_TX, \
- .channel = channel_id, \
- .clk_div = 80, \
- .gpio_num = gpio, \
- .mem_block_num = 1, \
- .tx_config = { \
- .loop_en = false, \
- .carrier_freq_hz = 38000, \
- .carrier_duty_percent = 33, \
- .carrier_level = RMT_CARRIER_LEVEL_HIGH, \
- .carrier_en = false, \
- .idle_level = RMT_IDLE_LEVEL_LOW, \
- .idle_output_en = true, \
- } \
- }
-#endif
-
// Logical 0 and 1 values (encoded as a rmt_item32_t).
// The duration fields will be set later.
STATIC rmt_item32_t bitstream_high_low_0 = {{{ 0, 1, 0, 0 }}};
@@ -163,13 +146,7 @@ STATIC void machine_bitstream_high_low_rmt(mp_hal_pin_obj_t pin, uint32_t *timin
// Get the tick rate in kHz (this will likely be 40000).
uint32_t counter_clk_khz = 0;
- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 1, 0)
- uint8_t div_cnt;
- check_esp_err(rmt_get_clk_div(config.channel, &div_cnt));
- counter_clk_khz = APB_CLK_FREQ / div_cnt;
- #else
check_esp_err(rmt_get_counter_clock(config.channel, &counter_clk_khz));
- #endif
counter_clk_khz /= 1000;
@@ -193,7 +170,7 @@ STATIC void machine_bitstream_high_low_rmt(mp_hal_pin_obj_t pin, uint32_t *timin
check_esp_err(rmt_driver_uninstall(config.channel));
// Cancel RMT output to GPIO pin.
- gpio_matrix_out(pin, SIG_GPIO_OUT_IDX, false, false);
+ esp_rom_gpio_connect_out_signal(pin, SIG_GPIO_OUT_IDX, false, false);
}
/******************************************************************************/
diff --git a/ports/esp32/machine_dac.c b/ports/esp32/machine_dac.c
index 35826d4a99a8b..0e85dc9c9bfb2 100644
--- a/ports/esp32/machine_dac.c
+++ b/ports/esp32/machine_dac.c
@@ -104,12 +104,13 @@ STATIC const mp_rom_map_elem_t mdac_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(mdac_locals_dict, mdac_locals_dict_table);
-const mp_obj_type_t machine_dac_type = {
- { &mp_type_type },
- .name = MP_QSTR_DAC,
- .print = mdac_print,
- .make_new = mdac_make_new,
- .locals_dict = (mp_obj_t)&mdac_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_dac_type,
+ MP_QSTR_DAC,
+ MP_TYPE_FLAG_NONE,
+ make_new, mdac_make_new,
+ print, mdac_print,
+ locals_dict, &mdac_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_DAC
diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c
index 3e720adb1a5e2..662d0e599419b 100644
--- a/ports/esp32/machine_hw_spi.c
+++ b/ports/esp32/machine_hw_spi.c
@@ -35,6 +35,8 @@
#include "modmachine.h"
#include "driver/spi_master.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/spi_pins.h"
// SPI mappings by device, naming used by IDF old/new
// upython | ESP32 | ESP32S2 | ESP32S3 | ESP32C3
@@ -57,9 +59,9 @@
#define MICROPY_HW_SPI1_MOSI FSPI_IOMUX_PIN_NUM_MOSI
#define MICROPY_HW_SPI1_MISO FSPI_IOMUX_PIN_NUM_MISO
#else
-#define MICROPY_HW_SPI1_SCK HSPI_IOMUX_PIN_NUM_CLK
-#define MICROPY_HW_SPI1_MOSI HSPI_IOMUX_PIN_NUM_MOSI
-#define MICROPY_HW_SPI1_MISO HSPI_IOMUX_PIN_NUM_MISO
+#define MICROPY_HW_SPI1_SCK SPI2_IOMUX_PIN_NUM_CLK
+#define MICROPY_HW_SPI1_MOSI SPI2_IOMUX_PIN_NUM_MOSI
+#define MICROPY_HW_SPI1_MISO SPI2_IOMUX_PIN_NUM_MISO
#endif
#endif
@@ -67,9 +69,9 @@
#ifndef MICROPY_HW_SPI2_SCK
#if CONFIG_IDF_TARGET_ESP32
// ESP32 has IO_MUX pins for VSPI/SPI3 lines, use them as defaults
-#define MICROPY_HW_SPI2_SCK VSPI_IOMUX_PIN_NUM_CLK // pin 18
-#define MICROPY_HW_SPI2_MOSI VSPI_IOMUX_PIN_NUM_MOSI // pin 23
-#define MICROPY_HW_SPI2_MISO VSPI_IOMUX_PIN_NUM_MISO // pin 19
+#define MICROPY_HW_SPI2_SCK SPI3_IOMUX_PIN_NUM_CLK // pin 18
+#define MICROPY_HW_SPI2_MOSI SPI3_IOMUX_PIN_NUM_MOSI // pin 23
+#define MICROPY_HW_SPI2_MISO SPI3_IOMUX_PIN_NUM_MISO // pin 19
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
// ESP32S2 and S3 uses GPIO matrix for SPI3 pins, no IO_MUX possible
// Set defaults to the pins used by SPI2 in Octal mode
@@ -83,9 +85,9 @@
#define MP_HW_SPI_MAX_XFER_BITS (MP_HW_SPI_MAX_XFER_BYTES * 8) // Has to be an even multiple of 8
#if CONFIG_IDF_TARGET_ESP32C3
-#define HSPI_HOST SPI2_HOST
+#define SPI2_HOST SPI2_HOST
#elif CONFIG_IDF_TARGET_ESP32S3
-#define HSPI_HOST SPI3_HOST
+#define SPI2_HOST SPI3_HOST
#define FSPI_HOST SPI2_HOST
#endif
@@ -122,7 +124,7 @@ STATIC const machine_hw_spi_default_pins_t machine_hw_spi_default_pins[2] = {
#endif
};
-// Static objects mapping to HSPI and VSPI hardware peripherals
+// Static objects mapping to SPI2 and SPI3 hardware peripherals
STATIC machine_hw_spi_obj_t machine_hw_spi_obj[2];
STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self) {
@@ -150,8 +152,8 @@ STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self) {
for (int i = 0; i < 3; i++) {
if (pins[i] != -1) {
- gpio_pad_select_gpio(pins[i]);
- gpio_matrix_out(pins[i], SIG_GPIO_OUT_IDX, false, false);
+ esp_rom_gpio_pad_select_gpio(pins[i]);
+ esp_rom_gpio_connect_out_signal(pins[i], SIG_GPIO_OUT_IDX, false, false);
gpio_set_direction(pins[i], GPIO_MODE_INPUT);
}
}
@@ -226,12 +228,12 @@ STATIC void machine_hw_spi_init_internal(
changed = true;
}
- if (self->host != HSPI_HOST
+ if (self->host != SPI2_HOST
#ifdef FSPI_HOST
&& self->host != FSPI_HOST
#endif
- #ifdef VSPI_HOST
- && self->host != VSPI_HOST
+ #ifdef SPI3_HOST
+ && self->host != SPI3_HOST
#endif
) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI(%d) doesn't exist"), self->host);
@@ -267,21 +269,15 @@ STATIC void machine_hw_spi_init_internal(
// Select DMA channel based on the hardware SPI host
int dma_chan = 0;
- if (self->host == HSPI_HOST) {
- #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
- dma_chan = 3;
- #else
+ #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
+ dma_chan = SPI_DMA_CH_AUTO;
+ #else
+ if (self->host == SPI2_HOST) {
dma_chan = 1;
- #endif
- #ifdef FSPI_HOST
- } else if (self->host == FSPI_HOST) {
- dma_chan = 1;
- #endif
- #ifdef VSPI_HOST
- } else if (self->host == VSPI_HOST) {
+ } else {
dma_chan = 2;
- #endif
}
+ #endif
ret = spi_bus_initialize(self->host, &buscfg, dma_chan);
switch (ret) {
@@ -489,14 +485,14 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
machine_hw_spi_obj_t *self;
const machine_hw_spi_default_pins_t *default_pins;
- if (args[ARG_id].u_int == 1) { // SPI2_HOST which is FSPI_HOST on ESP32Sx, HSPI_HOST on others
+ if (args[ARG_id].u_int == 1) { // SPI2_HOST which is FSPI_HOST on ESP32Sx, SPI2_HOST on others
self = &machine_hw_spi_obj[0];
default_pins = &machine_hw_spi_default_pins[0];
} else {
self = &machine_hw_spi_obj[1];
default_pins = &machine_hw_spi_default_pins[1];
}
- self->base.type = &machine_hw_spi_type;
+ self->base.type = &machine_spi_type;
int8_t sck, mosi, miso;
@@ -539,17 +535,26 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
return MP_OBJ_FROM_PTR(self);
}
+spi_host_device_t machine_hw_spi_get_host(mp_obj_t in) {
+ if (mp_obj_get_type(in) != &machine_spi_type) {
+ mp_raise_ValueError(MP_ERROR_TEXT("expecting a SPI object"));
+ }
+ machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t *)in;
+ return self->host;
+}
+
STATIC const mp_machine_spi_p_t machine_hw_spi_p = {
.init = machine_hw_spi_init,
.deinit = machine_hw_spi_deinit,
.transfer = machine_hw_spi_transfer,
};
-const mp_obj_type_t machine_hw_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = machine_hw_spi_print,
- .make_new = machine_hw_spi_make_new,
- .protocol = &machine_hw_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hw_spi_make_new,
+ print, machine_hw_spi_print,
+ protocol, &machine_hw_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c
index e25cad0b60a52..d498aa058d74b 100644
--- a/ports/esp32/machine_i2c.c
+++ b/ports/esp32/machine_i2c.c
@@ -31,6 +31,7 @@
#include "modmachine.h"
#include "driver/i2c.h"
+#include "hal/i2c_ll.h"
#ifndef MICROPY_HW_I2C0_SCL
#define MICROPY_HW_I2C0_SCL (GPIO_NUM_18)
@@ -47,7 +48,15 @@
#endif
#endif
-#define I2C_DEFAULT_TIMEOUT_US (10000) // 10ms
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+#define I2C_SCLK_FREQ XTAL_CLK_FREQ
+#elif CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
+#define I2C_SCLK_FREQ I2C_APB_CLK_FREQ
+#else
+#error "unsupported I2C for ESP32 SoC variant"
+#endif
+
+#define I2C_DEFAULT_TIMEOUT_US (50000) // 50ms
typedef struct _machine_hw_i2c_obj_t {
mp_obj_base_t base;
@@ -71,7 +80,8 @@ STATIC void machine_hw_i2c_init(machine_hw_i2c_obj_t *self, uint32_t freq, uint3
.master.clk_speed = freq,
};
i2c_param_config(self->port, &conf);
- i2c_set_timeout(self->port, I2C_APB_CLK_FREQ / 1000000 * timeout_us);
+ int timeout = I2C_SCLK_FREQ / 1000000 * timeout_us;
+ i2c_set_timeout(self->port, (timeout > I2C_LL_MAX_TIMEOUT) ? I2C_LL_MAX_TIMEOUT : timeout);
i2c_driver_install(self->port, I2C_MODE_MASTER, 0, 0, 0);
}
@@ -109,7 +119,7 @@ int machine_hw_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_
}
// TODO proper timeout
- esp_err_t err = i2c_master_cmd_begin(self->port, cmd, 100 * (1 + data_len) / portTICK_RATE_MS);
+ esp_err_t err = i2c_master_cmd_begin(self->port, cmd, 100 * (1 + data_len) / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (err == ESP_FAIL) {
@@ -131,7 +141,7 @@ STATIC void machine_hw_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_p
int h, l;
i2c_get_period(self->port, &h, &l);
mp_printf(print, "I2C(%u, scl=%u, sda=%u, freq=%u)",
- self->port, self->scl, self->sda, I2C_APB_CLK_FREQ / (h + l));
+ self->port, self->scl, self->sda, I2C_SCLK_FREQ / (h + l));
}
mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
@@ -161,7 +171,7 @@ mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_
bool first_init = false;
if (self->base.type == NULL) {
// Created for the first time, set default pins
- self->base.type = &machine_hw_i2c_type;
+ self->base.type = &machine_i2c_type;
self->port = i2c_id;
if (self->port == I2C_NUM_0) {
self->scl = MICROPY_HW_I2C0_SCL;
@@ -175,10 +185,10 @@ mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_
// Set SCL/SDA pins if given
if (args[ARG_scl].u_obj != MP_OBJ_NULL) {
- self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj);
+ self->scl = machine_pin_get_id(args[ARG_scl].u_obj);
}
if (args[ARG_sda].u_obj != MP_OBJ_NULL) {
- self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj);
+ self->sda = machine_pin_get_id(args[ARG_sda].u_obj);
}
// Initialise the I2C peripheral
@@ -192,11 +202,12 @@ STATIC const mp_machine_i2c_p_t machine_hw_i2c_p = {
.transfer = machine_hw_i2c_transfer,
};
-const mp_obj_type_t machine_hw_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = machine_hw_i2c_print,
- .make_new = machine_hw_i2c_make_new,
- .protocol = &machine_hw_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hw_i2c_make_new,
+ print, machine_hw_i2c_print,
+ protocol, &machine_hw_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c
index 8832ad5e90733..95751c87c3e60 100644
--- a/ports/esp32/machine_i2s.c
+++ b/ports/esp32/machine_i2s.c
@@ -61,9 +61,9 @@
// - a FreeRTOS task is created to implement the asynchronous background operations
// - a FreeRTOS queue is used to transfer the supplied buffer to the background task
//
-// Mode3: Uasyncio
+// Mode3: Asyncio
// - implements the stream protocol
-// - uasyncio mode is enabled when the ioctl() function is called
+// - asyncio mode is enabled when the ioctl() function is called
// - the I2S event queue is used to detect that I2S samples can be read or written from/to DMA memory
//
// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention:
@@ -102,7 +102,7 @@ typedef enum {
typedef enum {
BLOCKING,
NON_BLOCKING,
- UASYNCIO
+ ASYNCIO
} io_mode_t;
typedef enum {
@@ -148,7 +148,7 @@ STATIC const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYT
};
void machine_i2s_init0() {
- for (i2s_port_t p = 0; p < I2S_NUM_MAX; p++) {
+ for (i2s_port_t p = 0; p < I2S_NUM_AUTO; p++) {
MP_STATE_PORT(machine_i2s_obj)[p] = NULL;
}
}
@@ -240,7 +240,7 @@ STATIC uint32_t fill_appbuf_from_dma(machine_i2s_obj_t *self, mp_buffer_info_t *
// copy audio samples from DMA memory to the app buffer
// audio samples are read from DMA memory in chunks
// loop, reading and copying chunks until the app buffer is filled
- // For uasyncio mode, the loop will make an early exit if DMA memory becomes empty
+ // For asyncio mode, the loop will make an early exit if DMA memory becomes empty
// Example:
// a MicroPython I2S object is configured for 16-bit mono (2 bytes per audio sample).
// For every frame coming from DMA (8 bytes), 2 bytes are "cherry picked" and
@@ -257,7 +257,7 @@ STATIC uint32_t fill_appbuf_from_dma(machine_i2s_obj_t *self, mp_buffer_info_t *
size_t num_bytes_received_from_dma = 0;
TickType_t delay;
- if (self->io_mode == UASYNCIO) {
+ if (self->io_mode == ASYNCIO) {
delay = 0; // stop i2s_read() operation if DMA memory becomes empty
} else {
delay = portMAX_DELAY; // block until supplied buffer is filled
@@ -269,15 +269,6 @@ STATIC uint32_t fill_appbuf_from_dma(machine_i2s_obj_t *self, mp_buffer_info_t *
num_bytes_requested_from_dma,
&num_bytes_received_from_dma,
delay);
-
- // the following is a workaround for a bug in ESP-IDF v4.4
- // https://github.com/espressif/esp-idf/issues/8121
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 4)
- if ((delay != portMAX_DELAY) && (ret == ESP_ERR_TIMEOUT)) {
- ret = ESP_OK;
- }
- #endif
-
check_esp_err(ret);
// process the transform buffer one frame at a time.
@@ -307,7 +298,7 @@ STATIC uint32_t fill_appbuf_from_dma(machine_i2s_obj_t *self, mp_buffer_info_t *
num_bytes_needed_from_dma -= num_bytes_received_from_dma;
- if ((self->io_mode == UASYNCIO) && (num_bytes_received_from_dma < num_bytes_requested_from_dma)) {
+ if ((self->io_mode == ASYNCIO) && (num_bytes_received_from_dma < num_bytes_requested_from_dma)) {
// Unable to fill the entire app buffer from DMA memory. This indicates all DMA RX buffers are empty.
// Clear the I2S event queue so ioctl() indicates that the I2S object cannot currently
// supply more audio samples
@@ -327,32 +318,23 @@ STATIC size_t copy_appbuf_to_dma(machine_i2s_obj_t *self, mp_buffer_info_t *appb
size_t num_bytes_written = 0;
TickType_t delay;
- if (self->io_mode == UASYNCIO) {
+ if (self->io_mode == ASYNCIO) {
delay = 0; // stop i2s_write() operation if DMA memory becomes full
} else {
delay = portMAX_DELAY; // block until supplied buffer is emptied
}
esp_err_t ret = i2s_write(self->port, appbuf->buf, appbuf->len, &num_bytes_written, delay);
-
- // the following is a workaround for a bug in ESP-IDF v4.4
- // https://github.com/espressif/esp-idf/issues/8121
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 4)
- if ((delay != portMAX_DELAY) && (ret == ESP_ERR_TIMEOUT)) {
- ret = ESP_OK;
- }
- #endif
-
check_esp_err(ret);
- if ((self->io_mode == UASYNCIO) && (num_bytes_written < appbuf->len)) {
+ if ((self->io_mode == ASYNCIO) && (num_bytes_written < appbuf->len)) {
// Unable to empty the entire app buffer into DMA memory. This indicates all DMA TX buffers are full.
// Clear the I2S event queue so ioctl() indicates that the I2S object cannot currently
// accept more audio samples
xQueueReset(self->i2s_event_queue);
// Undo the swap transformation as the buffer has not been completely emptied.
- // The uasyncio stream writer will use the same buffer in a future write call.
+ // The asyncio stream writer will use the same buffer in a future write call.
if ((self->bits == I2S_BITS_PER_SAMPLE_32BIT) && (self->format == STEREO)) {
swap_32_bit_stereo_channels(appbuf);
}
@@ -410,9 +392,9 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args,
//
// are Pins valid?
- int8_t sck = args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : mp_hal_get_pin_obj(args[ARG_sck].u_obj);
- int8_t ws = args[ARG_ws].u_obj == MP_OBJ_NULL ? -1 : mp_hal_get_pin_obj(args[ARG_ws].u_obj);
- int8_t sd = args[ARG_sd].u_obj == MP_OBJ_NULL ? -1 : mp_hal_get_pin_obj(args[ARG_sd].u_obj);
+ int8_t sck = args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj);
+ int8_t ws = args[ARG_ws].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_ws].u_obj);
+ int8_t sd = args[ARG_sd].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sd].u_obj);
// is Mode valid?
i2s_mode_t mode = args[ARG_mode].u_int;
@@ -467,10 +449,8 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args,
i2s_config.use_apll = false;
i2s_config.tx_desc_auto_clear = true;
i2s_config.fixed_mclk = 0;
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 4)
- i2s_config.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT;
+ i2s_config.mclk_multiple = I2S_MCLK_MULTIPLE_256;
i2s_config.bits_per_chan = 0;
- #endif
// I2S queue size equals the number of DMA buffers
check_esp_err(i2s_driver_install(self->port, &i2s_config, i2s_config.dma_buf_count, &self->i2s_event_queue));
@@ -487,9 +467,7 @@ STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args,
#endif
i2s_pin_config_t pin_config;
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 4)
pin_config.mck_io_num = I2S_PIN_NO_CHANGE;
- #endif
pin_config.bck_io_num = self->sck;
pin_config.ws_io_num = self->ws;
@@ -527,13 +505,14 @@ STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_arg
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
i2s_port_t port = mp_obj_get_int(args[0]);
- if (port < 0 || port >= I2S_NUM_MAX) {
+ if (port < 0 || port >= I2S_NUM_AUTO) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid id"));
}
machine_i2s_obj_t *self;
if (MP_STATE_PORT(machine_i2s_obj)[port] == NULL) {
- self = mp_obj_malloc(machine_i2s_obj_t, &machine_i2s_type);
+ self = m_new_obj_with_finaliser(machine_i2s_obj_t);
+ self->base.type = &machine_i2s_type;
MP_STATE_PORT(machine_i2s_obj)[port] = self;
self->port = port;
} else {
@@ -688,6 +667,7 @@ STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2s_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2s_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_i2s_deinit_obj) },
// Static method
{ MP_ROM_QSTR(MP_QSTR_shift), MP_ROM_PTR(&machine_i2s_shift_obj) },
@@ -727,7 +707,7 @@ STATIC mp_uint_t machine_i2s_stream_read(mp_obj_t self_in, void *buf_in, mp_uint
// send the descriptor to the task that handles non-blocking mode
xQueueSend(self->non_blocking_mode_queue, &descriptor, 0);
return size;
- } else { // blocking or uasyncio mode
+ } else { // blocking or asyncio mode
mp_buffer_info_t appbuf;
appbuf.buf = (void *)buf_in;
appbuf.len = size;
@@ -757,7 +737,7 @@ STATIC mp_uint_t machine_i2s_stream_write(mp_obj_t self_in, const void *buf_in,
// send the descriptor to the task that handles non-blocking mode
xQueueSend(self->non_blocking_mode_queue, &descriptor, 0);
return size;
- } else { // blocking or uasyncio mode
+ } else { // blocking or asyncio mode
mp_buffer_info_t appbuf;
appbuf.buf = (void *)buf_in;
appbuf.len = size;
@@ -770,7 +750,7 @@ STATIC mp_uint_t machine_i2s_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_uint_t ret;
mp_uint_t flags = arg;
- self->io_mode = UASYNCIO; // a call to ioctl() is an indication that uasyncio is being used
+ self->io_mode = ASYNCIO; // a call to ioctl() is an indication that asyncio is being used
if (request == MP_STREAM_POLL) {
ret = 0;
@@ -829,15 +809,16 @@ STATIC const mp_stream_p_t i2s_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_i2s_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2S,
- .print = machine_i2s_print,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &i2s_stream_p,
- .make_new = machine_i2s_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2s_type,
+ MP_QSTR_I2S,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_i2s_make_new,
+ print, machine_i2s_print,
+ protocol, &i2s_stream_p,
+ locals_dict, &machine_i2s_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_AUTO]);
#endif // MICROPY_PY_MACHINE_I2S
diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c
index 865face96f2ad..835f16b1b066b 100644
--- a/ports/esp32/machine_pin.c
+++ b/ports/esp32/machine_pin.c
@@ -5,7 +5,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George
+ * Copyright (c) 2016-2023 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
@@ -31,14 +31,17 @@
#include "driver/gpio.h"
#include "driver/rtc_io.h"
+#include "hal/gpio_ll.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "mphalport.h"
#include "modmachine.h"
#include "extmod/virtpin.h"
+#include "machine_pin.h"
#include "machine_rtc.h"
#include "modesp32.h"
+#include "genhdr/pins.h"
#if CONFIG_IDF_TARGET_ESP32C3
#include "soc/usb_serial_jtag_reg.h"
@@ -54,178 +57,18 @@
#define GPIO_FIRST_NON_OUTPUT (46)
#endif
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- gpio_num_t id;
-} machine_pin_obj_t;
-
-typedef struct _machine_pin_irq_obj_t {
- mp_obj_base_t base;
- gpio_num_t id;
-} machine_pin_irq_obj_t;
-
-STATIC const machine_pin_obj_t machine_pin_obj[] = {
- #if CONFIG_IDF_TARGET_ESP32
-
- {{&machine_pin_type}, GPIO_NUM_0},
- {{&machine_pin_type}, GPIO_NUM_1},
- {{&machine_pin_type}, GPIO_NUM_2},
- {{&machine_pin_type}, GPIO_NUM_3},
- {{&machine_pin_type}, GPIO_NUM_4},
- {{&machine_pin_type}, GPIO_NUM_5},
- {{&machine_pin_type}, GPIO_NUM_6},
- {{&machine_pin_type}, GPIO_NUM_7},
- {{&machine_pin_type}, GPIO_NUM_8},
- {{&machine_pin_type}, GPIO_NUM_9},
- {{&machine_pin_type}, GPIO_NUM_10},
- {{&machine_pin_type}, GPIO_NUM_11},
- {{&machine_pin_type}, GPIO_NUM_12},
- {{&machine_pin_type}, GPIO_NUM_13},
- {{&machine_pin_type}, GPIO_NUM_14},
- {{&machine_pin_type}, GPIO_NUM_15},
- #if CONFIG_ESP32_SPIRAM_SUPPORT
- {{NULL}, -1},
- {{NULL}, -1},
- #else
- {{&machine_pin_type}, GPIO_NUM_16},
- {{&machine_pin_type}, GPIO_NUM_17},
- #endif
- {{&machine_pin_type}, GPIO_NUM_18},
- {{&machine_pin_type}, GPIO_NUM_19},
- #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 2)
- {{&machine_pin_type}, GPIO_NUM_20},
- #else
- {{NULL}, -1},
- #endif
- {{&machine_pin_type}, GPIO_NUM_21},
- {{&machine_pin_type}, GPIO_NUM_22},
- {{&machine_pin_type}, GPIO_NUM_23},
- {{NULL}, -1},
- {{&machine_pin_type}, GPIO_NUM_25},
- {{&machine_pin_type}, GPIO_NUM_26},
- {{&machine_pin_type}, GPIO_NUM_27},
- {{NULL}, -1},
- {{NULL}, -1},
- {{NULL}, -1},
- {{NULL}, -1},
- {{&machine_pin_type}, GPIO_NUM_32},
- {{&machine_pin_type}, GPIO_NUM_33},
- {{&machine_pin_type}, GPIO_NUM_34},
- {{&machine_pin_type}, GPIO_NUM_35},
- {{&machine_pin_type}, GPIO_NUM_36},
- {{&machine_pin_type}, GPIO_NUM_37},
- {{&machine_pin_type}, GPIO_NUM_38},
- {{&machine_pin_type}, GPIO_NUM_39},
-
- #elif CONFIG_IDF_TARGET_ESP32C3
-
- {{&machine_pin_type}, GPIO_NUM_0},
- {{&machine_pin_type}, GPIO_NUM_1},
- {{&machine_pin_type}, GPIO_NUM_2},
- {{&machine_pin_type}, GPIO_NUM_3},
- {{&machine_pin_type}, GPIO_NUM_4},
- {{&machine_pin_type}, GPIO_NUM_5},
- {{&machine_pin_type}, GPIO_NUM_6},
- {{&machine_pin_type}, GPIO_NUM_7},
- {{&machine_pin_type}, GPIO_NUM_8},
- {{&machine_pin_type}, GPIO_NUM_9},
- {{&machine_pin_type}, GPIO_NUM_10},
- {{&machine_pin_type}, GPIO_NUM_11},
- {{&machine_pin_type}, GPIO_NUM_12},
- {{&machine_pin_type}, GPIO_NUM_13},
- {{NULL}, -1}, // 14 FLASH
- {{NULL}, -1}, // 15 FLASH
- {{NULL}, -1}, // 16 FLASH
- {{NULL}, -1}, // 17 FLASH
- #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
- {{NULL}, -1}, // 18 is for native USB D-
- {{NULL}, -1}, // 19 is for native USB D+
- #else
- {{&machine_pin_type}, GPIO_NUM_18},
- {{&machine_pin_type}, GPIO_NUM_19},
- #endif
- {{&machine_pin_type}, GPIO_NUM_20},
- {{&machine_pin_type}, GPIO_NUM_21},
-
- #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-
- {{&machine_pin_type}, GPIO_NUM_0},
- {{&machine_pin_type}, GPIO_NUM_1},
- {{&machine_pin_type}, GPIO_NUM_2},
- {{&machine_pin_type}, GPIO_NUM_3},
- {{&machine_pin_type}, GPIO_NUM_4},
- {{&machine_pin_type}, GPIO_NUM_5},
- {{&machine_pin_type}, GPIO_NUM_6},
- {{&machine_pin_type}, GPIO_NUM_7},
- {{&machine_pin_type}, GPIO_NUM_8},
- {{&machine_pin_type}, GPIO_NUM_9},
- {{&machine_pin_type}, GPIO_NUM_10},
- {{&machine_pin_type}, GPIO_NUM_11},
- {{&machine_pin_type}, GPIO_NUM_12},
- {{&machine_pin_type}, GPIO_NUM_13},
- {{&machine_pin_type}, GPIO_NUM_14},
- {{&machine_pin_type}, GPIO_NUM_15},
- {{&machine_pin_type}, GPIO_NUM_16},
- {{&machine_pin_type}, GPIO_NUM_17},
- {{&machine_pin_type}, GPIO_NUM_18},
- #if CONFIG_USB_CDC_ENABLED
- {{NULL}, -1}, // 19 is for native USB D-
- {{NULL}, -1}, // 20 is for native USB D-
- #else
- {{&machine_pin_type}, GPIO_NUM_19},
- {{&machine_pin_type}, GPIO_NUM_20},
- #endif
- {{&machine_pin_type}, GPIO_NUM_21},
- {{NULL}, -1}, // 22 not a pin
- {{NULL}, -1}, // 23 not a pin
- {{NULL}, -1}, // 24 not a pin
- {{NULL}, -1}, // 25 not a pin
- #if CONFIG_SPIRAM
- {{NULL}, -1}, // 26 PSRAM
- #else
- {{&machine_pin_type}, GPIO_NUM_26},
- #endif
- {{NULL}, -1}, // 27 FLASH/PSRAM
- {{NULL}, -1}, // 28 FLASH/PSRAM
- {{NULL}, -1}, // 29 FLASH/PSRAM
- {{NULL}, -1}, // 30 FLASH/PSRAM
- {{NULL}, -1}, // 31 FLASH/PSRAM
- {{NULL}, -1}, // 32 FLASH/PSRAM
- #if CONFIG_SPIRAM_MODE_OCT
- {{NULL}, -1}, // 33 FLASH/PSRAM
- {{NULL}, -1}, // 34 FLASH/PSRAM
- {{NULL}, -1}, // 35 FLASH/PSRAM
- {{NULL}, -1}, // 36 FLASH/PSRAM
- {{NULL}, -1}, // 37 FLASH/PSRAM
- #else
- {{&machine_pin_type}, GPIO_NUM_33},
- {{&machine_pin_type}, GPIO_NUM_34},
- {{&machine_pin_type}, GPIO_NUM_35},
- {{&machine_pin_type}, GPIO_NUM_36},
- {{&machine_pin_type}, GPIO_NUM_37},
- #endif
- {{&machine_pin_type}, GPIO_NUM_38},
- {{&machine_pin_type}, GPIO_NUM_39}, // MTCLK
- {{&machine_pin_type}, GPIO_NUM_40}, // MTDO
- {{&machine_pin_type}, GPIO_NUM_41}, // MTDI
- {{&machine_pin_type}, GPIO_NUM_42}, // MTMS
- {{&machine_pin_type}, GPIO_NUM_43}, // U0TXD
- {{&machine_pin_type}, GPIO_NUM_44}, // U0RXD
- {{&machine_pin_type}, GPIO_NUM_45},
- {{&machine_pin_type}, GPIO_NUM_46},
-
- #endif
-
- #if CONFIG_IDF_TARGET_ESP32S3 && MICROPY_HW_ESP32S3_EXTENDED_IO
-
- {{&machine_pin_type}, GPIO_NUM_47},
- {{&machine_pin_type}, GPIO_NUM_48},
-
- #endif
-};
+// Return the gpio_num_t index for a given pin or pin-irq object.
+#define PIN_OBJ_INDEX(self) ((self) - &machine_pin_obj_table[0])
+#define PIN_IRQ_OBJ_INDEX(self) ((self) - &machine_pin_irq_obj_table[0])
-// forward declaration
-STATIC const machine_pin_irq_obj_t machine_pin_irq_object[];
+STATIC const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name) {
+ const mp_map_t *named_map = &named_pins->map;
+ mp_map_elem_t *named_elem = mp_map_lookup((mp_map_t *)named_map, name, MP_MAP_LOOKUP);
+ if (named_elem != NULL && named_elem->value != NULL) {
+ return MP_OBJ_TO_PTR(named_elem->value);
+ }
+ return NULL;
+}
void machine_pins_init(void) {
static bool did_install = false;
@@ -237,31 +80,55 @@ void machine_pins_init(void) {
}
void machine_pins_deinit(void) {
- for (int i = 0; i < MP_ARRAY_SIZE(machine_pin_obj); ++i) {
- if (machine_pin_obj[i].id != (gpio_num_t)-1) {
- gpio_isr_handler_remove(machine_pin_obj[i].id);
+ for (int i = 0; i < MP_ARRAY_SIZE(machine_pin_obj_table); ++i) {
+ if (machine_pin_obj_table[i].base.type != NULL) {
+ gpio_isr_handler_remove(i);
}
}
}
STATIC void machine_pin_isr_handler(void *arg) {
machine_pin_obj_t *self = arg;
- mp_obj_t handler = MP_STATE_PORT(machine_pin_irq_handler)[self->id];
+ mp_obj_t handler = MP_STATE_PORT(machine_pin_irq_handler)[PIN_OBJ_INDEX(self)];
mp_sched_schedule(handler, MP_OBJ_FROM_PTR(self));
mp_hal_wake_main_task_from_isr();
}
-gpio_num_t machine_pin_get_id(mp_obj_t pin_in) {
- if (mp_obj_get_type(pin_in) != &machine_pin_type) {
- mp_raise_ValueError(MP_ERROR_TEXT("expecting a pin"));
+STATIC const machine_pin_obj_t *machine_pin_find(mp_obj_t pin_in) {
+ if (mp_obj_is_type(pin_in, &machine_pin_type)) {
+ return pin_in;
+ }
+
+ // Try to find the pin via integer index into the array of all pins.
+ if (mp_obj_is_int(pin_in)) {
+ int wanted_pin = mp_obj_get_int(pin_in);
+ if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj_table)) {
+ const machine_pin_obj_t *self = (machine_pin_obj_t *)&machine_pin_obj_table[wanted_pin];
+ if (self->base.type != NULL) {
+ return self;
+ }
+ }
+ }
+
+ // Try to find the pin in the board pins dict.
+ if (mp_obj_is_str(pin_in)) {
+ const machine_pin_obj_t *self = machine_pin_find_named(&machine_pin_board_pins_locals_dict, pin_in);
+ if (self->base.type != NULL) {
+ return self;
+ }
}
- machine_pin_obj_t *self = pin_in;
- return self->id;
+
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
+}
+
+gpio_num_t machine_pin_get_id(mp_obj_t pin_in) {
+ const machine_pin_obj_t *self = machine_pin_find(pin_in);
+ return PIN_OBJ_INDEX(self);
}
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pin_obj_t *self = self_in;
- mp_printf(print, "Pin(%u)", self->id);
+ mp_printf(print, "Pin(%u)", PIN_OBJ_INDEX(self));
}
// pin.init(mode=None, pull=-1, *, value, drive, hold)
@@ -281,32 +148,32 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
// reset the pin to digital if this is a mode-setting init (grab it back from ADC)
if (args[ARG_mode].u_obj != mp_const_none) {
- if (rtc_gpio_is_valid_gpio(self->id)) {
+ if (rtc_gpio_is_valid_gpio(PIN_OBJ_INDEX(self))) {
#if !CONFIG_IDF_TARGET_ESP32C3
- rtc_gpio_deinit(self->id);
+ rtc_gpio_deinit(PIN_OBJ_INDEX(self));
#endif
}
}
#if CONFIG_IDF_TARGET_ESP32C3
- if (self->id == 18 || self->id == 19) {
+ if (PIN_OBJ_INDEX(self) == 18 || PIN_OBJ_INDEX(self) == 19) {
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
}
#endif
// configure the pin for gpio
- gpio_pad_select_gpio(self->id);
+ esp_rom_gpio_pad_select_gpio(PIN_OBJ_INDEX(self));
// set initial value (do this before configuring mode/pull)
if (args[ARG_value].u_obj != MP_OBJ_NULL) {
- gpio_set_level(self->id, mp_obj_is_true(args[ARG_value].u_obj));
+ gpio_set_level(PIN_OBJ_INDEX(self), mp_obj_is_true(args[ARG_value].u_obj));
}
// set drive capability (do this before configuring mode)
- if (args[ARG_drive].u_obj != MP_OBJ_NULL && GPIO_IS_VALID_OUTPUT_GPIO(self->id)) {
+ if (args[ARG_drive].u_obj != MP_OBJ_NULL && GPIO_IS_VALID_OUTPUT_GPIO(PIN_OBJ_INDEX(self))) {
mp_int_t strength = mp_obj_get_int(args[ARG_drive].u_obj);
if (0 <= strength && strength < GPIO_DRIVE_CAP_MAX) {
- gpio_set_drive_capability(self->id, strength);
+ gpio_set_drive_capability(PIN_OBJ_INDEX(self), strength);
}
}
@@ -314,11 +181,11 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
if (args[ARG_mode].u_obj != mp_const_none) {
mp_int_t pin_io_mode = mp_obj_get_int(args[ARG_mode].u_obj);
#ifdef GPIO_FIRST_NON_OUTPUT
- if (self->id >= GPIO_FIRST_NON_OUTPUT && (pin_io_mode & GPIO_MODE_DEF_OUTPUT)) {
+ if (PIN_OBJ_INDEX(self) >= GPIO_FIRST_NON_OUTPUT && (pin_io_mode & GPIO_MODE_DEF_OUTPUT)) {
mp_raise_ValueError(MP_ERROR_TEXT("pin can only be input"));
}
#endif
- gpio_set_direction(self->id, pin_io_mode);
+ gpio_set_direction(PIN_OBJ_INDEX(self), pin_io_mode);
}
// configure pull
@@ -328,24 +195,24 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
mode = mp_obj_get_int(args[ARG_pull].u_obj);
}
if (mode & GPIO_PULL_DOWN) {
- gpio_pulldown_en(self->id);
+ gpio_pulldown_en(PIN_OBJ_INDEX(self));
} else {
- gpio_pulldown_dis(self->id);
+ gpio_pulldown_dis(PIN_OBJ_INDEX(self));
}
if (mode & GPIO_PULL_UP) {
- gpio_pullup_en(self->id);
+ gpio_pullup_en(PIN_OBJ_INDEX(self));
} else {
- gpio_pullup_dis(self->id);
+ gpio_pullup_dis(PIN_OBJ_INDEX(self));
}
}
// configure pad hold
- if (args[ARG_hold].u_obj != MP_OBJ_NULL && GPIO_IS_VALID_OUTPUT_GPIO(self->id)) {
+ if (args[ARG_hold].u_obj != MP_OBJ_NULL && GPIO_IS_VALID_OUTPUT_GPIO(PIN_OBJ_INDEX(self))) {
// always disable pad hold to apply outstanding config changes
- gpio_hold_dis(self->id);
+ gpio_hold_dis(PIN_OBJ_INDEX(self));
// (re-)enable pad hold if requested
if (mp_obj_is_true(args[ARG_hold].u_obj)) {
- gpio_hold_en(self->id);
+ gpio_hold_en(PIN_OBJ_INDEX(self));
}
}
@@ -357,14 +224,7 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted pin object
- int wanted_pin = mp_obj_get_int(args[0]);
- const machine_pin_obj_t *self = NULL;
- if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) {
- self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin];
- }
- if (self == NULL || self->base.type == NULL) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
- }
+ const machine_pin_obj_t *self = machine_pin_find(args[0]);
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
@@ -382,10 +242,10 @@ STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
machine_pin_obj_t *self = self_in;
if (n_args == 0) {
// get pin
- return MP_OBJ_NEW_SMALL_INT(gpio_get_level(self->id));
+ return MP_OBJ_NEW_SMALL_INT(gpio_get_level(PIN_OBJ_INDEX(self)));
} else {
// set pin
- gpio_set_level(self->id, mp_obj_is_true(args[0]));
+ gpio_set_level(PIN_OBJ_INDEX(self), mp_obj_is_true(args[0]));
return mp_const_none;
}
}
@@ -405,7 +265,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_
// pin.off()
STATIC mp_obj_t machine_pin_off(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_level(self->id, 0);
+ gpio_set_level(PIN_OBJ_INDEX(self), 0);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off);
@@ -413,7 +273,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_off_obj, machine_pin_off);
// pin.on()
STATIC mp_obj_t machine_pin_on(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_level(self->id, 1);
+ gpio_set_level(PIN_OBJ_INDEX(self), 1);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on);
@@ -423,7 +283,7 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
enum { ARG_handler, ARG_trigger, ARG_wake };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE} },
+ { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_INTR_POSEDGE | GPIO_INTR_NEGEDGE} },
{ MP_QSTR_wake, MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
@@ -436,7 +296,7 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
uint32_t trigger = args[ARG_trigger].u_int;
mp_obj_t wake_obj = args[ARG_wake].u_obj;
- if ((trigger == GPIO_PIN_INTR_LOLEVEL || trigger == GPIO_PIN_INTR_HILEVEL) && wake_obj != mp_const_none) {
+ if ((trigger == GPIO_INTR_LOW_LEVEL || trigger == GPIO_INTR_HIGH_LEVEL) && wake_obj != mp_const_none) {
mp_int_t wake;
if (mp_obj_get_int_maybe(wake_obj, &wake)) {
if (wake < 2 || wake > 7) {
@@ -450,20 +310,20 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
mp_raise_ValueError(MP_ERROR_TEXT("no resources"));
}
- if (!RTC_IS_VALID_EXT_PIN(self->id)) {
+ if (!RTC_IS_VALID_EXT_PIN(PIN_OBJ_INDEX(self))) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for wake"));
}
if (machine_rtc_config.ext0_pin == -1) {
- machine_rtc_config.ext0_pin = self->id;
- } else if (machine_rtc_config.ext0_pin != self->id) {
+ machine_rtc_config.ext0_pin = PIN_OBJ_INDEX(self);
+ } else if (machine_rtc_config.ext0_pin != PIN_OBJ_INDEX(self)) {
mp_raise_ValueError(MP_ERROR_TEXT("no resources"));
}
- machine_rtc_config.ext0_level = trigger == GPIO_PIN_INTR_LOLEVEL ? 0 : 1;
+ machine_rtc_config.ext0_level = trigger == GPIO_INTR_LOW_LEVEL ? 0 : 1;
machine_rtc_config.ext0_wake_types = wake;
} else {
- if (machine_rtc_config.ext0_pin == self->id) {
+ if (machine_rtc_config.ext0_pin == PIN_OBJ_INDEX(self)) {
machine_rtc_config.ext0_pin = -1;
}
@@ -471,18 +331,25 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
handler = MP_OBJ_NULL;
trigger = 0;
}
- gpio_isr_handler_remove(self->id);
- MP_STATE_PORT(machine_pin_irq_handler)[self->id] = handler;
- gpio_set_intr_type(self->id, trigger);
- gpio_isr_handler_add(self->id, machine_pin_isr_handler, (void *)self);
+ gpio_isr_handler_remove(PIN_OBJ_INDEX(self));
+ MP_STATE_PORT(machine_pin_irq_handler)[PIN_OBJ_INDEX(self)] = handler;
+ gpio_set_intr_type(PIN_OBJ_INDEX(self), trigger);
+ gpio_isr_handler_add(PIN_OBJ_INDEX(self), machine_pin_isr_handler, (void *)self);
}
}
// return the irq object
- return MP_OBJ_FROM_PTR(&machine_pin_irq_object[self->id]);
+ return MP_OBJ_FROM_PTR(&machine_pin_irq_obj_table[PIN_OBJ_INDEX(self)]);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &machine_pin_board_pins_locals_dict
+ );
+
STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
// instance methods
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) },
@@ -491,16 +358,19 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
+ // class attributes
+ { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&machine_pin_board_pins_obj_type) },
+
// class constants
{ MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) },
{ MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) },
{ MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) },
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) },
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) },
- { MP_ROM_QSTR(MP_QSTR_WAKE_LOW), MP_ROM_INT(GPIO_PIN_INTR_LOLEVEL) },
- { MP_ROM_QSTR(MP_QSTR_WAKE_HIGH), MP_ROM_INT(GPIO_PIN_INTR_HILEVEL) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_INTR_POSEDGE) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_INTR_NEGEDGE) },
+ { MP_ROM_QSTR(MP_QSTR_WAKE_LOW), MP_ROM_INT(GPIO_INTR_LOW_LEVEL) },
+ { MP_ROM_QSTR(MP_QSTR_WAKE_HIGH), MP_ROM_INT(GPIO_INTR_HIGH_LEVEL) },
{ MP_ROM_QSTR(MP_QSTR_DRIVE_0), MP_ROM_INT(GPIO_DRIVE_CAP_0) },
{ MP_ROM_QSTR(MP_QSTR_DRIVE_1), MP_ROM_INT(GPIO_DRIVE_CAP_1) },
{ MP_ROM_QSTR(MP_QSTR_DRIVE_2), MP_ROM_INT(GPIO_DRIVE_CAP_2) },
@@ -513,10 +383,10 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i
switch (request) {
case MP_PIN_READ: {
- return gpio_get_level(self->id);
+ return gpio_get_level(PIN_OBJ_INDEX(self));
}
case MP_PIN_WRITE: {
- gpio_set_level(self->id, arg);
+ gpio_set_level(PIN_OBJ_INDEX(self), arg);
return 0;
}
}
@@ -529,189 +399,33 @@ STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
-const mp_obj_type_t machine_pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = machine_pin_print,
- .make_new = mp_pin_make_new,
- .call = machine_pin_call,
- .protocol = &pin_pin_p,
- .locals_dict = (mp_obj_t)&machine_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, machine_pin_print,
+ call, machine_pin_call,
+ protocol, &pin_pin_p,
+ locals_dict, &machine_pin_locals_dict
+ );
/******************************************************************************/
// Pin IRQ object
-STATIC const mp_obj_type_t machine_pin_irq_type;
-
-STATIC const machine_pin_irq_obj_t machine_pin_irq_object[] = {
- #if CONFIG_IDF_TARGET_ESP32
-
- {{&machine_pin_irq_type}, GPIO_NUM_0},
- {{&machine_pin_irq_type}, GPIO_NUM_1},
- {{&machine_pin_irq_type}, GPIO_NUM_2},
- {{&machine_pin_irq_type}, GPIO_NUM_3},
- {{&machine_pin_irq_type}, GPIO_NUM_4},
- {{&machine_pin_irq_type}, GPIO_NUM_5},
- {{&machine_pin_irq_type}, GPIO_NUM_6},
- {{&machine_pin_irq_type}, GPIO_NUM_7},
- {{&machine_pin_irq_type}, GPIO_NUM_8},
- {{&machine_pin_irq_type}, GPIO_NUM_9},
- {{&machine_pin_irq_type}, GPIO_NUM_10},
- {{&machine_pin_irq_type}, GPIO_NUM_11},
- {{&machine_pin_irq_type}, GPIO_NUM_12},
- {{&machine_pin_irq_type}, GPIO_NUM_13},
- {{&machine_pin_irq_type}, GPIO_NUM_14},
- {{&machine_pin_irq_type}, GPIO_NUM_15},
- #if CONFIG_ESP32_SPIRAM_SUPPORT
- {{NULL}, -1},
- {{NULL}, -1},
- #else
- {{&machine_pin_irq_type}, GPIO_NUM_16},
- {{&machine_pin_irq_type}, GPIO_NUM_17},
- #endif
- {{&machine_pin_irq_type}, GPIO_NUM_18},
- {{&machine_pin_irq_type}, GPIO_NUM_19},
- #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 2)
- {{&machine_pin_irq_type}, GPIO_NUM_20},
- #else
- {{NULL}, -1},
- #endif
- {{&machine_pin_irq_type}, GPIO_NUM_21},
- {{&machine_pin_irq_type}, GPIO_NUM_22},
- {{&machine_pin_irq_type}, GPIO_NUM_23},
- {{NULL}, -1},
- {{&machine_pin_irq_type}, GPIO_NUM_25},
- {{&machine_pin_irq_type}, GPIO_NUM_26},
- {{&machine_pin_irq_type}, GPIO_NUM_27},
- {{NULL}, -1},
- {{NULL}, -1},
- {{NULL}, -1},
- {{NULL}, -1},
- {{&machine_pin_irq_type}, GPIO_NUM_32},
- {{&machine_pin_irq_type}, GPIO_NUM_33},
- {{&machine_pin_irq_type}, GPIO_NUM_34},
- {{&machine_pin_irq_type}, GPIO_NUM_35},
- {{&machine_pin_irq_type}, GPIO_NUM_36},
- {{&machine_pin_irq_type}, GPIO_NUM_37},
- {{&machine_pin_irq_type}, GPIO_NUM_38},
- {{&machine_pin_irq_type}, GPIO_NUM_39},
-
- #elif CONFIG_IDF_TARGET_ESP32C3
-
- {{&machine_pin_irq_type}, GPIO_NUM_0},
- {{&machine_pin_irq_type}, GPIO_NUM_1},
- {{&machine_pin_irq_type}, GPIO_NUM_2},
- {{&machine_pin_irq_type}, GPIO_NUM_3},
- {{&machine_pin_irq_type}, GPIO_NUM_4},
- {{&machine_pin_irq_type}, GPIO_NUM_5},
- {{&machine_pin_irq_type}, GPIO_NUM_6},
- {{&machine_pin_irq_type}, GPIO_NUM_7},
- {{&machine_pin_irq_type}, GPIO_NUM_8},
- {{&machine_pin_irq_type}, GPIO_NUM_9},
- {{&machine_pin_irq_type}, GPIO_NUM_10},
- {{&machine_pin_irq_type}, GPIO_NUM_11},
- {{&machine_pin_irq_type}, GPIO_NUM_12},
- {{&machine_pin_irq_type}, GPIO_NUM_13},
- {{&machine_pin_irq_type}, GPIO_NUM_14},
- {{&machine_pin_irq_type}, GPIO_NUM_15},
- {{&machine_pin_irq_type}, GPIO_NUM_16},
- {{&machine_pin_irq_type}, GPIO_NUM_17},
- {{&machine_pin_irq_type}, GPIO_NUM_18},
- {{&machine_pin_irq_type}, GPIO_NUM_19},
- {{&machine_pin_irq_type}, GPIO_NUM_20},
- {{&machine_pin_irq_type}, GPIO_NUM_21},
-
- #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-
- {{&machine_pin_irq_type}, GPIO_NUM_0},
- {{&machine_pin_irq_type}, GPIO_NUM_1},
- {{&machine_pin_irq_type}, GPIO_NUM_2},
- {{&machine_pin_irq_type}, GPIO_NUM_3},
- {{&machine_pin_irq_type}, GPIO_NUM_4},
- {{&machine_pin_irq_type}, GPIO_NUM_5},
- {{&machine_pin_irq_type}, GPIO_NUM_6},
- {{&machine_pin_irq_type}, GPIO_NUM_7},
- {{&machine_pin_irq_type}, GPIO_NUM_8},
- {{&machine_pin_irq_type}, GPIO_NUM_9},
- {{&machine_pin_irq_type}, GPIO_NUM_10},
- {{&machine_pin_irq_type}, GPIO_NUM_11},
- {{&machine_pin_irq_type}, GPIO_NUM_12},
- {{&machine_pin_irq_type}, GPIO_NUM_13},
- {{&machine_pin_irq_type}, GPIO_NUM_14},
- {{&machine_pin_irq_type}, GPIO_NUM_15},
- {{&machine_pin_irq_type}, GPIO_NUM_16},
- {{&machine_pin_irq_type}, GPIO_NUM_17},
- {{&machine_pin_irq_type}, GPIO_NUM_18},
- #if CONFIG_USB_CDC_ENABLED
- {{NULL}, -1}, // 19 is for native USB D-
- {{NULL}, -1}, // 20 is for native USB D-
- #else
- {{&machine_pin_irq_type}, GPIO_NUM_19},
- {{&machine_pin_irq_type}, GPIO_NUM_20},
- #endif
- {{&machine_pin_irq_type}, GPIO_NUM_21},
- {{NULL}, -1}, // 22 not a pin
- {{NULL}, -1}, // 23 not a pin
- {{NULL}, -1}, // 24 not a pin
- {{NULL}, -1}, // 25 not a pin
- #if CONFIG_SPIRAM
- {{NULL}, -1}, // 26 PSRAM
- #else
- {{&machine_pin_irq_type}, GPIO_NUM_26},
- #endif
- {{NULL}, -1}, // 27 FLASH/PSRAM
- {{NULL}, -1}, // 28 FLASH/PSRAM
- {{NULL}, -1}, // 29 FLASH/PSRAM
- {{NULL}, -1}, // 30 FLASH/PSRAM
- {{NULL}, -1}, // 31 FLASH/PSRAM
- {{NULL}, -1}, // 32 FLASH/PSRAM
- #if CONFIG_SPIRAM_MODE_OCT
- {{NULL}, -1}, // 33 FLASH/PSRAM
- {{NULL}, -1}, // 34 FLASH/PSRAM
- {{NULL}, -1}, // 35 FLASH/PSRAM
- {{NULL}, -1}, // 36 FLASH/PSRAM
- {{NULL}, -1}, // 37 FLASH/PSRAM
- #else
- {{&machine_pin_irq_type}, GPIO_NUM_33},
- {{&machine_pin_irq_type}, GPIO_NUM_34},
- {{&machine_pin_irq_type}, GPIO_NUM_35},
- {{&machine_pin_irq_type}, GPIO_NUM_36},
- {{&machine_pin_irq_type}, GPIO_NUM_37},
- #endif
- {{&machine_pin_irq_type}, GPIO_NUM_38},
- {{&machine_pin_irq_type}, GPIO_NUM_39},
- {{&machine_pin_irq_type}, GPIO_NUM_40},
- {{&machine_pin_irq_type}, GPIO_NUM_41},
- {{&machine_pin_irq_type}, GPIO_NUM_42},
- {{&machine_pin_irq_type}, GPIO_NUM_43},
- {{&machine_pin_irq_type}, GPIO_NUM_44},
- {{&machine_pin_irq_type}, GPIO_NUM_45},
- {{&machine_pin_irq_type}, GPIO_NUM_46},
-
- #endif
-
- #if CONFIG_IDF_TARGET_ESP32S3 && MICROPY_HW_ESP32S3_EXTENDED_IO
-
- {{&machine_pin_irq_type}, GPIO_NUM_47},
- {{&machine_pin_irq_type}, GPIO_NUM_48},
-
- #endif
-};
-
STATIC mp_obj_t machine_pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
machine_pin_irq_obj_t *self = self_in;
mp_arg_check_num(n_args, n_kw, 0, 0, false);
- machine_pin_isr_handler((void *)&machine_pin_obj[self->id]);
+ machine_pin_isr_handler((void *)&machine_pin_obj_table[PIN_IRQ_OBJ_INDEX(self)]);
return mp_const_none;
}
STATIC mp_obj_t machine_pin_irq_trigger(size_t n_args, const mp_obj_t *args) {
machine_pin_irq_obj_t *self = args[0];
- uint32_t orig_trig = GPIO.pin[self->id].int_type;
+ uint32_t orig_trig = GPIO.pin[PIN_IRQ_OBJ_INDEX(self)].int_type;
if (n_args == 2) {
// set trigger
- gpio_set_intr_type(self->id, mp_obj_get_int(args[1]));
+ gpio_set_intr_type(PIN_IRQ_OBJ_INDEX(self), mp_obj_get_int(args[1]));
}
// return original trigger value
return MP_OBJ_NEW_SMALL_INT(orig_trig);
@@ -723,9 +437,12 @@ STATIC const mp_rom_map_elem_t machine_pin_irq_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_irq_locals_dict, machine_pin_irq_locals_dict_table);
-STATIC const mp_obj_type_t machine_pin_irq_type = {
- { &mp_type_type },
- .name = MP_QSTR_IRQ,
- .call = machine_pin_irq_call,
- .locals_dict = (mp_obj_dict_t *)&machine_pin_irq_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_irq_type,
+ MP_QSTR_IRQ,
+ MP_TYPE_FLAG_NONE,
+ call, machine_pin_irq_call,
+ locals_dict, &machine_pin_irq_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t machine_pin_irq_handler[GPIO_PIN_COUNT]);
diff --git a/ports/esp32/machine_pin.h b/ports/esp32/machine_pin.h
new file mode 100644
index 0000000000000..dbbaac2219be9
--- /dev/null
+++ b/ports/esp32/machine_pin.h
@@ -0,0 +1,164 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 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_ESP32_MACHINE_PIN_H
+#define MICROPY_INCLUDED_ESP32_MACHINE_PIN_H
+
+#include "py/obj.h"
+#include "hal/gpio_types.h"
+
+// Define which pins are enabled for a given SoC and configuration.
+
+#if CONFIG_IDF_TARGET_ESP32
+
+#define MICROPY_HW_ENABLE_GPIO0 (1)
+#define MICROPY_HW_ENABLE_GPIO1 (1)
+#define MICROPY_HW_ENABLE_GPIO2 (1)
+#define MICROPY_HW_ENABLE_GPIO3 (1)
+#define MICROPY_HW_ENABLE_GPIO4 (1)
+#define MICROPY_HW_ENABLE_GPIO5 (1)
+#define MICROPY_HW_ENABLE_GPIO6 (1)
+#define MICROPY_HW_ENABLE_GPIO7 (1)
+#define MICROPY_HW_ENABLE_GPIO8 (1)
+#define MICROPY_HW_ENABLE_GPIO9 (1)
+#define MICROPY_HW_ENABLE_GPIO10 (1)
+#define MICROPY_HW_ENABLE_GPIO11 (1)
+#define MICROPY_HW_ENABLE_GPIO12 (1)
+#define MICROPY_HW_ENABLE_GPIO13 (1)
+#define MICROPY_HW_ENABLE_GPIO14 (1)
+#define MICROPY_HW_ENABLE_GPIO15 (1)
+#if !CONFIG_ESP32_SPIRAM_SUPPORT
+#define MICROPY_HW_ENABLE_GPIO16 (1)
+#define MICROPY_HW_ENABLE_GPIO17 (1)
+#endif
+#define MICROPY_HW_ENABLE_GPIO18 (1)
+#define MICROPY_HW_ENABLE_GPIO19 (1)
+#define MICROPY_HW_ENABLE_GPIO20 (1)
+#define MICROPY_HW_ENABLE_GPIO21 (1)
+#define MICROPY_HW_ENABLE_GPIO22 (1)
+#define MICROPY_HW_ENABLE_GPIO23 (1)
+#define MICROPY_HW_ENABLE_GPIO25 (1)
+#define MICROPY_HW_ENABLE_GPIO26 (1)
+#define MICROPY_HW_ENABLE_GPIO27 (1)
+#define MICROPY_HW_ENABLE_GPIO32 (1)
+#define MICROPY_HW_ENABLE_GPIO33 (1)
+#define MICROPY_HW_ENABLE_GPIO34 (1)
+#define MICROPY_HW_ENABLE_GPIO35 (1)
+#define MICROPY_HW_ENABLE_GPIO36 (1)
+#define MICROPY_HW_ENABLE_GPIO37 (1)
+#define MICROPY_HW_ENABLE_GPIO38 (1)
+#define MICROPY_HW_ENABLE_GPIO39 (1)
+
+#elif CONFIG_IDF_TARGET_ESP32C3
+
+#define MICROPY_HW_ENABLE_GPIO0 (1)
+#define MICROPY_HW_ENABLE_GPIO1 (1)
+#define MICROPY_HW_ENABLE_GPIO2 (1)
+#define MICROPY_HW_ENABLE_GPIO3 (1)
+#define MICROPY_HW_ENABLE_GPIO4 (1)
+#define MICROPY_HW_ENABLE_GPIO5 (1)
+#define MICROPY_HW_ENABLE_GPIO6 (1)
+#define MICROPY_HW_ENABLE_GPIO7 (1)
+#define MICROPY_HW_ENABLE_GPIO8 (1)
+#define MICROPY_HW_ENABLE_GPIO9 (1)
+#define MICROPY_HW_ENABLE_GPIO10 (1)
+#define MICROPY_HW_ENABLE_GPIO11 (1)
+#define MICROPY_HW_ENABLE_GPIO12 (1)
+#define MICROPY_HW_ENABLE_GPIO13 (1)
+#if !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
+#define MICROPY_HW_ENABLE_GPIO18 (1)
+#define MICROPY_HW_ENABLE_GPIO19 (1)
+#endif
+#define MICROPY_HW_ENABLE_GPIO20 (1)
+#define MICROPY_HW_ENABLE_GPIO21 (1)
+
+#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+
+#define MICROPY_HW_ENABLE_GPIO0 (1)
+#define MICROPY_HW_ENABLE_GPIO1 (1)
+#define MICROPY_HW_ENABLE_GPIO2 (1)
+#define MICROPY_HW_ENABLE_GPIO3 (1)
+#define MICROPY_HW_ENABLE_GPIO4 (1)
+#define MICROPY_HW_ENABLE_GPIO5 (1)
+#define MICROPY_HW_ENABLE_GPIO6 (1)
+#define MICROPY_HW_ENABLE_GPIO7 (1)
+#define MICROPY_HW_ENABLE_GPIO8 (1)
+#define MICROPY_HW_ENABLE_GPIO9 (1)
+#define MICROPY_HW_ENABLE_GPIO10 (1)
+#define MICROPY_HW_ENABLE_GPIO11 (1)
+#define MICROPY_HW_ENABLE_GPIO12 (1)
+#define MICROPY_HW_ENABLE_GPIO13 (1)
+#define MICROPY_HW_ENABLE_GPIO14 (1)
+#define MICROPY_HW_ENABLE_GPIO15 (1)
+#define MICROPY_HW_ENABLE_GPIO16 (1)
+#define MICROPY_HW_ENABLE_GPIO17 (1)
+#define MICROPY_HW_ENABLE_GPIO18 (1)
+#if !CONFIG_USB_CDC_ENABLED
+#define MICROPY_HW_ENABLE_GPIO19 (1)
+#define MICROPY_HW_ENABLE_GPIO20 (1)
+#endif
+#define MICROPY_HW_ENABLE_GPIO21 (1)
+#if !CONFIG_SPIRAM
+#define MICROPY_HW_ENABLE_GPIO26 (1)
+#endif
+#if !CONFIG_SPIRAM_MODE_OCT
+#define MICROPY_HW_ENABLE_GPIO33 (1)
+#define MICROPY_HW_ENABLE_GPIO34 (1)
+#define MICROPY_HW_ENABLE_GPIO35 (1)
+#define MICROPY_HW_ENABLE_GPIO36 (1)
+#define MICROPY_HW_ENABLE_GPIO37 (1)
+#endif
+#define MICROPY_HW_ENABLE_GPIO38 (1)
+#define MICROPY_HW_ENABLE_GPIO39 (1)
+#define MICROPY_HW_ENABLE_GPIO40 (1)
+#define MICROPY_HW_ENABLE_GPIO41 (1)
+#define MICROPY_HW_ENABLE_GPIO42 (1)
+#define MICROPY_HW_ENABLE_GPIO43 (1)
+#define MICROPY_HW_ENABLE_GPIO44 (1)
+#define MICROPY_HW_ENABLE_GPIO45 (1)
+#define MICROPY_HW_ENABLE_GPIO46 (1)
+#if CONFIG_IDF_TARGET_ESP32S3 && MICROPY_HW_ESP32S3_EXTENDED_IO
+#define MICROPY_HW_ENABLE_GPIO47 (1)
+#define MICROPY_HW_ENABLE_GPIO48 (1)
+#endif
+
+#endif
+
+typedef struct _machine_pin_obj_t {
+ mp_obj_base_t base;
+} machine_pin_obj_t;
+
+typedef struct _machine_pin_irq_obj_t {
+ mp_obj_base_t base;
+} machine_pin_irq_obj_t;
+
+extern const mp_obj_type_t machine_pin_irq_type;
+
+extern const machine_pin_obj_t machine_pin_obj_table[GPIO_NUM_MAX];
+extern const machine_pin_irq_obj_t machine_pin_irq_obj_table[GPIO_NUM_MAX];
+
+extern const mp_obj_dict_t machine_pin_board_pins_locals_dict;
+
+#endif // MICROPY_INCLUDED_ESP32_MACHINE_PIN_H
diff --git a/ports/esp32/machine_pwm.c b/ports/esp32/machine_pwm.c
index 0107187a8c98c..462d0fa79c740 100644
--- a/ports/esp32/machine_pwm.c
+++ b/ports/esp32/machine_pwm.c
@@ -1,5 +1,5 @@
/*
- * This file is part of the Micro Python project, http://micropython.org/
+ * This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
@@ -34,6 +34,7 @@
#include "driver/ledc.h"
#include "esp_err.h"
+#include "soc/gpio_sig_map.h"
#define PWM_DBG(...)
// #define PWM_DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, "\n");
@@ -97,8 +98,10 @@ STATIC ledc_timer_config_t timers[PWM_TIMER_MAX];
// How much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT
#define UI_RES_SHIFT (UI_RES_16_BIT - HIGHEST_PWM_RES) // 0 for ESP32, 2 for S2, S3, C3
+#if SOC_LEDC_SUPPORT_REF_TICK
// If the PWM frequency is less than EMPIRIC_FREQ, then LEDC_REF_CLK_HZ(1 MHz) source is used, else LEDC_APB_CLK_HZ(80 MHz) source is used
#define EMPIRIC_FREQ (10) // Hz
+#endif
// Config of timer upon which we run all PWM'ed GPIO pins
STATIC bool pwm_inited = false;
@@ -162,13 +165,13 @@ STATIC void pwm_deinit(int channel_idx) {
// Mark it unused, and tell the hardware to stop routing
check_esp_err(ledc_stop(mode, channel, 0));
// Disable ledc signal for the pin
- // gpio_matrix_out(pin, SIG_GPIO_OUT_IDX, false, false);
+ // esp_rom_gpio_connect_out_signal(pin, SIG_GPIO_OUT_IDX, false, false);
if (mode == LEDC_LOW_SPEED_MODE) {
- gpio_matrix_out(pin, LEDC_LS_SIG_OUT0_IDX + channel, false, true);
+ esp_rom_gpio_connect_out_signal(pin, LEDC_LS_SIG_OUT0_IDX + channel, false, true);
} else {
#if LEDC_SPEED_MODE_MAX > 1
#if CONFIG_IDF_TARGET_ESP32
- gpio_matrix_out(pin, LEDC_HS_SIG_OUT0_IDX + channel, false, true);
+ esp_rom_gpio_connect_out_signal(pin, LEDC_HS_SIG_OUT0_IDX + channel, false, true);
#else
#error Add supported CONFIG_IDF_TARGET_ESP32_xxx
#endif
@@ -207,16 +210,13 @@ STATIC void configure_channel(machine_pwm_obj_t *self) {
STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_config_t *timer) {
if (freq != timer->freq_hz) {
// Find the highest bit resolution for the requested frequency
- unsigned int i = LEDC_APB_CLK_HZ; // 80 MHz
+ unsigned int i = APB_CLK_FREQ; // 80 MHz
+ #if SOC_LEDC_SUPPORT_REF_TICK
if (freq < EMPIRIC_FREQ) {
- i = LEDC_REF_CLK_HZ; // 1 MHz
+ i = REF_CLK_FREQ; // 1 MHz
}
+ #endif
- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
- // original code
- i /= freq;
- #else
- // See https://github.com/espressif/esp-idf/issues/7722
int divider = (i + freq / 2) / freq; // rounded
if (divider == 0) {
divider = 1;
@@ -226,7 +226,6 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
f = 1.0;
}
i = (unsigned int)roundf((float)i / f);
- #endif
unsigned int res = 0;
for (; i > 1; i >>= 1) {
@@ -243,9 +242,11 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
timer->duty_resolution = res;
timer->freq_hz = freq;
timer->clk_cfg = LEDC_USE_APB_CLK;
+ #if SOC_LEDC_SUPPORT_REF_TICK
if (freq < EMPIRIC_FREQ) {
timer->clk_cfg = LEDC_USE_REF_TICK;
}
+ #endif
// Set frequency
esp_err_t err = ledc_timer_config(timer);
@@ -292,7 +293,14 @@ STATIC int duty_to_ns(machine_pwm_obj_t *self, int duty) {
#define get_duty_raw(self) ledc_get_duty(self->mode, self->channel)
+STATIC void pwm_is_active(machine_pwm_obj_t *self) {
+ if (self->active == false) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("PWM inactive"));
+ }
+}
+
STATIC uint32_t get_duty_u16(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
int resolution = timers[TIMER_IDX(self->mode, self->timer)].duty_resolution;
int duty = ledc_get_duty(self->mode, self->channel);
if (resolution <= UI_RES_16_BIT) {
@@ -304,14 +312,17 @@ STATIC uint32_t get_duty_u16(machine_pwm_obj_t *self) {
}
STATIC uint32_t get_duty_u10(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
return get_duty_u16(self) >> 6; // Scale down from 16 bit to 10 bit resolution
}
STATIC uint32_t get_duty_ns(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
return duty_to_ns(self, get_duty_u16(self));
}
STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
+ pwm_is_active(self);
if ((duty < 0) || (duty > UI_MAX_DUTY)) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty_u16 must be from 0 to %d"), UI_MAX_DUTY);
}
@@ -334,11 +345,11 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
/*
// Bug: Sometimes duty is not set right now.
// Not a bug. It's a feature. The duty is applied at the beginning of the next signal period.
- // Bug: It has been experimentally established that the duty is setted during 2 signal periods, but 1 period is expected.
+ // Bug: It has been experimentally established that the duty is set during 2 signal periods, but 1 period is expected.
// See https://github.com/espressif/esp-idf/issues/7288
if (duty != get_duty_u16(self)) {
PWM_DBG("set_duty_u16(%u), get_duty_u16():%u, channel_duty:%d, duty_resolution:%d, freq_hz:%d", duty, get_duty_u16(self), channel_duty, timer.duty_resolution, timer.freq_hz);
- ets_delay_us(2 * 1000000 / timer.freq_hz);
+ esp_rom_delay_us(2 * 1000000 / timer.freq_hz);
if (duty != get_duty_u16(self)) {
PWM_DBG("set_duty_u16(%u), get_duty_u16():%u, channel_duty:%d, duty_resolution:%d, freq_hz:%d", duty, get_duty_u16(self), channel_duty, timer.duty_resolution, timer.freq_hz);
}
@@ -350,6 +361,7 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
}
STATIC void set_duty_u10(machine_pwm_obj_t *self, int duty) {
+ pwm_is_active(self);
if ((duty < 0) || (duty > MAX_DUTY_U10)) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty must be from 0 to %u"), MAX_DUTY_U10);
}
@@ -359,6 +371,7 @@ STATIC void set_duty_u10(machine_pwm_obj_t *self, int duty) {
}
STATIC void set_duty_ns(machine_pwm_obj_t *self, int ns) {
+ pwm_is_active(self);
if ((ns < 0) || (ns > duty_to_ns(self, UI_MAX_DUTY))) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty_ns must be from 0 to %d ns"), duty_to_ns(self, UI_MAX_DUTY));
}
@@ -492,7 +505,7 @@ STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
}
}
if ((freq <= 0) || (freq > 40000000)) {
- mp_raise_ValueError(MP_ERROR_TEXT("freqency must be from 1Hz to 40MHz"));
+ mp_raise_ValueError(MP_ERROR_TEXT("frequency must be from 1Hz to 40MHz"));
}
int timer_idx;
@@ -589,15 +602,17 @@ STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
self->duty_x = 0;
}
-// Set's and get's methods of PWM class
+// Set and get methods of PWM class
STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
return MP_OBJ_NEW_SMALL_INT(ledc_get_freq(self->mode, self->timer));
}
STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
+ pwm_is_active(self);
if ((freq <= 0) || (freq > 40000000)) {
- mp_raise_ValueError(MP_ERROR_TEXT("freqency must be from 1Hz to 40MHz"));
+ mp_raise_ValueError(MP_ERROR_TEXT("frequency must be from 1Hz to 40MHz"));
}
if (freq == timers[TIMER_IDX(self->mode, self->timer)].freq_hz) {
return;
diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c
index 72d7b5c8280aa..3d620336c9a91 100644
--- a/ports/esp32/machine_rtc.c
+++ b/ports/esp32/machine_rtc.c
@@ -173,9 +173,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
-const mp_obj_type_t machine_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = machine_rtc_make_new,
- .locals_dict = (mp_obj_t)&machine_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_rtc_make_new,
+ locals_dict, &machine_rtc_locals_dict
+ );
diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c
index 82c2e6cd4e320..bc4aaf30c6f2b 100644
--- a/ports/esp32/machine_sdcard.c
+++ b/ports/esp32/machine_sdcard.c
@@ -69,18 +69,71 @@ typedef struct _sdcard_obj_t {
#define _SECTOR_SIZE(self) (self->card.csd.sector_size)
-STATIC gpio_num_t pin_or_int(const mp_obj_t arg) {
- if (mp_obj_is_small_int(arg)) {
- return MP_OBJ_SMALL_INT_VALUE(arg);
- } else {
- // This raises a value error if the argument is not a Pin.
- return machine_pin_get_id(arg);
- }
-}
+// SPI bus default bus and device configuration.
+
+static const spi_bus_config_t spi_bus_defaults[2] = {
+ {
+ #if CONFIG_IDF_TARGET_ESP32
+ .miso_io_num = GPIO_NUM_19,
+ .mosi_io_num = GPIO_NUM_23,
+ .sclk_io_num = GPIO_NUM_18,
+ #else
+ .miso_io_num = GPIO_NUM_36,
+ .mosi_io_num = GPIO_NUM_35,
+ .sclk_io_num = GPIO_NUM_37,
+ #endif
+ .data2_io_num = GPIO_NUM_NC,
+ .data3_io_num = GPIO_NUM_NC,
+ .data4_io_num = GPIO_NUM_NC,
+ .data5_io_num = GPIO_NUM_NC,
+ .data6_io_num = GPIO_NUM_NC,
+ .data7_io_num = GPIO_NUM_NC,
+ .max_transfer_sz = 4000,
+ .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_MOSI,
+ .intr_flags = 0,
+ },
+ {
+ .miso_io_num = GPIO_NUM_2,
+ .mosi_io_num = GPIO_NUM_15,
+ .sclk_io_num = GPIO_NUM_14,
+ .data2_io_num = GPIO_NUM_NC,
+ .data3_io_num = GPIO_NUM_NC,
+ .data4_io_num = GPIO_NUM_NC,
+ .data5_io_num = GPIO_NUM_NC,
+ .data6_io_num = GPIO_NUM_NC,
+ .data7_io_num = GPIO_NUM_NC,
+ .max_transfer_sz = 4000,
+ .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_MOSI,
+ .intr_flags = 0,
+ },
+};
+
+#if CONFIG_IDF_TARGET_ESP32
+static const uint8_t spi_dma_channel_defaults[2] = {
+ 2,
+ 1,
+};
+#endif
+
+static const sdspi_device_config_t spi_dev_defaults[2] = {
+ {
+ #if CONFIG_IDF_TARGET_ESP32
+ .host_id = VSPI_HOST,
+ .gpio_cs = GPIO_NUM_5,
+ #else
+ .host_id = SPI3_HOST,
+ .gpio_cs = GPIO_NUM_34,
+ #endif
+ .gpio_cd = SDSPI_SLOT_NO_CD,
+ .gpio_wp = SDSPI_SLOT_NO_WP,
+ .gpio_int = SDSPI_SLOT_NO_INT,
+ },
+ SDSPI_DEVICE_CONFIG_DEFAULT(), // HSPI (ESP32) / SPI2 (ESP32S3)
+};
#define SET_CONFIG_PIN(config, pin_var, arg_id) \
if (arg_vals[arg_id].u_obj != mp_const_none) \
- config.pin_var = pin_or_int(arg_vals[arg_id].u_obj)
+ config.pin_var = machine_pin_get_id(arg_vals[arg_id].u_obj)
STATIC esp_err_t sdcard_ensure_card_init(sdcard_card_obj_t *self, bool force) {
if (force || !(self->flags & SDCARD_CARD_FLAGS_CARD_INIT_DONE)) {
@@ -188,10 +241,11 @@ STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
}
if (is_spi) {
- #if CONFIG_IDF_TARGET_ESP32S3
- self->host.slot = slot_num ? SPI3_HOST : SPI2_HOST;
- #else
+ // Needs to match spi_dev_defaults above.
+ #if CONFIG_IDF_TARGET_ESP32
self->host.slot = slot_num ? HSPI_HOST : VSPI_HOST;
+ #else
+ self->host.slot = slot_num ? SPI2_HOST : SPI3_HOST;
#endif
}
@@ -202,46 +256,39 @@ STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
if (is_spi) {
// SPI interface
- #if CONFIG_IDF_TARGET_ESP32S3
- STATIC const sdspi_slot_config_t slot_defaults[2] = {
- {
- .gpio_miso = GPIO_NUM_36,
- .gpio_mosi = GPIO_NUM_35,
- .gpio_sck = GPIO_NUM_37,
- .gpio_cs = GPIO_NUM_34,
- .gpio_cd = SDSPI_SLOT_NO_CD,
- .gpio_wp = SDSPI_SLOT_NO_WP,
- .dma_channel = 2
- },
- SDSPI_SLOT_CONFIG_DEFAULT()
- };
+ DEBUG_printf(" Setting up SPI slot configuration");
+ spi_host_device_t spi_host_id = self->host.slot;
+ spi_bus_config_t bus_config = spi_bus_defaults[slot_num];
+ #if CONFIG_IDF_TARGET_ESP32
+ spi_dma_chan_t dma_channel = spi_dma_channel_defaults[slot_num];
#else
- STATIC const sdspi_slot_config_t slot_defaults[2] = {
- {
- .gpio_miso = GPIO_NUM_19,
- .gpio_mosi = GPIO_NUM_23,
- .gpio_sck = GPIO_NUM_18,
- .gpio_cs = GPIO_NUM_5,
- .gpio_cd = SDSPI_SLOT_NO_CD,
- .gpio_wp = SDSPI_SLOT_NO_WP,
- .dma_channel = 2
- },
- SDSPI_SLOT_CONFIG_DEFAULT()
- };
+ spi_dma_chan_t dma_channel = SPI_DMA_CH_AUTO;
#endif
+ sdspi_device_config_t dev_config = spi_dev_defaults[slot_num];
- DEBUG_printf(" Setting up SPI slot configuration");
- sdspi_slot_config_t slot_config = slot_defaults[slot_num];
+ SET_CONFIG_PIN(bus_config, miso_io_num, ARG_miso);
+ SET_CONFIG_PIN(bus_config, mosi_io_num, ARG_mosi);
+ SET_CONFIG_PIN(bus_config, sclk_io_num, ARG_sck);
- SET_CONFIG_PIN(slot_config, gpio_cd, ARG_cd);
- SET_CONFIG_PIN(slot_config, gpio_wp, ARG_wp);
- SET_CONFIG_PIN(slot_config, gpio_miso, ARG_miso);
- SET_CONFIG_PIN(slot_config, gpio_mosi, ARG_mosi);
- SET_CONFIG_PIN(slot_config, gpio_sck, ARG_sck);
- SET_CONFIG_PIN(slot_config, gpio_cs, ARG_cs);
+ SET_CONFIG_PIN(dev_config, gpio_cs, ARG_cs);
+ SET_CONFIG_PIN(dev_config, gpio_cd, ARG_cd);
+ SET_CONFIG_PIN(dev_config, gpio_wp, ARG_wp);
- DEBUG_printf(" Calling init_slot()");
- check_esp_err(sdspi_host_init_slot(self->host.slot, &slot_config));
+ DEBUG_printf(" Calling spi_bus_initialize()");
+ check_esp_err(spi_bus_initialize(spi_host_id, &bus_config, dma_channel));
+
+ DEBUG_printf(" Calling sdspi_host_init_device()");
+ sdspi_dev_handle_t sdspi_handle;
+ esp_err_t ret = sdspi_host_init_device(&dev_config, &sdspi_handle);
+ if (ret != ESP_OK) {
+ spi_bus_free(spi_host_id);
+ check_esp_err(ret);
+ }
+ if (self->host.slot != sdspi_handle) {
+ // MicroPython restriction: the SPI bus must be exclusively for the SD card.
+ spi_bus_free(spi_host_id);
+ mp_raise_ValueError(MP_ERROR_TEXT("SPI bus already in use"));
+ }
} else {
// SD/MMC interface
DEBUG_printf(" Setting up SDMMC slot configuration");
@@ -275,14 +322,15 @@ STATIC mp_obj_t sd_deinit(mp_obj_t self_in) {
DEBUG_printf("De-init host\n");
if (self->flags & SDCARD_CARD_FLAGS_HOST_INIT_DONE) {
- #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
if (self->host.flags & SDMMC_HOST_FLAG_DEINIT_ARG) {
self->host.deinit_p(self->host.slot);
- } else
- #endif
- {
+ } else {
self->host.deinit();
}
+ if (self->host.flags & SDMMC_HOST_FLAG_SPI) {
+ // SD card used a (dedicated) SPI bus, so free that SPI bus.
+ spi_bus_free(self->host.slot);
+ }
self->flags &= ~SDCARD_CARD_FLAGS_HOST_INIT_DONE;
}
@@ -395,11 +443,12 @@ STATIC const mp_rom_map_elem_t machine_sdcard_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_sdcard_locals_dict, machine_sdcard_locals_dict_table);
-const mp_obj_type_t machine_sdcard_type = {
- { &mp_type_type },
- .name = MP_QSTR_SDCard,
- .make_new = machine_sdcard_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_sdcard_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_sdcard_type,
+ MP_QSTR_SDCard,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_sdcard_make_new,
+ locals_dict, &machine_sdcard_locals_dict
+ );
#endif // MICROPY_HW_ENABLE_SDCARD
diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c
index 100b2aa1fb9c8..aba3db1983fce 100644
--- a/ports/esp32/machine_timer.c
+++ b/ports/esp32/machine_timer.c
@@ -35,22 +35,21 @@
#include "modmachine.h"
#include "mphalport.h"
-#include "driver/timer.h"
-#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 1)
+#include "hal/timer_hal.h"
#include "hal/timer_ll.h"
-#define HAVE_TIMER_LL (1)
-#endif
+#include "soc/timer_periph.h"
-#define TIMER_INTR_SEL TIMER_INTR_LEVEL
#define TIMER_DIVIDER 8
// TIMER_BASE_CLK is normally 80MHz. TIMER_DIVIDER ought to divide this exactly
-#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER)
+#define TIMER_SCALE (APB_CLK_FREQ / TIMER_DIVIDER)
#define TIMER_FLAGS 0
typedef struct _machine_timer_obj_t {
mp_obj_base_t base;
+
+ timer_hal_context_t hal_context;
mp_uint_t group;
mp_uint_t index;
@@ -68,6 +67,7 @@ typedef struct _machine_timer_obj_t {
const mp_obj_type_t machine_timer_type;
STATIC void machine_timer_disable(machine_timer_obj_t *self);
+STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
void machine_timer_deinit_all(void) {
// Disable, deallocate and remove all timers from list
@@ -82,43 +82,54 @@ void machine_timer_deinit_all(void) {
STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_timer_obj_t *self = self_in;
-
- timer_config_t config;
- mp_printf(print, "Timer(%p; ", self);
-
- timer_get_config(self->group, self->index, &config);
-
- mp_printf(print, "alarm_en=%d, ", config.alarm_en);
- mp_printf(print, "auto_reload=%d, ", config.auto_reload);
- mp_printf(print, "counter_en=%d)", config.counter_en);
+ qstr mode = self->repeat ? MP_QSTR_PERIODIC : MP_QSTR_ONE_SHOT;
+ uint64_t period = self->period / (TIMER_SCALE / 1000); // convert to ms
+ mp_printf(print, "Timer(%u, mode=%q, period=%lu)", (self->group << 1) | self->index, mode, period);
}
STATIC mp_obj_t machine_timer_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, 1, 1, false);
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
mp_uint_t group = (mp_obj_get_int(args[0]) >> 1) & 1;
mp_uint_t index = mp_obj_get_int(args[0]) & 1;
- // Check whether the timer is already initialized, if so return it
+ machine_timer_obj_t *self = NULL;
+
+ // Check whether the timer is already initialized, if so use it
for (machine_timer_obj_t *t = MP_STATE_PORT(machine_timer_obj_head); t; t = t->next) {
if (t->group == group && t->index == index) {
- return t;
+ self = t;
+ break;
}
}
+ // The timer does not exist, create it.
+ if (self == NULL) {
+ self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type);
+ self->group = group;
+ self->index = index;
+
+ // Add the timer to the linked-list of timers
+ self->next = MP_STATE_PORT(machine_timer_obj_head);
+ MP_STATE_PORT(machine_timer_obj_head) = self;
+ }
- machine_timer_obj_t *self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type);
- self->group = group;
- self->index = index;
-
- // Add the timer to the linked-list of timers
- self->next = MP_STATE_PORT(machine_timer_obj_head);
- MP_STATE_PORT(machine_timer_obj_head) = self;
+ if (n_args > 1 || n_kw > 0) {
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ machine_timer_init_helper(self, n_args - 1, args + 1, &kw_args);
+ }
return self;
}
STATIC void machine_timer_disable(machine_timer_obj_t *self) {
+ if (self->hal_context.dev != NULL) {
+ // Disable the counter and alarm.
+ timer_ll_enable_counter(self->hal_context.dev, self->index, false);
+ timer_ll_enable_alarm(self->hal_context.dev, self->index, false);
+ }
+
if (self->handle) {
- timer_pause(self->group, self->index);
+ // Free the interrupt handler.
esp_intr_free(self->handle);
self->handle = NULL;
}
@@ -129,61 +140,47 @@ STATIC void machine_timer_disable(machine_timer_obj_t *self) {
STATIC void machine_timer_isr(void *self_in) {
machine_timer_obj_t *self = self_in;
- timg_dev_t *device = self->group ? &(TIMERG1) : &(TIMERG0);
- #if HAVE_TIMER_LL
+ uint32_t intr_status = timer_ll_get_intr_status(self->hal_context.dev);
- #if CONFIG_IDF_TARGET_ESP32 && ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
- device->hw_timer[self->index].update = 1;
- #else
- #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
- #if CONFIG_IDF_TARGET_ESP32S3
- device->hw_timer[self->index].update.tn_update = 1;
- #else
- device->hw_timer[self->index].update.tx_update = 1;
- #endif
- #else
- device->hw_timer[self->index].update.update = 1;
- #endif
- #endif
- timer_ll_clear_intr_status(device, self->index);
- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
- timer_ll_set_alarm_enable(device, self->index, self->repeat);
- #else
- timer_ll_set_alarm_value(device, self->index, self->repeat);
- #endif
-
- #else
-
- device->hw_timer[self->index].update = 1;
- if (self->index) {
- device->int_clr_timers.t1 = 1;
- } else {
- device->int_clr_timers.t0 = 1;
+ if (intr_status & TIMER_LL_EVENT_ALARM(self->index)) {
+ timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
+ if (self->repeat) {
+ timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
+ }
+ mp_sched_schedule(self->callback, self);
+ mp_hal_wake_main_task_from_isr();
}
- device->hw_timer[self->index].config.alarm_en = self->repeat;
-
- #endif
-
- mp_sched_schedule(self->callback, self);
- mp_hal_wake_main_task_from_isr();
}
STATIC void machine_timer_enable(machine_timer_obj_t *self) {
- timer_config_t config;
- config.alarm_en = TIMER_ALARM_EN;
- config.auto_reload = self->repeat;
- config.counter_dir = TIMER_COUNT_UP;
- config.divider = TIMER_DIVIDER;
- config.intr_type = TIMER_INTR_LEVEL;
- config.counter_en = TIMER_PAUSE;
-
- check_esp_err(timer_init(self->group, self->index, &config));
- check_esp_err(timer_set_counter_value(self->group, self->index, 0x00000000));
- check_esp_err(timer_set_alarm_value(self->group, self->index, self->period));
- check_esp_err(timer_enable_intr(self->group, self->index));
- check_esp_err(timer_isr_register(self->group, self->index, machine_timer_isr, (void *)self, TIMER_FLAGS, &self->handle));
- check_esp_err(timer_start(self->group, self->index));
+ // Initialise the timer.
+ timer_hal_init(&self->hal_context, self->group, self->index);
+ timer_ll_enable_counter(self->hal_context.dev, self->index, false);
+ timer_ll_set_clock_source(self->hal_context.dev, self->index, GPTIMER_CLK_SRC_APB);
+ timer_ll_set_clock_prescale(self->hal_context.dev, self->index, TIMER_DIVIDER);
+ timer_hal_set_counter_value(&self->hal_context, 0);
+ timer_ll_set_count_direction(self->hal_context.dev, self->index, GPTIMER_COUNT_UP);
+
+ // Allocate and enable the alarm interrupt.
+ timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), false);
+ timer_ll_clear_intr_status(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index));
+ ESP_ERROR_CHECK(
+ esp_intr_alloc(timer_group_periph_signals.groups[self->group].timer_irq_id[self->index],
+ TIMER_FLAGS, machine_timer_isr, self, &self->handle)
+ );
+ timer_ll_enable_intr(self->hal_context.dev, TIMER_LL_EVENT_ALARM(self->index), true);
+
+ // Enable the alarm to trigger at the given period.
+ timer_ll_set_alarm_value(self->hal_context.dev, self->index, self->period);
+ timer_ll_enable_alarm(self->hal_context.dev, self->index, true);
+
+ // Set the counter to reload at 0 if it's in repeat mode.
+ timer_ll_set_reload_value(self->hal_context.dev, self->index, 0);
+ timer_ll_enable_auto_reload(self->hal_context.dev, self->index, self->repeat);
+
+ // Enable the counter.
+ timer_ll_enable_counter(self->hal_context.dev, self->index, true);
}
STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -247,11 +244,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init)
STATIC mp_obj_t machine_timer_value(mp_obj_t self_in) {
machine_timer_obj_t *self = self_in;
- double result;
-
- timer_get_counter_time_sec(self->group, self->index, &result);
-
- return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(result * 1000)); // value in ms
+ uint64_t result = timer_ll_get_counter_value(self->hal_context.dev, self->index);
+ return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(result / (TIMER_SCALE / 1000))); // value in ms
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_value_obj, machine_timer_value);
@@ -265,10 +259,13 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
-const mp_obj_type_t machine_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = machine_timer_print,
- .make_new = machine_timer_make_new,
- .locals_dict = (mp_obj_t)&machine_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_timer_make_new,
+ print, machine_timer_print,
+ locals_dict, &machine_timer_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *machine_timer_obj_head);
diff --git a/ports/esp32/machine_touchpad.c b/ports/esp32/machine_touchpad.c
index 168ac16d0eef6..d9f4ef3ebc7f4 100644
--- a/ports/esp32/machine_touchpad.c
+++ b/ports/esp32/machine_touchpad.c
@@ -27,10 +27,10 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"
+#include "driver/gpio.h"
-#if CONFIG_IDF_TARGET_ESP32
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-#include "driver/gpio.h"
#if CONFIG_IDF_TARGET_ESP32
#include "driver/touch_pad.h"
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
@@ -43,8 +43,8 @@ typedef struct _mtp_obj_t {
touch_pad_t touchpad_id;
} mtp_obj_t;
-#if CONFIG_IDF_TARGET_ESP32
STATIC const mtp_obj_t touchpad_obj[] = {
+ #if CONFIG_IDF_TARGET_ESP32
{{&machine_touchpad_type}, GPIO_NUM_4, TOUCH_PAD_NUM0},
{{&machine_touchpad_type}, GPIO_NUM_0, TOUCH_PAD_NUM1},
{{&machine_touchpad_type}, GPIO_NUM_2, TOUCH_PAD_NUM2},
@@ -55,9 +55,7 @@ STATIC const mtp_obj_t touchpad_obj[] = {
{{&machine_touchpad_type}, GPIO_NUM_27, TOUCH_PAD_NUM7},
{{&machine_touchpad_type}, GPIO_NUM_33, TOUCH_PAD_NUM8},
{{&machine_touchpad_type}, GPIO_NUM_32, TOUCH_PAD_NUM9},
-};
-#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-STATIC const mtp_obj_t touchpad_obj[] = {
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
{{&machine_touchpad_type}, GPIO_NUM_1, TOUCH_PAD_NUM1},
{{&machine_touchpad_type}, GPIO_NUM_2, TOUCH_PAD_NUM2},
{{&machine_touchpad_type}, GPIO_NUM_3, TOUCH_PAD_NUM3},
@@ -72,12 +70,11 @@ STATIC const mtp_obj_t touchpad_obj[] = {
{{&machine_touchpad_type}, GPIO_NUM_12, TOUCH_PAD_NUM12},
{{&machine_touchpad_type}, GPIO_NUM_13, TOUCH_PAD_NUM13},
{{&machine_touchpad_type}, GPIO_NUM_14, TOUCH_PAD_NUM14},
+ #endif
};
-#endif
STATIC mp_obj_t mtp_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, 1, 1, true);
gpio_num_t pin_id = machine_pin_get_id(args[0]);
const mtp_obj_t *self = NULL;
@@ -95,9 +92,16 @@ STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
if (!initialized) {
touch_pad_init();
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
+ #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ touch_pad_fsm_start();
+ #endif
initialized = 1;
}
+ #if CONFIG_IDF_TARGET_ESP32
esp_err_t err = touch_pad_config(self->touchpad_id, 0);
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ esp_err_t err = touch_pad_config(self->touchpad_id);
+ #endif
if (err == ESP_OK) {
return MP_OBJ_FROM_PTR(self);
}
@@ -106,8 +110,12 @@ STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
STATIC mp_obj_t mtp_config(mp_obj_t self_in, mp_obj_t value_in) {
mtp_obj_t *self = self_in;
+ #if CONFIG_IDF_TARGET_ESP32
uint16_t value = mp_obj_get_int(value_in);
esp_err_t err = touch_pad_config(self->touchpad_id, value);
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ esp_err_t err = touch_pad_config(self->touchpad_id);
+ #endif
if (err == ESP_OK) {
return mp_const_none;
}
@@ -117,8 +125,13 @@ MP_DEFINE_CONST_FUN_OBJ_2(mtp_config_obj, mtp_config);
STATIC mp_obj_t mtp_read(mp_obj_t self_in) {
mtp_obj_t *self = self_in;
+ #if CONFIG_IDF_TARGET_ESP32
uint16_t value;
esp_err_t err = touch_pad_read(self->touchpad_id, &value);
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ uint32_t value;
+ esp_err_t err = touch_pad_read_raw_data(self->touchpad_id, &value);
+ #endif
if (err == ESP_OK) {
return MP_OBJ_NEW_SMALL_INT(value);
}
@@ -134,11 +147,12 @@ STATIC const mp_rom_map_elem_t mtp_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(mtp_locals_dict, mtp_locals_dict_table);
-const mp_obj_type_t machine_touchpad_type = {
- { &mp_type_type },
- .name = MP_QSTR_TouchPad,
- .make_new = mtp_make_new,
- .locals_dict = (mp_obj_t)&mtp_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_touchpad_type,
+ MP_QSTR_TouchPad,
+ MP_TYPE_FLAG_NONE,
+ make_new, mtp_make_new,
+ locals_dict, &mtp_locals_dict
+ );
-#endif // CONFIG_IDF_TARGET_ESP32
+#endif
diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c
index 49ce78b1b24c9..e7b2b8376b7aa 100644
--- a/ports/esp32/machine_uart.c
+++ b/ports/esp32/machine_uart.c
@@ -34,20 +34,21 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
+#include "py/mphal.h"
#include "modmachine.h"
#include "uart.h"
-#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 1, 0)
-#define UART_INV_TX UART_INVERSE_TXD
-#define UART_INV_RX UART_INVERSE_RXD
-#define UART_INV_RTS UART_INVERSE_RTS
-#define UART_INV_CTS UART_INVERSE_CTS
+#if SOC_UART_SUPPORT_XTAL_CLK
+// Works independently of APB frequency, on ESP32C3, ESP32S3.
+#define UART_SOURCE_CLK UART_SCLK_XTAL
#else
+#define UART_SOURCE_CLK UART_SCLK_DEFAULT
+#endif
+
#define UART_INV_TX UART_SIGNAL_TXD_INV
#define UART_INV_RX UART_SIGNAL_RXD_INV
#define UART_INV_RTS UART_SIGNAL_RTS_INV
#define UART_INV_CTS UART_SIGNAL_CTS_INV
-#endif
#define UART_INV_MASK (UART_INV_TX | UART_INV_RX | UART_INV_RTS | UART_INV_CTS)
@@ -58,10 +59,10 @@ typedef struct _machine_uart_obj_t {
uint8_t bits;
uint8_t parity;
uint8_t stop;
- int8_t tx;
- int8_t rx;
- int8_t rts;
- int8_t cts;
+ gpio_num_t tx;
+ gpio_num_t rx;
+ gpio_num_t rts;
+ gpio_num_t cts;
uint16_t txbuf;
uint16_t rxbuf;
uint16_t timeout; // timeout waiting for first char (in ms)
@@ -133,10 +134,10 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
- { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
- { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
- { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
+ { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
@@ -164,7 +165,8 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
}
uart_config_t uartcfg = {
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
- .rx_flow_ctrl_thresh = 0
+ .rx_flow_ctrl_thresh = 0,
+ .source_clk = UART_SOURCE_CLK,
};
uint32_t baudrate;
uart_get_baudrate(self->uart_num, &baudrate);
@@ -184,22 +186,22 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
}
uart_get_baudrate(self->uart_num, &baudrate);
- uart_set_pin(self->uart_num, args[ARG_tx].u_int, args[ARG_rx].u_int, args[ARG_rts].u_int, args[ARG_cts].u_int);
- if (args[ARG_tx].u_int != UART_PIN_NO_CHANGE) {
- self->tx = args[ARG_tx].u_int;
+ if (args[ARG_tx].u_obj != MP_OBJ_NULL) {
+ self->tx = machine_pin_get_id(args[ARG_tx].u_obj);
}
- if (args[ARG_rx].u_int != UART_PIN_NO_CHANGE) {
- self->rx = args[ARG_rx].u_int;
+ if (args[ARG_rx].u_obj != MP_OBJ_NULL) {
+ self->rx = machine_pin_get_id(args[ARG_rx].u_obj);
}
- if (args[ARG_rts].u_int != UART_PIN_NO_CHANGE) {
- self->rts = args[ARG_rts].u_int;
+ if (args[ARG_rts].u_obj != MP_OBJ_NULL) {
+ self->rts = machine_pin_get_id(args[ARG_rts].u_obj);
}
- if (args[ARG_cts].u_int != UART_PIN_NO_CHANGE) {
- self->cts = args[ARG_cts].u_int;
+ if (args[ARG_cts].u_obj != MP_OBJ_NULL) {
+ self->cts = machine_pin_get_id(args[ARG_cts].u_obj);
}
+ uart_set_pin(self->uart_num, self->tx, self->rx, self->rts, self->cts);
// set data bits
switch (args[ARG_bits].u_int) {
@@ -273,9 +275,7 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
uint32_t char_time_ms = 12000 / baudrate + 1;
uint32_t rx_timeout = self->timeout_char / char_time_ms;
if (rx_timeout < 1) {
- #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)
uart_set_rx_full_threshold(self->uart_num, 1);
- #endif
uart_set_rx_timeout(self->uart_num, 1);
} else {
uart_set_rx_timeout(self->uart_num, rx_timeout);
@@ -317,7 +317,8 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
- .rx_flow_ctrl_thresh = 0
+ .rx_flow_ctrl_thresh = 0,
+ .source_clk = UART_SOURCE_CLK,
};
// create instance
@@ -399,42 +400,46 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Save settings
- uart_word_length_t word_length;
- uart_parity_t parity;
- uart_get_word_length(self->uart_num, &word_length);
- uart_get_parity(self->uart_num, &parity);
+ uint32_t baudrate;
+ uart_get_baudrate(self->uart_num, &baudrate);
- // Synthesise the break condition by either a longer word or using even parity
+ // Synthesise the break condition by reducing the baud rate,
+ // and cater for the worst case of 5 data bits, no parity.
uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000));
- if (word_length != UART_DATA_8_BITS) {
- uart_set_word_length(self->uart_num, UART_DATA_8_BITS);
- } else if (parity == UART_PARITY_DISABLE) {
- uart_set_parity(self->uart_num, UART_PARITY_EVEN);
- } else {
- // Cannot synthesise break
- mp_raise_OSError(MP_EPERM);
- }
+ uart_set_baudrate(self->uart_num, baudrate * 6 / 15);
char buf[1] = {0};
uart_write_bytes(self->uart_num, buf, 1);
uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000));
- // Restore original settings
- uart_set_word_length(self->uart_num, word_length);
- uart_set_parity(self->uart_num, parity);
+ // Restore original setting
+ uart_set_baudrate(self->uart_num, baudrate);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (uart_wait_tx_done(self->uart_num, 0) == ESP_OK) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
{ MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INV_TX) },
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INV_RX) },
@@ -500,6 +505,18 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr
if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num)
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint32_t baudrate;
+ uart_get_baudrate(self->uart_num, &baudrate);
+ uint32_t timeout = (3 + self->txbuf) * 13000 * 2 / baudrate;
+ if (uart_wait_tx_done(self->uart_num, timeout) == ESP_OK) {
+ ret = 0;
+ } else {
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
+ }
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -514,13 +531,12 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = machine_uart_print,
- .make_new = machine_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_uart_make_new,
+ print, machine_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &machine_uart_locals_dict
+ );
diff --git a/ports/esp32/machine_wdt.c b/ports/esp32/machine_wdt.c
index f0ec6928e05df..2cb6c518175eb 100644
--- a/ports/esp32/machine_wdt.c
+++ b/ports/esp32/machine_wdt.c
@@ -54,14 +54,16 @@ STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args
mp_raise_ValueError(NULL);
}
- // Convert milliseconds to seconds (esp_task_wdt_init needs seconds)
- args[ARG_timeout].u_int /= 1000;
-
if (args[ARG_timeout].u_int <= 0) {
mp_raise_ValueError(MP_ERROR_TEXT("WDT timeout too short"));
}
- mp_int_t rs_code = esp_task_wdt_init(args[ARG_timeout].u_int, true);
+ esp_task_wdt_config_t config = {
+ .timeout_ms = args[ARG_timeout].u_int,
+ .idle_core_mask = 0,
+ .trigger_panic = true,
+ };
+ mp_int_t rs_code = esp_task_wdt_reconfigure(&config);
if (rs_code != ESP_OK) {
mp_raise_OSError(rs_code);
}
@@ -83,9 +85,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
-const mp_obj_type_t machine_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = machine_wdt_make_new,
- .locals_dict = (mp_obj_t)&machine_wdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_wdt_make_new,
+ locals_dict, &machine_wdt_locals_dict
+ );
diff --git a/ports/esp32/main.c b/ports/esp32/main.c
index 14b7e14c62ff1..b8ba03e513fff 100644
--- a/ports/esp32/main.c
+++ b/ports/esp32/main.c
@@ -35,16 +35,9 @@
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_task.h"
-#include "soc/cpu.h"
+#include "esp_event.h"
#include "esp_log.h"
-
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/spiram.h"
-#endif
+#include "esp_psram.h"
#include "py/stackctrl.h"
#include "py/nlr.h"
@@ -67,6 +60,10 @@
#include "extmod/modbluetooth.h"
#endif
+#if MICROPY_ESPNOW
+#include "modespnow.h"
+#endif
+
// MicroPython runs as a task under FreeRTOS
#define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1)
#define MP_TASK_STACK_SIZE (16 * 1024)
@@ -84,11 +81,11 @@ int vprintf_null(const char *format, va_list ap) {
}
void mp_task(void *pvParameter) {
- volatile uint32_t sp = (uint32_t)get_sp();
+ volatile uint32_t sp = (uint32_t)esp_cpu_get_sp();
#if MICROPY_PY_THREAD
mp_thread_init(pxTaskGetStackStart(NULL), MP_TASK_STACK_SIZE / sizeof(uintptr_t));
#endif
- #if CONFIG_USB_ENABLED
+ #if CONFIG_USB_OTG_SUPPORTED
usb_init();
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
usb_serial_jtag_init();
@@ -98,50 +95,18 @@ void mp_task(void *pvParameter) {
#endif
machine_init();
- size_t mp_task_heap_size;
- void *mp_task_heap = NULL;
-
- #if CONFIG_SPIRAM_USE_MALLOC
- // SPIRAM is issued using MALLOC, fallback to normal allocation rules
- mp_task_heap = NULL;
- #elif CONFIG_ESP32_SPIRAM_SUPPORT
- // Try to use the entire external SPIRAM directly for the heap
- mp_task_heap = (void *)SOC_EXTRAM_DATA_LOW;
- switch (esp_spiram_get_chip_size()) {
- case ESP_SPIRAM_SIZE_16MBITS:
- mp_task_heap_size = 2 * 1024 * 1024;
- break;
- case ESP_SPIRAM_SIZE_32MBITS:
- case ESP_SPIRAM_SIZE_64MBITS:
- mp_task_heap_size = 4 * 1024 * 1024;
- break;
- default:
- // No SPIRAM, fallback to normal allocation
- mp_task_heap = NULL;
- break;
- }
- #elif CONFIG_ESP32S2_SPIRAM_SUPPORT || CONFIG_ESP32S3_SPIRAM_SUPPORT
- // Try to use the entire external SPIRAM directly for the heap
- size_t esp_spiram_size = esp_spiram_get_size();
- if (esp_spiram_size > 0) {
- mp_task_heap = (void *)SOC_EXTRAM_DATA_HIGH - esp_spiram_size;
- mp_task_heap_size = esp_spiram_size;
+ esp_err_t err = esp_event_loop_create_default();
+ if (err != ESP_OK) {
+ ESP_LOGE("esp_init", "can't create event loop: 0x%x\n", err);
}
- #endif
- if (mp_task_heap == NULL) {
- // Allocate the uPy heap using malloc and get the largest available region,
- // limiting to 1/2 total available memory to leave memory for the OS.
- #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)
- size_t heap_total = heap_caps_get_total_size(MALLOC_CAP_8BIT);
- #else
- multi_heap_info_t info;
- heap_caps_get_info(&info, MALLOC_CAP_8BIT);
- size_t heap_total = info.total_free_bytes + info.total_allocated_bytes;
- #endif
- mp_task_heap_size = MIN(heap_caps_get_largest_free_block(MALLOC_CAP_8BIT), heap_total / 2);
- mp_task_heap = malloc(mp_task_heap_size);
- }
+ // Allocate the uPy heap using malloc and get the largest available region,
+ // limiting to 1/2 total available memory to leave memory for the OS.
+ // When SPIRAM is enabled, this will allocate from SPIRAM.
+ uint32_t caps = MALLOC_CAP_8BIT;
+ size_t heap_total = heap_caps_get_total_size(caps);
+ size_t mp_task_heap_size = MIN(heap_caps_get_largest_free_block(caps), heap_total / 2);
+ void *mp_task_heap = heap_caps_malloc(mp_task_heap_size, caps);
soft_reset:
// initialise the stack pointer for the main thread
@@ -161,7 +126,7 @@ void mp_task(void *pvParameter) {
#endif
// run boot-up scripts
- pyexec_frozen_module("_boot.py");
+ pyexec_frozen_module("_boot.py", false);
pyexec_file_if_exists("boot.py");
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
int ret = pyexec_file_if_exists("main.py");
@@ -190,6 +155,11 @@ void mp_task(void *pvParameter) {
mp_bluetooth_deinit();
#endif
+ #if MICROPY_ESPNOW
+ espnow_deinit(mp_const_none);
+ MP_STATE_PORT(espnow_singleton) = NULL;
+ #endif
+
machine_timer_deinit_all();
#if MICROPY_PY_THREAD
@@ -215,7 +185,9 @@ void mp_task(void *pvParameter) {
// TODO: machine_rmt_deinit_all();
machine_pins_deinit();
machine_deinit();
- usocket_events_deinit();
+ #if MICROPY_PY_SOCKET_EVENTS
+ socket_events_deinit();
+ #endif
mp_deinit();
fflush(stdout);
@@ -265,3 +237,5 @@ void *esp_native_code_commit(void *buf, size_t len, void *reloc) {
memcpy(p, buf, len);
return p;
}
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t native_code_pointers);
diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt
deleted file mode 100644
index 9ac6537f86be1..0000000000000
--- a/ports/esp32/main/CMakeLists.txt
+++ /dev/null
@@ -1,223 +0,0 @@
-# Set location of base MicroPython directory.
-if(NOT MICROPY_DIR)
- get_filename_component(MICROPY_DIR ${PROJECT_DIR}/../.. ABSOLUTE)
-endif()
-
-# Include core source components.
-include(${MICROPY_DIR}/py/py.cmake)
-
-if(NOT CMAKE_BUILD_EARLY_EXPANSION)
- # Enable extmod components that will be configured by extmod.cmake.
- # A board may also have enabled additional components.
- set(MICROPY_PY_BTREE ON)
-
- include(${MICROPY_DIR}/py/usermod.cmake)
- include(${MICROPY_DIR}/extmod/extmod.cmake)
-endif()
-
-set(MICROPY_QSTRDEFS_PORT
- ${PROJECT_DIR}/qstrdefsport.h
-)
-
-set(MICROPY_SOURCE_SHARED
- ${MICROPY_DIR}/shared/readline/readline.c
- ${MICROPY_DIR}/shared/netutils/netutils.c
- ${MICROPY_DIR}/shared/timeutils/timeutils.c
- ${MICROPY_DIR}/shared/runtime/interrupt_char.c
- ${MICROPY_DIR}/shared/runtime/stdout_helpers.c
- ${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
- ${MICROPY_DIR}/shared/runtime/pyexec.c
-)
-
-set(MICROPY_SOURCE_LIB
- ${MICROPY_DIR}/lib/littlefs/lfs1.c
- ${MICROPY_DIR}/lib/littlefs/lfs1_util.c
- ${MICROPY_DIR}/lib/littlefs/lfs2.c
- ${MICROPY_DIR}/lib/littlefs/lfs2_util.c
- ${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c
- ${MICROPY_DIR}/lib/oofatfs/ff.c
- ${MICROPY_DIR}/lib/oofatfs/ffunicode.c
-)
-if(IDF_TARGET STREQUAL "esp32c3")
- list(APPEND MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/runtime/gchelper_generic.c)
-endif()
-
-set(MICROPY_SOURCE_DRIVERS
- ${MICROPY_DIR}/drivers/bus/softspi.c
- ${MICROPY_DIR}/drivers/dht/dht.c
-)
-
-set(MICROPY_SOURCE_PORT
- ${PROJECT_DIR}/main.c
- ${PROJECT_DIR}/uart.c
- ${PROJECT_DIR}/usb.c
- ${PROJECT_DIR}/usb_serial_jtag.c
- ${PROJECT_DIR}/gccollect.c
- ${PROJECT_DIR}/mphalport.c
- ${PROJECT_DIR}/fatfs_port.c
- ${PROJECT_DIR}/help.c
- ${PROJECT_DIR}/modutime.c
- ${PROJECT_DIR}/machine_bitstream.c
- ${PROJECT_DIR}/machine_timer.c
- ${PROJECT_DIR}/machine_pin.c
- ${PROJECT_DIR}/machine_touchpad.c
- ${PROJECT_DIR}/machine_adc.c
- ${PROJECT_DIR}/machine_adcblock.c
- ${PROJECT_DIR}/machine_dac.c
- ${PROJECT_DIR}/machine_i2c.c
- ${PROJECT_DIR}/machine_i2s.c
- ${PROJECT_DIR}/machine_uart.c
- ${PROJECT_DIR}/modmachine.c
- ${PROJECT_DIR}/modnetwork.c
- ${PROJECT_DIR}/network_lan.c
- ${PROJECT_DIR}/network_ppp.c
- ${PROJECT_DIR}/network_wlan.c
- ${PROJECT_DIR}/mpnimbleport.c
- ${PROJECT_DIR}/modsocket.c
- ${PROJECT_DIR}/modesp.c
- ${PROJECT_DIR}/esp32_nvs.c
- ${PROJECT_DIR}/esp32_partition.c
- ${PROJECT_DIR}/esp32_rmt.c
- ${PROJECT_DIR}/esp32_ulp.c
- ${PROJECT_DIR}/modesp32.c
- ${PROJECT_DIR}/machine_hw_spi.c
- ${PROJECT_DIR}/machine_wdt.c
- ${PROJECT_DIR}/mpthreadport.c
- ${PROJECT_DIR}/machine_rtc.c
- ${PROJECT_DIR}/machine_sdcard.c
-)
-
-set(MICROPY_SOURCE_QSTR
- ${MICROPY_SOURCE_PY}
- ${MICROPY_SOURCE_EXTMOD}
- ${MICROPY_SOURCE_USERMOD}
- ${MICROPY_SOURCE_SHARED}
- ${MICROPY_SOURCE_LIB}
- ${MICROPY_SOURCE_PORT}
- ${MICROPY_SOURCE_BOARD}
-)
-
-set(IDF_COMPONENTS
- app_update
- bootloader_support
- bt
- driver
- esp_adc_cal
- esp_common
- esp_eth
- esp_event
- esp_ringbuf
- esp_rom
- esp_wifi
- freertos
- heap
- log
- lwip
- mbedtls
- mdns
- newlib
- nvs_flash
- sdmmc
- soc
- spi_flash
- tcpip_adapter
- ulp
- vfs
- xtensa
-)
-
-if(IDF_VERSION_MINOR GREATER_EQUAL 1 OR IDF_VERSION_MAJOR GREATER_EQUAL 5)
- list(APPEND IDF_COMPONENTS esp_netif)
-endif()
-
-if(IDF_VERSION_MINOR GREATER_EQUAL 2 OR IDF_VERSION_MAJOR GREATER_EQUAL 5)
- list(APPEND IDF_COMPONENTS esp_system)
- list(APPEND IDF_COMPONENTS esp_timer)
-endif()
-
-if(IDF_VERSION_MINOR GREATER_EQUAL 3 OR IDF_VERSION_MAJOR GREATER_EQUAL 5)
- list(APPEND IDF_COMPONENTS esp_hw_support)
- list(APPEND IDF_COMPONENTS esp_pm)
- list(APPEND IDF_COMPONENTS hal)
-endif()
-
-if(IDF_TARGET STREQUAL "esp32")
- list(APPEND IDF_COMPONENTS esp32)
-elseif(IDF_TARGET STREQUAL "esp32c3")
- list(APPEND IDF_COMPONENTS esp32c3)
- list(APPEND IDF_COMPONENTS riscv)
-elseif(IDF_TARGET STREQUAL "esp32s2")
- list(APPEND IDF_COMPONENTS esp32s2)
- list(APPEND IDF_COMPONENTS tinyusb)
-elseif(IDF_TARGET STREQUAL "esp32s3")
- list(APPEND IDF_COMPONENTS esp32s3)
- list(APPEND IDF_COMPONENTS tinyusb)
-endif()
-
-# Register the main IDF component.
-idf_component_register(
- SRCS
- ${MICROPY_SOURCE_PY}
- ${MICROPY_SOURCE_EXTMOD}
- ${MICROPY_SOURCE_SHARED}
- ${MICROPY_SOURCE_LIB}
- ${MICROPY_SOURCE_DRIVERS}
- ${MICROPY_SOURCE_PORT}
- ${MICROPY_SOURCE_BOARD}
- INCLUDE_DIRS
- ${MICROPY_INC_CORE}
- ${MICROPY_INC_USERMOD}
- ${MICROPY_PORT_DIR}
- ${MICROPY_BOARD_DIR}
- ${CMAKE_BINARY_DIR}
- REQUIRES
- ${IDF_COMPONENTS}
-)
-
-# Set the MicroPython target as the current (main) IDF component target.
-set(MICROPY_TARGET ${COMPONENT_TARGET})
-
-# Define mpy-cross flags, for use with frozen code.
-set(MICROPY_CROSS_FLAGS -march=xtensawin)
-
-# Set compile options for this port.
-target_compile_definitions(${MICROPY_TARGET} PUBLIC
- ${MICROPY_DEF_CORE}
- MICROPY_ESP_IDF_4=1
- MICROPY_VFS_FAT=1
- MICROPY_VFS_LFS2=1
- FFCONF_H=\"${MICROPY_OOFATFS_DIR}/ffconf.h\"
- LFS1_NO_MALLOC LFS1_NO_DEBUG LFS1_NO_WARN LFS1_NO_ERROR LFS1_NO_ASSERT
- LFS2_NO_MALLOC LFS2_NO_DEBUG LFS2_NO_WARN LFS2_NO_ERROR LFS2_NO_ASSERT
-)
-
-# Disable some warnings to keep the build output clean.
-target_compile_options(${MICROPY_TARGET} PUBLIC
- -Wno-clobbered
- -Wno-deprecated-declarations
- -Wno-missing-field-initializers
-)
-
-# Add additional extmod and usermod components.
-target_link_libraries(${MICROPY_TARGET} micropy_extmod_btree)
-target_link_libraries(${MICROPY_TARGET} usermod)
-
-
-# Collect all of the include directories and compile definitions for the IDF components.
-foreach(comp ${IDF_COMPONENTS})
- micropy_gather_target_properties(__idf_${comp})
-endforeach()
-
-if(IDF_VERSION_MINOR GREATER_EQUAL 2 OR IDF_VERSION_MAJOR GREATER_EQUAL 5)
- # These paths cannot currently be found by the IDF_COMPONENTS search loop above,
- # so add them explicitly.
- list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/soc/soc/${IDF_TARGET}/include)
- list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/soc/soc/include)
- if(IDF_VERSION_MINOR GREATER_EQUAL 3)
- list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/tinyusb/additions/include)
- list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/tinyusb/tinyusb/src)
- endif()
-endif()
-
-# Include the main MicroPython cmake rules.
-include(${MICROPY_DIR}/py/mkrules.cmake)
diff --git a/ports/esp32/main_esp32/CMakeLists.txt b/ports/esp32/main_esp32/CMakeLists.txt
new file mode 100644
index 0000000000000..40188abff8e57
--- /dev/null
+++ b/ports/esp32/main_esp32/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Set location of base MicroPython directory.
+if(NOT MICROPY_DIR)
+ get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../.. ABSOLUTE)
+endif()
+
+# Set location of the ESP32 port directory.
+if(NOT MICROPY_PORT_DIR)
+ get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
+endif()
+
+include(${MICROPY_PORT_DIR}/esp32_common.cmake)
diff --git a/ports/esp32/main_esp32/idf_component.yml b/ports/esp32/main_esp32/idf_component.yml
new file mode 100644
index 0000000000000..8be21ed2fbe87
--- /dev/null
+++ b/ports/esp32/main_esp32/idf_component.yml
@@ -0,0 +1,5 @@
+## IDF Component Manager Manifest File
+dependencies:
+ espressif/mdns: "~1.1.0"
+ idf:
+ version: ">=5.0.2"
diff --git a/ports/esp32/main_esp32c3/CMakeLists.txt b/ports/esp32/main_esp32c3/CMakeLists.txt
new file mode 100644
index 0000000000000..307c0f32183a9
--- /dev/null
+++ b/ports/esp32/main_esp32c3/CMakeLists.txt
@@ -0,0 +1,14 @@
+# Set location of base MicroPython directory.
+if(NOT MICROPY_DIR)
+ get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../.. ABSOLUTE)
+endif()
+
+# Set location of the ESP32 port directory.
+if(NOT MICROPY_PORT_DIR)
+ get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
+endif()
+
+list(APPEND MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/runtime/gchelper_generic.c)
+list(APPEND IDF_COMPONENTS riscv)
+
+include(${MICROPY_PORT_DIR}/esp32_common.cmake)
diff --git a/ports/esp32/main_esp32c3/idf_component.yml b/ports/esp32/main_esp32c3/idf_component.yml
new file mode 100644
index 0000000000000..8be21ed2fbe87
--- /dev/null
+++ b/ports/esp32/main_esp32c3/idf_component.yml
@@ -0,0 +1,5 @@
+## IDF Component Manager Manifest File
+dependencies:
+ espressif/mdns: "~1.1.0"
+ idf:
+ version: ">=5.0.2"
diff --git a/ports/esp32/main_esp32s2/CMakeLists.txt b/ports/esp32/main_esp32s2/CMakeLists.txt
new file mode 100644
index 0000000000000..40188abff8e57
--- /dev/null
+++ b/ports/esp32/main_esp32s2/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Set location of base MicroPython directory.
+if(NOT MICROPY_DIR)
+ get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../.. ABSOLUTE)
+endif()
+
+# Set location of the ESP32 port directory.
+if(NOT MICROPY_PORT_DIR)
+ get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
+endif()
+
+include(${MICROPY_PORT_DIR}/esp32_common.cmake)
diff --git a/ports/esp32/main_esp32s2/idf_component.yml b/ports/esp32/main_esp32s2/idf_component.yml
new file mode 100644
index 0000000000000..69e27bf8b54bc
--- /dev/null
+++ b/ports/esp32/main_esp32s2/idf_component.yml
@@ -0,0 +1,6 @@
+## IDF Component Manager Manifest File
+dependencies:
+ espressif/mdns: "~1.1.0"
+ espressif/esp_tinyusb: "~1.0.0"
+ idf:
+ version: ">=5.0.2"
diff --git a/ports/esp32/main_esp32s3/CMakeLists.txt b/ports/esp32/main_esp32s3/CMakeLists.txt
new file mode 100644
index 0000000000000..40188abff8e57
--- /dev/null
+++ b/ports/esp32/main_esp32s3/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Set location of base MicroPython directory.
+if(NOT MICROPY_DIR)
+ get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../.. ABSOLUTE)
+endif()
+
+# Set location of the ESP32 port directory.
+if(NOT MICROPY_PORT_DIR)
+ get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
+endif()
+
+include(${MICROPY_PORT_DIR}/esp32_common.cmake)
diff --git a/ports/esp32/main_esp32s3/idf_component.yml b/ports/esp32/main_esp32s3/idf_component.yml
new file mode 100644
index 0000000000000..69e27bf8b54bc
--- /dev/null
+++ b/ports/esp32/main_esp32s3/idf_component.yml
@@ -0,0 +1,6 @@
+## IDF Component Manager Manifest File
+dependencies:
+ espressif/mdns: "~1.1.0"
+ espressif/esp_tinyusb: "~1.0.0"
+ idf:
+ version: ">=5.0.2"
diff --git a/ports/esp32/modesp.c b/ports/esp32/modesp.c
index 0c6429be7f1ed..4726ce5874209 100644
--- a/ports/esp32/modesp.c
+++ b/ports/esp32/modesp.c
@@ -29,13 +29,12 @@
#include
+#include "esp_flash.h"
#include "esp_log.h"
-#include "esp_spi_flash.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
-#include "drivers/dht/dht.h"
STATIC mp_obj_t esp_osdebug(size_t n_args, const mp_obj_t *args) {
esp_log_level_t level = LOG_LOCAL_LEVEL;
@@ -54,33 +53,33 @@ STATIC mp_obj_t esp_osdebug(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_osdebug_obj, 1, 2, esp_osdebug);
-STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t buf_in) {
+STATIC mp_obj_t esp_flash_read_(mp_obj_t offset_in, mp_obj_t buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
- esp_err_t res = spi_flash_read(offset, bufinfo.buf, bufinfo.len);
+ esp_err_t res = esp_flash_read(NULL, bufinfo.buf, offset, bufinfo.len);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read_);
-STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, mp_obj_t buf_in) {
+STATIC mp_obj_t esp_flash_write_(mp_obj_t offset_in, mp_obj_t buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
- esp_err_t res = spi_flash_write(offset, bufinfo.buf, bufinfo.len);
+ esp_err_t res = esp_flash_write(NULL, bufinfo.buf, offset, bufinfo.len);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write_);
STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
mp_int_t sector = mp_obj_get_int(sector_in);
- esp_err_t res = spi_flash_erase_sector(sector);
+ esp_err_t res = esp_flash_erase_region(NULL, sector * 4096, 4096);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
@@ -89,7 +88,9 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
STATIC mp_obj_t esp_flash_size(void) {
- return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
+ uint32_t size;
+ esp_flash_get_size(NULL, &size);
+ return mp_obj_new_int_from_uint(size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
@@ -99,14 +100,14 @@ STATIC mp_obj_t esp_flash_user_start(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);
STATIC mp_obj_t esp_gpio_matrix_in(mp_obj_t pin, mp_obj_t sig, mp_obj_t inv) {
- gpio_matrix_in(mp_obj_get_int(pin), mp_obj_get_int(sig), mp_obj_get_int(inv));
+ esp_rom_gpio_connect_in_signal(mp_obj_get_int(pin), mp_obj_get_int(sig), mp_obj_get_int(inv));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_gpio_matrix_in_obj, esp_gpio_matrix_in);
STATIC mp_obj_t esp_gpio_matrix_out(size_t n_args, const mp_obj_t *args) {
(void)n_args;
- gpio_matrix_out(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3]));
+ esp_rom_gpio_connect_out_signal(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3]));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_gpio_matrix_out_obj, 4, 4, esp_gpio_matrix_out);
@@ -125,8 +126,6 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_in), MP_ROM_PTR(&esp_gpio_matrix_in_obj) },
{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_out), MP_ROM_PTR(&esp_gpio_matrix_out_obj) },
- { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
-
// Constants for second arg of osdebug()
{ MP_ROM_QSTR(MP_QSTR_LOG_NONE), MP_ROM_INT((mp_uint_t)ESP_LOG_NONE)},
{ MP_ROM_QSTR(MP_QSTR_LOG_ERROR), MP_ROM_INT((mp_uint_t)ESP_LOG_ERROR)},
diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c
index 017db36e22adf..ef3ad0b76d459 100644
--- a/ports/esp32/modesp32.c
+++ b/ports/esp32/modesp32.c
@@ -45,10 +45,8 @@
#include "modesp32.h"
// These private includes are needed for idf_heap_info.
-#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
#define MULTI_HEAP_FREERTOS
#include "../multi_heap_platform.h"
-#endif
#include "../heap_private.h"
STATIC mp_obj_t esp32_wake_on_touch(const mp_obj_t wake) {
@@ -161,21 +159,15 @@ STATIC mp_obj_t esp32_raw_temperature(void) {
CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);
SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE);
SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP);
- ets_delay_us(100);
+ esp_rom_delay_us(100);
SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT);
- ets_delay_us(5);
+ esp_rom_delay_us(5);
int res = GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT, SENS_TSENS_OUT_S);
return mp_obj_new_int(res);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_raw_temperature_obj, esp32_raw_temperature);
-STATIC mp_obj_t esp32_hall_sensor(void) {
- adc1_config_width(ADC_WIDTH_12Bit);
- return MP_OBJ_NEW_SMALL_INT(hall_sensor_read());
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_hall_sensor_obj, esp32_hall_sensor);
-
#endif
STATIC mp_obj_t esp32_idf_heap_info(const mp_obj_t cap_in) {
@@ -210,14 +202,13 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_gpio_deep_sleep_hold), MP_ROM_PTR(&esp32_gpio_deep_sleep_hold_obj) },
#if CONFIG_IDF_TARGET_ESP32
{ MP_ROM_QSTR(MP_QSTR_raw_temperature), MP_ROM_PTR(&esp32_raw_temperature_obj) },
- { MP_ROM_QSTR(MP_QSTR_hall_sensor), MP_ROM_PTR(&esp32_hall_sensor_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_idf_heap_info), MP_ROM_PTR(&esp32_idf_heap_info_obj) },
{ MP_ROM_QSTR(MP_QSTR_NVS), MP_ROM_PTR(&esp32_nvs_type) },
{ MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) },
{ MP_ROM_QSTR(MP_QSTR_RMT), MP_ROM_PTR(&esp32_rmt_type) },
- #if CONFIG_IDF_TARGET_ESP32
+ #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
{ MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) },
#endif
diff --git a/ports/esp32/modespnow.c b/ports/esp32/modespnow.c
new file mode 100644
index 0000000000000..08836c0ad790e
--- /dev/null
+++ b/ports/esp32/modespnow.c
@@ -0,0 +1,861 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017-2020 Nick Moore
+ * Copyright (c) 2018 shawwwn
+ * Copyright (c) 2020-2021 Glenn Moloney @glenn20
+ *
+ * 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 "esp_log.h"
+#include "esp_now.h"
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "py/mperrno.h"
+#include "py/obj.h"
+#include "py/objstr.h"
+#include "py/objarray.h"
+#include "py/stream.h"
+#include "py/binary.h"
+#include "py/ringbuf.h"
+
+#include "mpconfigport.h"
+#include "mphalport.h"
+#include "modnetwork.h"
+#include "modespnow.h"
+
+#ifndef MICROPY_ESPNOW_RSSI
+// Include code to track rssi of peers
+#define MICROPY_ESPNOW_RSSI 1
+#endif
+#ifndef MICROPY_ESPNOW_EXTRA_PEER_METHODS
+// Include mod_peer(),get_peer(),peer_count()
+#define MICROPY_ESPNOW_EXTRA_PEER_METHODS 1
+#endif
+
+// Relies on gcc Variadic Macros and Statement Expressions
+#define NEW_TUPLE(...) \
+ ({mp_obj_t _z[] = {__VA_ARGS__}; mp_obj_new_tuple(MP_ARRAY_SIZE(_z), _z); })
+
+static const uint8_t ESPNOW_MAGIC = 0x99;
+
+// ESPNow packet format for the receive buffer.
+// Use this for peeking at the header of the next packet in the buffer.
+typedef struct {
+ uint8_t magic; // = ESPNOW_MAGIC
+ uint8_t msg_len; // Length of the message
+ #if MICROPY_ESPNOW_RSSI
+ uint32_t time_ms; // Timestamp (ms) when packet is received
+ int8_t rssi; // RSSI value (dBm) (-127 to 0)
+ #endif // MICROPY_ESPNOW_RSSI
+} __attribute__((packed)) espnow_hdr_t;
+
+typedef struct {
+ espnow_hdr_t hdr; // The header
+ uint8_t peer[6]; // Peer address
+ uint8_t msg[0]; // Message is up to 250 bytes
+} __attribute__((packed)) espnow_pkt_t;
+
+// The maximum length of an espnow packet (bytes)
+static const size_t MAX_PACKET_LEN = (
+ (sizeof(espnow_pkt_t) + ESP_NOW_MAX_DATA_LEN));
+
+// Enough for 2 full-size packets: 2 * (6 + 7 + 250) = 526 bytes
+// Will allocate an additional 7 bytes for buffer overhead
+static const size_t DEFAULT_RECV_BUFFER_SIZE = (2 * MAX_PACKET_LEN);
+
+// Default timeout (millisec) to wait for incoming ESPNow messages (5 minutes).
+static const size_t DEFAULT_RECV_TIMEOUT_MS = (5 * 60 * 1000);
+
+// Time to wait (millisec) for responses from sent packets: (2 seconds).
+static const size_t DEFAULT_SEND_TIMEOUT_MS = (2 * 1000);
+
+// Number of milliseconds to wait for pending responses to sent packets.
+// This is a fallback which should never be reached.
+static const mp_uint_t PENDING_RESPONSES_TIMEOUT_MS = 100;
+static const mp_uint_t PENDING_RESPONSES_BUSY_POLL_MS = 10;
+
+// The data structure for the espnow_singleton.
+typedef struct _esp_espnow_obj_t {
+ mp_obj_base_t base;
+
+ ringbuf_t *recv_buffer; // A buffer for received packets
+ size_t recv_buffer_size; // The size of the recv_buffer
+ mp_int_t recv_timeout_ms; // Timeout for recv()
+ volatile size_t rx_packets; // # of received packets
+ size_t dropped_rx_pkts; // # of dropped packets (buffer full)
+ size_t tx_packets; // # of sent packets
+ volatile size_t tx_responses; // # of sent packet responses received
+ volatile size_t tx_failures; // # of sent packet responses failed
+ size_t peer_count; // Cache the # of peers for send(sync=True)
+ mp_obj_t recv_cb; // Callback when a packet is received
+ mp_obj_t recv_cb_arg; // Argument passed to callback
+ #if MICROPY_ESPNOW_RSSI
+ mp_obj_t peers_table; // A dictionary of discovered peers
+ #endif // MICROPY_ESPNOW_RSSI
+} esp_espnow_obj_t;
+
+const mp_obj_type_t esp_espnow_type;
+
+// ### Initialisation and Config functions
+//
+
+// Return a pointer to the ESPNow module singleton
+// If state == INITIALISED check the device has been initialised.
+// Raises OSError if not initialised and state == INITIALISED.
+static esp_espnow_obj_t *_get_singleton() {
+ return MP_STATE_PORT(espnow_singleton);
+}
+
+static esp_espnow_obj_t *_get_singleton_initialised() {
+ esp_espnow_obj_t *self = _get_singleton();
+ // assert(self);
+ if (self->recv_buffer == NULL) {
+ // Throw an espnow not initialised error
+ check_esp_err(ESP_ERR_ESPNOW_NOT_INIT);
+ }
+ return self;
+}
+
+// Allocate and initialise the ESPNow module as a singleton.
+// Returns the initialised espnow_singleton.
+STATIC mp_obj_t espnow_make_new(const mp_obj_type_t *type, size_t n_args,
+ size_t n_kw, const mp_obj_t *all_args) {
+
+ // The espnow_singleton must be defined in MICROPY_PORT_ROOT_POINTERS
+ // (see mpconfigport.h) to prevent memory allocated here from being
+ // garbage collected.
+ // NOTE: on soft reset the espnow_singleton MUST be set to NULL and the
+ // ESP-NOW functions de-initialised (see main.c).
+ esp_espnow_obj_t *self = MP_STATE_PORT(espnow_singleton);
+ if (self != NULL) {
+ return self;
+ }
+ self = m_new_obj(esp_espnow_obj_t);
+ self->base.type = &esp_espnow_type;
+ self->recv_buffer_size = DEFAULT_RECV_BUFFER_SIZE;
+ self->recv_timeout_ms = DEFAULT_RECV_TIMEOUT_MS;
+ self->recv_buffer = NULL; // Buffer is allocated in espnow_init()
+ self->recv_cb = mp_const_none;
+ #if MICROPY_ESPNOW_RSSI
+ self->peers_table = mp_obj_new_dict(0);
+ // Prevent user code modifying the dict
+ mp_obj_dict_get_map(self->peers_table)->is_fixed = 1;
+ #endif // MICROPY_ESPNOW_RSSI
+
+ // Set the global singleton pointer for the espnow protocol.
+ MP_STATE_PORT(espnow_singleton) = self;
+
+ return self;
+}
+
+// Forward declare the send and recv ESPNow callbacks
+STATIC void send_cb(const uint8_t *mac_addr, esp_now_send_status_t status);
+
+STATIC void recv_cb(const esp_now_recv_info_t *recv_info, const uint8_t *msg, int msg_len);
+
+// ESPNow.init(): Initialise the data buffers and ESP-NOW functions.
+// Initialise the Espressif ESPNOW software stack, register callbacks and
+// allocate the recv data buffers.
+// Returns None.
+static mp_obj_t espnow_init(mp_obj_t _) {
+ esp_espnow_obj_t *self = _get_singleton();
+ if (self->recv_buffer == NULL) { // Already initialised
+ self->recv_buffer = m_new_obj(ringbuf_t);
+ ringbuf_alloc(self->recv_buffer, self->recv_buffer_size);
+
+ esp_initialise_wifi(); // Call the wifi init code in network_wlan.c
+ check_esp_err(esp_now_init());
+ check_esp_err(esp_now_register_recv_cb(recv_cb));
+ check_esp_err(esp_now_register_send_cb(send_cb));
+ }
+ return mp_const_none;
+}
+
+// ESPNow.deinit(): De-initialise the ESPNOW software stack, disable callbacks
+// and deallocate the recv data buffers.
+// Note: this function is called from main.c:mp_task() to cleanup before soft
+// reset, so cannot be declared STATIC and must guard against self == NULL;.
+mp_obj_t espnow_deinit(mp_obj_t _) {
+ esp_espnow_obj_t *self = _get_singleton();
+ if (self != NULL && self->recv_buffer != NULL) {
+ check_esp_err(esp_now_unregister_recv_cb());
+ check_esp_err(esp_now_unregister_send_cb());
+ check_esp_err(esp_now_deinit());
+ self->recv_buffer->buf = NULL;
+ self->recv_buffer = NULL;
+ self->peer_count = 0; // esp_now_deinit() removes all peers.
+ self->tx_packets = self->tx_responses;
+ }
+ return mp_const_none;
+}
+
+STATIC mp_obj_t espnow_active(size_t n_args, const mp_obj_t *args) {
+ esp_espnow_obj_t *self = _get_singleton();
+ if (n_args > 1) {
+ if (mp_obj_is_true(args[1])) {
+ espnow_init(self);
+ } else {
+ espnow_deinit(self);
+ }
+ }
+ return self->recv_buffer != NULL ? mp_const_true : mp_const_false;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_active_obj, 1, 2, espnow_active);
+
+// ESPNow.config(['param'|param=value, ..])
+// Get or set configuration values. Supported config params:
+// buffer: size of buffer for rx packets (default=514 bytes)
+// timeout: Default read timeout (default=300,000 milliseconds)
+STATIC mp_obj_t espnow_config(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ esp_espnow_obj_t *self = _get_singleton();
+ enum { ARG_get, ARG_rxbuf, ARG_timeout_ms, ARG_rate };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_timeout_ms, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MIN} },
+ { MP_QSTR_rate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ };
+ 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);
+
+ if (args[ARG_rxbuf].u_int >= 0) {
+ self->recv_buffer_size = args[ARG_rxbuf].u_int;
+ }
+ if (args[ARG_timeout_ms].u_int != INT_MIN) {
+ self->recv_timeout_ms = args[ARG_timeout_ms].u_int;
+ }
+ if (args[ARG_rate].u_int >= 0) {
+ esp_initialise_wifi(); // Call the wifi init code in network_wlan.c
+ check_esp_err(esp_wifi_config_espnow_rate(ESP_IF_WIFI_STA, args[ARG_rate].u_int));
+ check_esp_err(esp_wifi_config_espnow_rate(ESP_IF_WIFI_AP, args[ARG_rate].u_int));
+ }
+ if (args[ARG_get].u_obj == MP_OBJ_NULL) {
+ return mp_const_none;
+ }
+#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
+ // Return the value of the requested parameter
+ uintptr_t name = (uintptr_t)args[ARG_get].u_obj;
+ if (name == QS(MP_QSTR_rxbuf)) {
+ return mp_obj_new_int(self->recv_buffer_size);
+ } else if (name == QS(MP_QSTR_timeout_ms)) {
+ return mp_obj_new_int(self->recv_timeout_ms);
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
+ }
+#undef QS
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espnow_config_obj, 1, espnow_config);
+
+// ESPNow.irq(recv_cb)
+// Set callback function to be invoked when a message is received.
+STATIC mp_obj_t espnow_irq(size_t n_args, const mp_obj_t *args) {
+ esp_espnow_obj_t *self = _get_singleton();
+ mp_obj_t recv_cb = args[1];
+ if (recv_cb != mp_const_none && !mp_obj_is_callable(recv_cb)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid handler"));
+ }
+ self->recv_cb = recv_cb;
+ self->recv_cb_arg = (n_args > 2) ? args[2] : mp_const_none;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_irq_obj, 2, 3, espnow_irq);
+
+// ESPnow.stats(): Provide some useful stats.
+// Returns a tuple of:
+// (tx_pkts, tx_responses, tx_failures, rx_pkts, dropped_rx_pkts)
+STATIC mp_obj_t espnow_stats(mp_obj_t _) {
+ const esp_espnow_obj_t *self = _get_singleton();
+ return NEW_TUPLE(
+ mp_obj_new_int(self->tx_packets),
+ mp_obj_new_int(self->tx_responses),
+ mp_obj_new_int(self->tx_failures),
+ mp_obj_new_int(self->rx_packets),
+ mp_obj_new_int(self->dropped_rx_pkts));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_stats_obj, espnow_stats);
+
+#if MICROPY_ESPNOW_RSSI
+// ### Maintaining the peer table and reading RSSI values
+//
+// We maintain a peers table for several reasons, to:
+// - support monitoring the RSSI values for all peers; and
+// - to return unique bytestrings for each peer which supports more efficient
+// application memory usage and peer handling.
+
+// Lookup a peer in the peers table and return a reference to the item in the
+// peers_table. Add peer to the table if it is not found (may alloc memory).
+// Will not return NULL.
+static mp_map_elem_t *_lookup_add_peer(esp_espnow_obj_t *self, const uint8_t *peer) {
+ // We do not want to allocate any new memory in the case that the peer
+ // already exists in the peers_table (which is almost all the time).
+ // So, we use a byte string on the stack and look that up in the dict.
+ mp_map_t *map = mp_obj_dict_get_map(self->peers_table);
+ mp_obj_str_t peer_obj = {{&mp_type_bytes}, 0, ESP_NOW_ETH_ALEN, peer};
+ mp_map_elem_t *item = mp_map_lookup(map, &peer_obj, MP_MAP_LOOKUP);
+ if (item == NULL) {
+ // If not found, add the peer using a new bytestring
+ map->is_fixed = 0; // Allow to modify the dict
+ mp_obj_t new_peer = mp_obj_new_bytes(peer, ESP_NOW_ETH_ALEN);
+ item = mp_map_lookup(map, new_peer, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
+ item->value = mp_obj_new_list(2, NULL);
+ map->is_fixed = 1; // Relock the dict
+ }
+ return item;
+}
+
+// Update the peers table with the new rssi value from a received pkt and
+// return a reference to the item in the peers_table.
+static mp_map_elem_t *_update_rssi(const uint8_t *peer, int8_t rssi, uint32_t time_ms) {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+ // Lookup the peer in the device table
+ mp_map_elem_t *item = _lookup_add_peer(self, peer);
+ mp_obj_list_t *list = MP_OBJ_TO_PTR(item->value);
+ list->items[0] = MP_OBJ_NEW_SMALL_INT(rssi);
+ list->items[1] = mp_obj_new_int(time_ms);
+ return item;
+}
+#endif // MICROPY_ESPNOW_RSSI
+
+// Return C pointer to byte memory string/bytes/bytearray in obj.
+// Raise ValueError if the length does not match expected len.
+static uint8_t *_get_bytes_len_rw(mp_obj_t obj, size_t len, mp_uint_t rw) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(obj, &bufinfo, rw);
+ if (bufinfo.len != len) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer length"));
+ }
+ return (uint8_t *)bufinfo.buf;
+}
+
+static uint8_t *_get_bytes_len(mp_obj_t obj, size_t len) {
+ return _get_bytes_len_rw(obj, len, MP_BUFFER_READ);
+}
+
+static uint8_t *_get_bytes_len_w(mp_obj_t obj, size_t len) {
+ return _get_bytes_len_rw(obj, len, MP_BUFFER_WRITE);
+}
+
+// Return C pointer to the MAC address.
+// Raise ValueError if mac_addr is wrong type or is not 6 bytes long.
+static const uint8_t *_get_peer(mp_obj_t mac_addr) {
+ return mp_obj_is_true(mac_addr)
+ ? _get_bytes_len(mac_addr, ESP_NOW_ETH_ALEN) : NULL;
+}
+
+// Copy data from the ring buffer - wait if buffer is empty up to timeout_ms
+// 0: Success
+// -1: Not enough data available to complete read (try again later)
+// -2: Requested read is larger than buffer - will never succeed
+static int ringbuf_get_bytes_wait(ringbuf_t *r, uint8_t *data, size_t len, mp_int_t timeout_ms) {
+ mp_uint_t start = mp_hal_ticks_ms();
+ int status = 0;
+ while (((status = ringbuf_get_bytes(r, data, len)) == -1)
+ && (timeout_ms < 0 || (mp_uint_t)(mp_hal_ticks_ms() - start) < (mp_uint_t)timeout_ms)) {
+ MICROPY_EVENT_POLL_HOOK;
+ }
+ return status;
+}
+
+// ESPNow.recvinto(buffers[, timeout_ms]):
+// Waits for an espnow message and copies the peer_addr and message into
+// the buffers list.
+// Arguments:
+// buffers: (Optional) list of bytearrays to store return values.
+// timeout_ms: (Optional) timeout in milliseconds (or None).
+// Buffers should be a list: [bytearray(6), bytearray(250)]
+// If buffers is 4 elements long, the rssi and timestamp values will be
+// loaded into the 3rd and 4th elements.
+// Default timeout is set with ESPNow.config(timeout=milliseconds).
+// Return (None, None) on timeout.
+STATIC mp_obj_t espnow_recvinto(size_t n_args, const mp_obj_t *args) {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+
+ mp_int_t timeout_ms = ((n_args > 2 && args[2] != mp_const_none)
+ ? mp_obj_get_int(args[2]) : self->recv_timeout_ms);
+
+ mp_obj_list_t *list = MP_OBJ_TO_PTR(args[1]);
+ if (!mp_obj_is_type(list, &mp_type_list) || list->len < 2) {
+ mp_raise_ValueError(MP_ERROR_TEXT("ESPNow.recvinto(): Invalid argument"));
+ }
+ mp_obj_array_t *msg = MP_OBJ_TO_PTR(list->items[1]);
+ if (mp_obj_is_type(msg, &mp_type_bytearray)) {
+ msg->len += msg->free; // Make all the space in msg array available
+ msg->free = 0;
+ }
+ #if MICROPY_ESPNOW_RSSI
+ uint8_t peer_buf[ESP_NOW_ETH_ALEN];
+ #else
+ uint8_t *peer_buf = _get_bytes_len_w(list->items[0], ESP_NOW_ETH_ALEN);
+ #endif // MICROPY_ESPNOW_RSSI
+ uint8_t *msg_buf = _get_bytes_len_w(msg, ESP_NOW_MAX_DATA_LEN);
+
+ // Read the packet header from the incoming buffer
+ espnow_hdr_t hdr;
+ if (ringbuf_get_bytes_wait(self->recv_buffer, (uint8_t *)&hdr, sizeof(hdr), timeout_ms) < 0) {
+ return MP_OBJ_NEW_SMALL_INT(0); // Timeout waiting for packet
+ }
+ int msg_len = hdr.msg_len;
+
+ // Check the message packet header format and read the message data
+ if (hdr.magic != ESPNOW_MAGIC
+ || msg_len > ESP_NOW_MAX_DATA_LEN
+ || ringbuf_get_bytes(self->recv_buffer, peer_buf, ESP_NOW_ETH_ALEN) < 0
+ || ringbuf_get_bytes(self->recv_buffer, msg_buf, msg_len) < 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("ESPNow.recv(): buffer error"));
+ }
+ if (mp_obj_is_type(msg, &mp_type_bytearray)) {
+ // Set the length of the message bytearray.
+ size_t size = msg->len + msg->free;
+ msg->len = msg_len;
+ msg->free = size - msg_len;
+ }
+
+ #if MICROPY_ESPNOW_RSSI
+ // Update rssi value in the peer device table
+ mp_map_elem_t *entry = _update_rssi(peer_buf, hdr.rssi, hdr.time_ms);
+ list->items[0] = entry->key; // Set first element of list to peer
+ if (list->len >= 4) {
+ list->items[2] = MP_OBJ_NEW_SMALL_INT(hdr.rssi);
+ list->items[3] = mp_obj_new_int(hdr.time_ms);
+ }
+ #endif // MICROPY_ESPNOW_RSSI
+
+ return MP_OBJ_NEW_SMALL_INT(msg_len);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_recvinto_obj, 2, 3, espnow_recvinto);
+
+// Test if data is available to read from the buffers
+STATIC mp_obj_t espnow_any(const mp_obj_t _) {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+
+ return ringbuf_avail(self->recv_buffer) ? mp_const_true : mp_const_false;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_any_obj, espnow_any);
+
+// Used by espnow_send() for sends() with sync==True.
+// Wait till all pending sent packet responses have been received.
+// ie. self->tx_responses == self->tx_packets.
+static void _wait_for_pending_responses(esp_espnow_obj_t *self) {
+ mp_uint_t start = mp_hal_ticks_ms();
+ mp_uint_t t;
+ while (self->tx_responses < self->tx_packets) {
+ if ((t = mp_hal_ticks_ms() - start) > PENDING_RESPONSES_TIMEOUT_MS) {
+ mp_raise_OSError(MP_ETIMEDOUT);
+ }
+ if (t > PENDING_RESPONSES_BUSY_POLL_MS) {
+ // After 10ms of busy waiting give other tasks a look in.
+ MICROPY_EVENT_POLL_HOOK;
+ }
+ }
+}
+
+// ESPNow.send(peer_addr, message, [sync (=true), size])
+// ESPNow.send(message)
+// Send a message to the peer's mac address. Optionally wait for a response.
+// If peer_addr == None or any non-true value, send to all registered peers.
+// If sync == True, wait for response after sending.
+// If size is provided it should be the number of bytes in message to send().
+// Returns:
+// True if sync==False and message sent successfully.
+// True if sync==True and message is received successfully by all recipients
+// False if sync==True and message is not received by at least one recipient
+// Raises: EAGAIN if the internal espnow buffers are full.
+STATIC mp_obj_t espnow_send(size_t n_args, const mp_obj_t *args) {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+ // Check the various combinations of input arguments
+ const uint8_t *peer = (n_args > 2) ? _get_peer(args[1]) : NULL;
+ mp_obj_t msg = (n_args > 2) ? args[2] : (n_args == 2) ? args[1] : MP_OBJ_NULL;
+ bool sync = n_args <= 3 || args[3] == mp_const_none || mp_obj_is_true(args[3]);
+
+ // Get a pointer to the data buffer of the message
+ mp_buffer_info_t message;
+ mp_get_buffer_raise(msg, &message, MP_BUFFER_READ);
+
+ if (sync) {
+ // Flush out any pending responses.
+ // If the last call was sync==False there may be outstanding responses
+ // still to be received (possible many if we just had a burst of
+ // unsync send()s). We need to wait for all pending responses if this
+ // call has sync=True.
+ _wait_for_pending_responses(self);
+ }
+ int saved_failures = self->tx_failures;
+ // Send the packet - try, try again if internal esp-now buffers are full.
+ esp_err_t err;
+ mp_uint_t start = mp_hal_ticks_ms();
+ while ((ESP_ERR_ESPNOW_NO_MEM == (err = esp_now_send(peer, message.buf, message.len)))
+ && (mp_uint_t)(mp_hal_ticks_ms() - start) < (mp_uint_t)DEFAULT_SEND_TIMEOUT_MS) {
+ MICROPY_EVENT_POLL_HOOK;
+ }
+ check_esp_err(err); // Will raise OSError if e != ESP_OK
+ // Increment the sent packet count. If peer_addr==NULL msg will be
+ // sent to all peers EXCEPT any broadcast or multicast addresses.
+ self->tx_packets += ((peer == NULL) ? self->peer_count : 1);
+ if (sync) {
+ // Wait for and tally all the expected responses from peers
+ _wait_for_pending_responses(self);
+ }
+ // Return False if sync and any peers did not respond.
+ return mp_obj_new_bool(!(sync && self->tx_failures != saved_failures));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_send_obj, 2, 4, espnow_send);
+
+// ### The ESP_Now send and recv callback routines
+//
+
+// Callback triggered when a sent packet is acknowledged by the peer (or not).
+// Just count the number of responses and number of failures.
+// These are used in the send() logic.
+STATIC void send_cb(const uint8_t *mac_addr, esp_now_send_status_t status) {
+ esp_espnow_obj_t *self = _get_singleton();
+ self->tx_responses++;
+ if (status != ESP_NOW_SEND_SUCCESS) {
+ self->tx_failures++;
+ }
+}
+
+// Callback triggered when an ESP-Now packet is received.
+// Write the peer MAC address and the message into the recv_buffer as an
+// ESPNow packet.
+// If the buffer is full, drop the message and increment the dropped count.
+// Schedules the user callback if one has been registered (ESPNow.config()).
+STATIC void recv_cb(const esp_now_recv_info_t *recv_info, const uint8_t *msg, int msg_len) {
+ esp_espnow_obj_t *self = _get_singleton();
+ ringbuf_t *buf = self->recv_buffer;
+ // TODO: Test this works with ">".
+ if (sizeof(espnow_pkt_t) + msg_len >= ringbuf_free(buf)) {
+ self->dropped_rx_pkts++;
+ return;
+ }
+ espnow_hdr_t header;
+ header.magic = ESPNOW_MAGIC;
+ header.msg_len = msg_len;
+ #if MICROPY_ESPNOW_RSSI
+ header.rssi = recv_info->rx_ctrl->rssi;
+ header.time_ms = mp_hal_ticks_ms();
+ #endif // MICROPY_ESPNOW_RSSI
+
+ ringbuf_put_bytes(buf, (uint8_t *)&header, sizeof(header));
+ ringbuf_put_bytes(buf, recv_info->src_addr, ESP_NOW_ETH_ALEN);
+ ringbuf_put_bytes(buf, msg, msg_len);
+ self->rx_packets++;
+ if (self->recv_cb != mp_const_none) {
+ mp_sched_schedule(self->recv_cb, self->recv_cb_arg);
+ }
+}
+
+// ### Peer Management Functions
+//
+
+// Set the ESP-NOW Primary Master Key (pmk) (for encrypted communications).
+// Raise OSError if ESP-NOW functions are not initialised.
+// Raise ValueError if key is not a bytes-like object exactly 16 bytes long.
+STATIC mp_obj_t espnow_set_pmk(mp_obj_t _, mp_obj_t key) {
+ check_esp_err(esp_now_set_pmk(_get_bytes_len(key, ESP_NOW_KEY_LEN)));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_set_pmk_obj, espnow_set_pmk);
+
+// Common code for add_peer() and mod_peer() to process the args and kw_args:
+// Raise ValueError if the LMK is not a bytes-like object of exactly 16 bytes.
+// Raise TypeError if invalid keyword args or too many positional args.
+// Return true if all args parsed correctly.
+STATIC bool _update_peer_info(
+ esp_now_peer_info_t *peer, size_t n_args,
+ const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ enum { ARG_lmk, ARG_channel, ARG_ifidx, ARG_encrypt };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_lmk, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_channel, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_ifidx, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_encrypt, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ if (args[ARG_lmk].u_obj != mp_const_none) {
+ mp_obj_t obj = args[ARG_lmk].u_obj;
+ peer->encrypt = mp_obj_is_true(obj);
+ if (peer->encrypt) {
+ // Key must be 16 bytes in length.
+ memcpy(peer->lmk, _get_bytes_len(obj, ESP_NOW_KEY_LEN), ESP_NOW_KEY_LEN);
+ }
+ }
+ if (args[ARG_channel].u_obj != mp_const_none) {
+ peer->channel = mp_obj_get_int(args[ARG_channel].u_obj);
+ }
+ if (args[ARG_ifidx].u_obj != mp_const_none) {
+ peer->ifidx = mp_obj_get_int(args[ARG_ifidx].u_obj);
+ }
+ if (args[ARG_encrypt].u_obj != mp_const_none) {
+ peer->encrypt = mp_obj_is_true(args[ARG_encrypt].u_obj);
+ }
+ return true;
+}
+
+// Update the cached peer count in self->peer_count;
+// The peer_count ignores broadcast and multicast addresses and is used for the
+// send() logic and is updated from add_peer(), mod_peer() and del_peer().
+STATIC void _update_peer_count() {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+
+ esp_now_peer_info_t peer = {0};
+ bool from_head = true;
+ int count = 0;
+ // esp_now_fetch_peer() skips over any broadcast or multicast addresses
+ while (esp_now_fetch_peer(from_head, &peer) == ESP_OK) {
+ from_head = false;
+ if (++count >= ESP_NOW_MAX_TOTAL_PEER_NUM) {
+ break; // Should not happen
+ }
+ }
+ self->peer_count = count;
+}
+
+// ESPNow.add_peer(peer_mac, [lmk, [channel, [ifidx, [encrypt]]]]) or
+// ESPNow.add_peer(peer_mac, [lmk=b'0123456789abcdef'|b''|None|False],
+// [channel=1..11|0], [ifidx=0|1], [encrypt=True|False])
+// Positional args set to None will be left at defaults.
+// Raise OSError if ESPNow.init() has not been called.
+// Raise ValueError if mac or LMK are not bytes-like objects or wrong length.
+// Raise TypeError if invalid keyword args or too many positional args.
+// Return None.
+STATIC mp_obj_t espnow_add_peer(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ esp_now_peer_info_t peer = {0};
+ memcpy(peer.peer_addr, _get_peer(args[1]), ESP_NOW_ETH_ALEN);
+ _update_peer_info(&peer, n_args - 2, args + 2, kw_args);
+
+ check_esp_err(esp_now_add_peer(&peer));
+ _update_peer_count();
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espnow_add_peer_obj, 2, espnow_add_peer);
+
+// ESPNow.del_peer(peer_mac): Unregister peer_mac.
+// Raise OSError if ESPNow.init() has not been called.
+// Raise ValueError if peer is not a bytes-like objects or wrong length.
+// Return None.
+STATIC mp_obj_t espnow_del_peer(mp_obj_t _, mp_obj_t peer) {
+ uint8_t peer_addr[ESP_NOW_ETH_ALEN];
+ memcpy(peer_addr, _get_peer(peer), ESP_NOW_ETH_ALEN);
+
+ check_esp_err(esp_now_del_peer(peer_addr));
+ _update_peer_count();
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_del_peer_obj, espnow_del_peer);
+
+// Convert a peer_info struct to python tuple
+// Used by espnow_get_peer() and espnow_get_peers()
+static mp_obj_t _peer_info_to_tuple(const esp_now_peer_info_t *peer) {
+ return NEW_TUPLE(
+ mp_obj_new_bytes(peer->peer_addr, MP_ARRAY_SIZE(peer->peer_addr)),
+ mp_obj_new_bytes(peer->lmk, MP_ARRAY_SIZE(peer->lmk)),
+ mp_obj_new_int(peer->channel),
+ mp_obj_new_int(peer->ifidx),
+ (peer->encrypt) ? mp_const_true : mp_const_false);
+}
+
+// ESPNow.get_peers(): Fetch peer_info records for all registered ESPNow peers.
+// Raise OSError if ESPNow.init() has not been called.
+// Return a tuple of tuples:
+// ((peer_addr, lmk, channel, ifidx, encrypt),
+// (peer_addr, lmk, channel, ifidx, encrypt), ...)
+STATIC mp_obj_t espnow_get_peers(mp_obj_t _) {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+
+ // Build and initialise the peer info tuple.
+ mp_obj_tuple_t *peerinfo_tuple = mp_obj_new_tuple(self->peer_count, NULL);
+ esp_now_peer_info_t peer = {0};
+ for (int i = 0; i < peerinfo_tuple->len; i++) {
+ int status = esp_now_fetch_peer((i == 0), &peer);
+ peerinfo_tuple->items[i] =
+ (status == ESP_OK ? _peer_info_to_tuple(&peer) : mp_const_none);
+ }
+
+ return peerinfo_tuple;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_get_peers_obj, espnow_get_peers);
+
+#if MICROPY_ESPNOW_EXTRA_PEER_METHODS
+// ESPNow.get_peer(peer_mac): Get the peer info for peer_mac as a tuple.
+// Raise OSError if ESPNow.init() has not been called.
+// Raise ValueError if mac or LMK are not bytes-like objects or wrong length.
+// Return a tuple of (peer_addr, lmk, channel, ifidx, encrypt).
+STATIC mp_obj_t espnow_get_peer(mp_obj_t _, mp_obj_t arg1) {
+ esp_now_peer_info_t peer = {0};
+ memcpy(peer.peer_addr, _get_peer(arg1), ESP_NOW_ETH_ALEN);
+
+ check_esp_err(esp_now_get_peer(peer.peer_addr, &peer));
+
+ return _peer_info_to_tuple(&peer);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_get_peer_obj, espnow_get_peer);
+
+// ESPNow.mod_peer(peer_mac, [lmk, [channel, [ifidx, [encrypt]]]]) or
+// ESPNow.mod_peer(peer_mac, [lmk=b'0123456789abcdef'|b''|None|False],
+// [channel=1..11|0], [ifidx=0|1], [encrypt=True|False])
+// Positional args set to None will be left at current values.
+// Raise OSError if ESPNow.init() has not been called.
+// Raise ValueError if mac or LMK are not bytes-like objects or wrong length.
+// Raise TypeError if invalid keyword args or too many positional args.
+// Return None.
+STATIC mp_obj_t espnow_mod_peer(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ esp_now_peer_info_t peer = {0};
+ memcpy(peer.peer_addr, _get_peer(args[1]), ESP_NOW_ETH_ALEN);
+ check_esp_err(esp_now_get_peer(peer.peer_addr, &peer));
+
+ _update_peer_info(&peer, n_args - 2, args + 2, kw_args);
+
+ check_esp_err(esp_now_mod_peer(&peer));
+ _update_peer_count();
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espnow_mod_peer_obj, 2, espnow_mod_peer);
+
+// ESPNow.espnow_peer_count(): Get the number of registered peers.
+// Raise OSError if ESPNow.init() has not been called.
+// Return a tuple of (num_total_peers, num_encrypted_peers).
+STATIC mp_obj_t espnow_peer_count(mp_obj_t _) {
+ esp_now_peer_num_t peer_num = {0};
+ check_esp_err(esp_now_get_peer_num(&peer_num));
+
+ return NEW_TUPLE(
+ mp_obj_new_int(peer_num.total_num),
+ mp_obj_new_int(peer_num.encrypt_num));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(espnow_peer_count_obj, espnow_peer_count);
+#endif
+
+STATIC const mp_rom_map_elem_t esp_espnow_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&espnow_active_obj) },
+ { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&espnow_config_obj) },
+ { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&espnow_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stats), MP_ROM_PTR(&espnow_stats_obj) },
+
+ // Send and receive messages
+ { MP_ROM_QSTR(MP_QSTR_recvinto), MP_ROM_PTR(&espnow_recvinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&espnow_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&espnow_any_obj) },
+
+ // Peer management functions
+ { MP_ROM_QSTR(MP_QSTR_set_pmk), MP_ROM_PTR(&espnow_set_pmk_obj) },
+ { MP_ROM_QSTR(MP_QSTR_add_peer), MP_ROM_PTR(&espnow_add_peer_obj) },
+ { MP_ROM_QSTR(MP_QSTR_del_peer), MP_ROM_PTR(&espnow_del_peer_obj) },
+ { MP_ROM_QSTR(MP_QSTR_get_peers), MP_ROM_PTR(&espnow_get_peers_obj) },
+ #if MICROPY_ESPNOW_EXTRA_PEER_METHODS
+ { MP_ROM_QSTR(MP_QSTR_mod_peer), MP_ROM_PTR(&espnow_mod_peer_obj) },
+ { MP_ROM_QSTR(MP_QSTR_get_peer), MP_ROM_PTR(&espnow_get_peer_obj) },
+ { MP_ROM_QSTR(MP_QSTR_peer_count), MP_ROM_PTR(&espnow_peer_count_obj) },
+ #endif // MICROPY_ESPNOW_EXTRA_PEER_METHODS
+};
+STATIC MP_DEFINE_CONST_DICT(esp_espnow_locals_dict, esp_espnow_locals_dict_table);
+
+STATIC const mp_rom_map_elem_t espnow_globals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__espnow) },
+ { MP_ROM_QSTR(MP_QSTR_ESPNowBase), MP_ROM_PTR(&esp_espnow_type) },
+ { MP_ROM_QSTR(MP_QSTR_MAX_DATA_LEN), MP_ROM_INT(ESP_NOW_MAX_DATA_LEN)},
+ { MP_ROM_QSTR(MP_QSTR_ADDR_LEN), MP_ROM_INT(ESP_NOW_ETH_ALEN)},
+ { MP_ROM_QSTR(MP_QSTR_KEY_LEN), MP_ROM_INT(ESP_NOW_KEY_LEN)},
+ { MP_ROM_QSTR(MP_QSTR_MAX_TOTAL_PEER_NUM), MP_ROM_INT(ESP_NOW_MAX_TOTAL_PEER_NUM)},
+ { MP_ROM_QSTR(MP_QSTR_MAX_ENCRYPT_PEER_NUM), MP_ROM_INT(ESP_NOW_MAX_ENCRYPT_PEER_NUM)},
+};
+STATIC MP_DEFINE_CONST_DICT(espnow_globals_dict, espnow_globals_dict_table);
+
+// ### Dummy Buffer Protocol support
+// ...so asyncio can poll.ipoll() on this device
+
+// Support ioctl(MP_STREAM_POLL, ) for asyncio
+STATIC mp_uint_t espnow_stream_ioctl(
+ mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+ if (request != MP_STREAM_POLL) {
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+ esp_espnow_obj_t *self = _get_singleton();
+ return (self->recv_buffer == NULL) ? 0 : // If not initialised
+ arg ^ (
+ // If no data in the buffer, unset the Read ready flag
+ ((ringbuf_avail(self->recv_buffer) == 0) ? MP_STREAM_POLL_RD : 0) |
+ // If still waiting for responses, unset the Write ready flag
+ ((self->tx_responses < self->tx_packets) ? MP_STREAM_POLL_WR : 0));
+}
+
+STATIC const mp_stream_p_t espnow_stream_p = {
+ .ioctl = espnow_stream_ioctl,
+};
+
+#if MICROPY_ESPNOW_RSSI
+// Return reference to the dictionary of peers we have seen:
+// {peer1: (rssi, time_sec), peer2: (rssi, time_msec), ...}
+// where:
+// peerX is a byte string containing the 6-byte mac address of the peer,
+// rssi is the wifi signal strength from the last msg received
+// (in dBm from -127 to 0)
+// time_sec is the time in milliseconds since device last booted.
+STATIC void espnow_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+ esp_espnow_obj_t *self = _get_singleton();
+ if (dest[0] != MP_OBJ_NULL) { // Only allow "Load" operation
+ return;
+ }
+ if (attr == MP_QSTR_peers_table) {
+ dest[0] = self->peers_table;
+ return;
+ }
+ dest[1] = MP_OBJ_SENTINEL; // Attribute not found
+}
+#endif // MICROPY_ESPNOW_RSSI
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_espnow_type,
+ MP_QSTR_ESPNowBase,
+ MP_TYPE_FLAG_NONE,
+ make_new, espnow_make_new,
+ #if MICROPY_ESPNOW_RSSI
+ attr, espnow_attr,
+ #endif // MICROPY_ESPNOW_RSSI
+ protocol, &espnow_stream_p,
+ locals_dict, &esp_espnow_locals_dict
+ );
+
+const mp_obj_module_t mp_module_espnow = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&espnow_globals_dict,
+};
+
+MP_REGISTER_MODULE(MP_QSTR__espnow, mp_module_espnow);
+MP_REGISTER_ROOT_POINTER(struct _esp_espnow_obj_t *espnow_singleton);
diff --git a/ports/esp32/modespnow.h b/ports/esp32/modespnow.h
new file mode 100644
index 0000000000000..3c6280b1ced48
--- /dev/null
+++ b/ports/esp32/modespnow.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Glenn Moloney @glenn20
+ *
+ * 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/obj.h"
+
+// Called from main.c:mp_task() to reset the espnow software stack
+mp_obj_t espnow_deinit(mp_obj_t _);
diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c
index db77becf87693..31fa589aed0a2 100644
--- a/ports/esp32/modmachine.c
+++ b/ports/esp32/modmachine.c
@@ -32,23 +32,14 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
+#include "esp_mac.h"
#include "esp_sleep.h"
#include "esp_pm.h"
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/rom/rtc.h"
-#include "esp32/clk.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/rom/rtc.h"
-#include "esp32s2/clk.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/rom/rtc.h"
-#include "esp32s3/clk.h"
-#endif
-
#include "py/obj.h"
#include "py/runtime.h"
#include "shared/runtime/pyexec.h"
+#include "drivers/dht/dht.h"
#include "extmod/machine_bitstream.h"
#include "extmod/machine_mem.h"
#include "extmod/machine_signal.h"
@@ -78,12 +69,20 @@ int esp_clk_cpu_freq(void);
STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
- return mp_obj_new_int(esp_clk_cpu_freq());
+ return mp_obj_new_int(esp_rom_get_cpu_ticks_per_us() * 1000000);
} else {
// set
mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
- if (freq != 20 && freq != 40 && freq != 80 && freq != 160 && freq != 240) {
+ if (freq != 20 && freq != 40 && freq != 80 && freq != 160
+ #if !CONFIG_IDF_TARGET_ESP32C3
+ && freq != 240
+ #endif
+ ) {
+ #if CONFIG_IDF_TARGET_ESP32C3
+ mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz or 160MHz"));
+ #else
mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz"));
+ #endif
}
#if CONFIG_IDF_TARGET_ESP32
esp_pm_config_esp32_t pm;
@@ -101,7 +100,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
if (ret != ESP_OK) {
mp_raise_ValueError(NULL);
}
- while (esp_clk_cpu_freq() != freq * 1000000) {
+ while (esp_rom_get_cpu_ticks_per_us() != freq) {
vTaskDelay(1);
}
return mp_const_none;
@@ -208,6 +207,13 @@ STATIC mp_obj_t machine_reset_cause(size_t n_args, const mp_obj_t *pos_args, mp_
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_reset_cause_obj, 0, machine_reset_cause);
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
+ MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
+ for (;;) {
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
+
void machine_init(void) {
is_soft_reset = 0;
}
@@ -263,7 +269,7 @@ STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
@@ -277,6 +283,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
@@ -287,6 +294,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_PULSE
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
#endif
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
@@ -299,7 +307,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
- #if CONFIG_IDF_TARGET_ESP32
+ #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
{ MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
@@ -307,14 +315,14 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_DAC
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
#endif
- { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#if MICROPY_PY_MACHINE_I2S
{ MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
- { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
@@ -343,6 +351,6 @@ const mp_obj_module_t mp_module_machine = {
.globals = (mp_obj_dict_t *)&machine_module_globals,
};
-MP_REGISTER_MODULE(MP_QSTR_umachine, mp_module_machine);
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_machine, mp_module_machine);
#endif // MICROPY_PY_MACHINE
diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h
index 4d2ab9020d16f..24417f6107467 100644
--- a/ports/esp32/modmachine.h
+++ b/ports/esp32/modmachine.h
@@ -16,8 +16,8 @@ extern const mp_obj_type_t machine_touchpad_type;
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_adcblock_type;
extern const mp_obj_type_t machine_dac_type;
-extern const mp_obj_type_t machine_hw_i2c_type;
-extern const mp_obj_type_t machine_hw_spi_type;
+extern const mp_obj_type_t machine_i2c_type;
+extern const mp_obj_type_t machine_spi_type;
extern const mp_obj_type_t machine_i2s_type;
extern const mp_obj_type_t machine_uart_type;
extern const mp_obj_type_t machine_rtc_type;
@@ -31,5 +31,6 @@ void machine_pwm_deinit_all(void);
// TODO: void machine_rmt_deinit_all(void);
void machine_timer_deinit_all(void);
void machine_i2s_init0();
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
#endif // MICROPY_INCLUDED_ESP32_MODMACHINE_H
diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c
deleted file mode 100644
index 45231c42307c8..0000000000000
--- a/ports/esp32/modnetwork.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * Development of the code in this file was sponsored by Microbric Pty Ltd
- * and Mnemote Pty Ltd
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016, 2017 Nick Moore @mnemote
- * Copyright (c) 2017 "Eric Poulsen"
- *
- * Based on esp8266/modnetwork.c which is Copyright (c) 2015 Paul Sokolovsky
- * And the ESP IDF example code which is Public Domain / CC0
- *
- * 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 "py/runtime.h"
-#include "py/mperrno.h"
-#include "shared/netutils/netutils.h"
-#include "modnetwork.h"
-
-#include "esp_wifi.h"
-#include "esp_log.h"
-#include "lwip/dns.h"
-
-#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 1, 0)
-#define DNS_MAIN TCPIP_ADAPTER_DNS_MAIN
-#else
-#define DNS_MAIN ESP_NETIF_DNS_MAIN
-#endif
-
-#define MODNETWORK_INCLUDE_CONSTANTS (1)
-
-NORETURN void esp_exceptions_helper(esp_err_t e) {
- switch (e) {
- case ESP_ERR_WIFI_NOT_INIT:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Initialized"));
- case ESP_ERR_WIFI_NOT_STARTED:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Started"));
- case ESP_ERR_WIFI_NOT_STOPPED:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Stopped"));
- case ESP_ERR_WIFI_IF:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Interface"));
- case ESP_ERR_WIFI_MODE:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Mode"));
- case ESP_ERR_WIFI_STATE:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Internal State Error"));
- case ESP_ERR_WIFI_CONN:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Internal Error"));
- case ESP_ERR_WIFI_NVS:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Internal NVS Error"));
- case ESP_ERR_WIFI_MAC:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid MAC Address"));
- case ESP_ERR_WIFI_SSID:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi SSID Invalid"));
- case ESP_ERR_WIFI_PASSWORD:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Password"));
- case ESP_ERR_WIFI_TIMEOUT:
- mp_raise_OSError(MP_ETIMEDOUT);
- case ESP_ERR_WIFI_WAKE_FAIL:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Wakeup Failure"));
- case ESP_ERR_WIFI_WOULD_BLOCK:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Would Block"));
- case ESP_ERR_WIFI_NOT_CONNECT:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Connected"));
- case ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("TCP/IP Invalid Parameters"));
- case ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("TCP/IP IF Not Ready"));
- case ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED:
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("TCP/IP DHCP Client Start Failed"));
- case ESP_ERR_TCPIP_ADAPTER_NO_MEM:
- mp_raise_OSError(MP_ENOMEM);
- default:
- mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Wifi Unknown Error 0x%04x"), e);
- }
-}
-
-// This function is called by the system-event task and so runs in a different
-// thread to the main MicroPython task. It must not raise any Python exceptions.
-static esp_err_t event_handler(void *ctx, system_event_t *event) {
- switch (event->event_id) {
- #if MICROPY_PY_NETWORK_WLAN
- case SYSTEM_EVENT_STA_START:
- case SYSTEM_EVENT_STA_CONNECTED:
- case SYSTEM_EVENT_STA_GOT_IP:
- case SYSTEM_EVENT_STA_DISCONNECTED:
- network_wlan_event_handler(event);
- break;
- #endif
- case SYSTEM_EVENT_GOT_IP6:
- ESP_LOGI("network", "Got IPv6");
- break;
- case SYSTEM_EVENT_ETH_START:
- ESP_LOGI("ethernet", "start");
- break;
- case SYSTEM_EVENT_ETH_STOP:
- ESP_LOGI("ethernet", "stop");
- break;
- case SYSTEM_EVENT_ETH_CONNECTED:
- ESP_LOGI("ethernet", "LAN cable connected");
- break;
- case SYSTEM_EVENT_ETH_DISCONNECTED:
- ESP_LOGI("ethernet", "LAN cable disconnected");
- break;
- case SYSTEM_EVENT_ETH_GOT_IP:
- ESP_LOGI("ethernet", "Got IP");
- break;
- default:
- ESP_LOGI("network", "event %d", event->event_id);
- break;
- }
- return ESP_OK;
-}
-
-STATIC mp_obj_t esp_initialize() {
- static int initialized = 0;
- if (!initialized) {
- ESP_LOGD("modnetwork", "Initializing TCP/IP");
- tcpip_adapter_init();
- ESP_LOGD("modnetwork", "Initializing Event Loop");
- esp_exceptions(esp_event_loop_init(event_handler, NULL));
- ESP_LOGD("modnetwork", "esp_event_loop_init done");
- initialized = 1;
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_initialize_obj, esp_initialize);
-
-STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
- wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- tcpip_adapter_ip_info_t info;
- tcpip_adapter_dns_info_t dns_info;
- tcpip_adapter_get_ip_info(self->if_id, &info);
- tcpip_adapter_get_dns_info(self->if_id, DNS_MAIN, &dns_info);
- if (n_args == 1) {
- // get
- mp_obj_t tuple[4] = {
- netutils_format_ipv4_addr((uint8_t *)&info.ip, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&info.netmask, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&info.gw, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&dns_info.ip, NETUTILS_BIG),
- };
- return mp_obj_new_tuple(4, tuple);
- } else {
- // set
- if (mp_obj_is_type(args[1], &mp_type_tuple) || mp_obj_is_type(args[1], &mp_type_list)) {
- mp_obj_t *items;
- mp_obj_get_array_fixed_n(args[1], 4, &items);
- netutils_parse_ipv4_addr(items[0], (void *)&info.ip, NETUTILS_BIG);
- if (mp_obj_is_integer(items[1])) {
- // allow numeric netmask, i.e.:
- // 24 -> 255.255.255.0
- // 16 -> 255.255.0.0
- // etc...
- uint32_t *m = (uint32_t *)&info.netmask;
- *m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1])));
- } else {
- netutils_parse_ipv4_addr(items[1], (void *)&info.netmask, NETUTILS_BIG);
- }
- netutils_parse_ipv4_addr(items[2], (void *)&info.gw, NETUTILS_BIG);
- netutils_parse_ipv4_addr(items[3], (void *)&dns_info.ip, NETUTILS_BIG);
- // To set a static IP we have to disable DHCP first
- if (self->if_id == WIFI_IF_STA || self->if_id == ESP_IF_ETH) {
- esp_err_t e = tcpip_adapter_dhcpc_stop(self->if_id);
- if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) {
- esp_exceptions_helper(e);
- }
- esp_exceptions(tcpip_adapter_set_ip_info(self->if_id, &info));
- esp_exceptions(tcpip_adapter_set_dns_info(self->if_id, DNS_MAIN, &dns_info));
- } else if (self->if_id == WIFI_IF_AP) {
- esp_err_t e = tcpip_adapter_dhcps_stop(WIFI_IF_AP);
- if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) {
- esp_exceptions_helper(e);
- }
- esp_exceptions(tcpip_adapter_set_ip_info(WIFI_IF_AP, &info));
- esp_exceptions(tcpip_adapter_set_dns_info(WIFI_IF_AP, DNS_MAIN, &dns_info));
- esp_exceptions(tcpip_adapter_dhcps_start(WIFI_IF_AP));
- }
- } else {
- // check for the correct string
- const char *mode = mp_obj_str_get_str(args[1]);
- if ((self->if_id != WIFI_IF_STA && self->if_id != ESP_IF_ETH) || strcmp("dhcp", mode)) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
- }
- esp_exceptions(tcpip_adapter_dhcpc_start(self->if_id));
- }
- return mp_const_none;
- }
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
-
-STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode);
-
-#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
-#define TEST_WIFI_AUTH_MAX 9
-#else
-#define TEST_WIFI_AUTH_MAX 8
-#endif
-_Static_assert(WIFI_AUTH_MAX == TEST_WIFI_AUTH_MAX, "Synchronize WIFI_AUTH_XXX constants with the ESP-IDF. Look at esp-idf/components/esp_wifi/include/esp_wifi_types.h");
-
-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___init__), MP_ROM_PTR(&esp_initialize_obj) },
-
- #if MICROPY_PY_NETWORK_WLAN
- { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) },
- #endif
-
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32)
- { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) },
- #endif
- { MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&ppp_make_new_obj) },
- { MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) },
-
- #if MODNETWORK_INCLUDE_CONSTANTS
-
- #if MICROPY_PY_NETWORK_WLAN
- { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(WIFI_IF_STA)},
- { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(WIFI_IF_AP)},
-
- { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) },
-
- { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(WIFI_AUTH_WPA_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA_WPA2_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_ENTERPRISE), MP_ROM_INT(WIFI_AUTH_WPA2_ENTERPRISE) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA3_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_WPA3_PSK) },
- #if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 3, 0)
- { MP_ROM_QSTR(MP_QSTR_AUTH_WAPI_PSK), MP_ROM_INT(WIFI_AUTH_WAPI_PSK) },
- #endif
- { MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) },
- #endif
-
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32)
- { MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) },
- { MP_ROM_QSTR(MP_QSTR_PHY_IP101), MP_ROM_INT(PHY_IP101) },
- { MP_ROM_QSTR(MP_QSTR_PHY_RTL8201), MP_ROM_INT(PHY_RTL8201) },
- { MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(PHY_DP83848) },
- #if ESP_IDF_VERSION_MINOR >= 3
- // PHY_KSZ8041 is new in ESP-IDF v4.3
- { MP_ROM_QSTR(MP_QSTR_PHY_KSZ8041), MP_ROM_INT(PHY_KSZ8041) },
- #endif
-
- { MP_ROM_QSTR(MP_QSTR_ETH_INITIALIZED), MP_ROM_INT(ETH_INITIALIZED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_STARTED), MP_ROM_INT(ETH_STARTED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_STOPPED), MP_ROM_INT(ETH_STOPPED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_CONNECTED), MP_ROM_INT(ETH_CONNECTED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_DISCONNECTED), MP_ROM_INT(ETH_DISCONNECTED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_GOT_IP), MP_ROM_INT(ETH_GOT_IP)},
- #endif
-
- { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STAT_IDLE)},
- { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STAT_CONNECTING)},
- { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STAT_GOT_IP)},
- // Errors from the ESP-IDF
- { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND)},
- { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(WIFI_REASON_AUTH_FAIL)},
- { MP_ROM_QSTR(MP_QSTR_STAT_BEACON_TIMEOUT), MP_ROM_INT(WIFI_REASON_BEACON_TIMEOUT)},
- { MP_ROM_QSTR(MP_QSTR_STAT_ASSOC_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)},
- { MP_ROM_QSTR(MP_QSTR_STAT_HANDSHAKE_TIMEOUT), MP_ROM_INT(WIFI_REASON_HANDSHAKE_TIMEOUT)},
- #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,
-};
-
-// Note: This port doesn't define MICROPY_PY_NETWORK so this will not conflict
-// with the common implementation provided by extmod/modnetwork.c.
-MP_REGISTER_MODULE(MP_QSTR_network, mp_module_network);
diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h
index 7bcfa0e6fcdb4..79bf9973ca95b 100644
--- a/ports/esp32/modnetwork.h
+++ b/ports/esp32/modnetwork.h
@@ -26,9 +26,10 @@
#ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H
#define MICROPY_INCLUDED_ESP32_MODNETWORK_H
-#include "esp_event.h"
+#include "esp_netif.h"
-enum { PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041 };
+enum { PHY_LAN8710, PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041, PHY_KSZ8081, PHY_KSZ8851SNL = 100, PHY_DM9051, PHY_W5500 };
+#define IS_SPI_PHY(NUM) (NUM >= 100)
enum { ETH_INITIALIZED, ETH_STARTED, ETH_STOPPED, ETH_CONNECTED, ETH_DISCONNECTED, ETH_GOT_IP };
// Cases similar to ESP8266 user_interface.h
@@ -39,16 +40,22 @@ enum {
STAT_GOT_IP = 1010,
};
-typedef struct _wlan_if_obj_t {
+typedef struct _base_if_obj_t {
mp_obj_base_t base;
- int if_id;
-} wlan_if_obj_t;
+ esp_interface_t if_id;
+ esp_netif_t *netif;
+ volatile bool active;
+} base_if_obj_t;
-MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj);
-MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj);
-MP_DECLARE_CONST_FUN_OBJ_1(ppp_make_new_obj);
-MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj);
-MP_DECLARE_CONST_FUN_OBJ_KW(esp_config_obj);
+extern const mp_obj_type_t esp_network_wlan_type;
+
+MP_DECLARE_CONST_FUN_OBJ_0(esp_network_initialize_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_get_wlan_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(esp_network_get_lan_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(esp_network_ppp_make_new_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_ifconfig_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(esp_network_config_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj);
NORETURN void esp_exceptions_helper(esp_err_t e);
@@ -58,7 +65,7 @@ static inline void esp_exceptions(esp_err_t e) {
}
}
-void usocket_events_deinit(void);
-void network_wlan_event_handler(system_event_t *event);
+void socket_events_deinit(void);
+void esp_initialise_wifi(void);
#endif
diff --git a/ports/esp32/modnetwork_globals.h b/ports/esp32/modnetwork_globals.h
new file mode 100644
index 0000000000000..7326d453be5aa
--- /dev/null
+++ b/ports/esp32/modnetwork_globals.h
@@ -0,0 +1,70 @@
+{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_network_initialize_obj) },
+
+#if MICROPY_PY_NETWORK_WLAN
+{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&esp_network_wlan_type) },
+#endif
+
+#if MICROPY_PY_NETWORK_LAN
+{ MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&esp_network_get_lan_obj) },
+#endif
+{ MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&esp_network_ppp_make_new_obj) },
+{ MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_network_phy_mode_obj) },
+
+#if MICROPY_PY_NETWORK_WLAN
+{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(WIFI_IF_STA)},
+{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(WIFI_IF_AP)},
+
+{ MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_LR), MP_ROM_INT(WIFI_PROTOCOL_LR) },
+
+{ MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(WIFI_AUTH_WPA_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA_WPA2_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_ENTERPRISE), MP_ROM_INT(WIFI_AUTH_WPA2_ENTERPRISE) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA3_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_WPA3_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WAPI_PSK), MP_ROM_INT(WIFI_AUTH_WAPI_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_OWE), MP_ROM_INT(WIFI_AUTH_OWE) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) },
+#endif
+
+#if MICROPY_PY_NETWORK_LAN
+{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8710), MP_ROM_INT(PHY_LAN8710) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_IP101), MP_ROM_INT(PHY_IP101) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_RTL8201), MP_ROM_INT(PHY_RTL8201) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(PHY_DP83848) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_KSZ8041), MP_ROM_INT(PHY_KSZ8041) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_KSZ8081), MP_ROM_INT(PHY_KSZ8081) },
+
+#if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
+{ MP_ROM_QSTR(MP_QSTR_PHY_KSZ8851SNL), MP_ROM_INT(PHY_KSZ8851SNL) },
+#endif
+#if CONFIG_ETH_SPI_ETHERNET_DM9051
+{ MP_ROM_QSTR(MP_QSTR_PHY_DM9051), MP_ROM_INT(PHY_DM9051) },
+#endif
+#if CONFIG_ETH_SPI_ETHERNET_W5500
+{ MP_ROM_QSTR(MP_QSTR_PHY_W5500), MP_ROM_INT(PHY_W5500) },
+#endif
+
+{ MP_ROM_QSTR(MP_QSTR_ETH_INITIALIZED), MP_ROM_INT(ETH_INITIALIZED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_STARTED), MP_ROM_INT(ETH_STARTED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_STOPPED), MP_ROM_INT(ETH_STOPPED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_CONNECTED), MP_ROM_INT(ETH_CONNECTED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_DISCONNECTED), MP_ROM_INT(ETH_DISCONNECTED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_GOT_IP), MP_ROM_INT(ETH_GOT_IP)},
+#endif
+
+{ MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STAT_IDLE)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STAT_CONNECTING)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STAT_GOT_IP)},
+// Errors from the ESP-IDF
+{ MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(WIFI_REASON_AUTH_FAIL)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_BEACON_TIMEOUT), MP_ROM_INT(WIFI_REASON_BEACON_TIMEOUT)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_ASSOC_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_HANDSHAKE_TIMEOUT), MP_ROM_INT(WIFI_REASON_HANDSHAKE_TIMEOUT)},
diff --git a/ports/esp32/modos.c b/ports/esp32/modos.c
new file mode 100644
index 0000000000000..287f1d9900211
--- /dev/null
+++ b/ports/esp32/modos.c
@@ -0,0 +1,65 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * Development of the code in this file was sponsored by Microbric Pty Ltd
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Josef Gajdusek
+ * Copyright (c) 2016 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 "esp_system.h"
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "extmod/misc.h"
+
+STATIC mp_obj_t mp_os_urandom(mp_obj_t num) {
+ mp_int_t n = mp_obj_get_int(num);
+ vstr_t vstr;
+ vstr_init_len(&vstr, n);
+ uint32_t r = 0;
+ for (int i = 0; i < n; i++) {
+ if ((i & 3) == 0) {
+ r = esp_random(); // returns 32-bit hardware random number
+ }
+ vstr.buf[i] = r;
+ r >>= 8;
+ }
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_urandom_obj, mp_os_urandom);
+
+#if MICROPY_PY_OS_DUPTERM_NOTIFY
+STATIC mp_obj_t mp_os_dupterm_notify(mp_obj_t obj_in) {
+ (void)obj_in;
+ for (;;) {
+ int c = mp_os_dupterm_rx_chr();
+ if (c < 0) {
+ break;
+ }
+ ringbuf_put(&stdin_ringbuf, c);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_dupterm_notify_obj, mp_os_dupterm_notify);
+#endif
diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c
index 819ea26e98006..ba1fe096f6946 100644
--- a/ports/esp32/modsocket.c
+++ b/ports/esp32/modsocket.c
@@ -46,7 +46,6 @@
#include "py/stream.h"
#include "py/mperrno.h"
#include "shared/netutils/netutils.h"
-#include "mdns.h"
#include "modnetwork.h"
#include "lwip/sockets.h"
@@ -59,6 +58,10 @@
#define MDNS_QUERY_TIMEOUT_MS (5000)
#define MDNS_LOCAL_SUFFIX ".local"
+#ifndef NO_QSTR
+#include "mdns.h"
+#endif
+
enum {
SOCKET_STATE_NEW,
SOCKET_STATE_CONNECTED,
@@ -73,7 +76,7 @@ typedef struct _socket_obj_t {
uint8_t proto;
uint8_t state;
unsigned int retries;
- #if MICROPY_PY_USOCKET_EVENTS
+ #if MICROPY_PY_SOCKET_EVENTS
mp_obj_t events_callback;
struct _socket_obj_t *events_next;
#endif
@@ -81,28 +84,28 @@ typedef struct _socket_obj_t {
void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms);
-#if MICROPY_PY_USOCKET_EVENTS
+#if MICROPY_PY_SOCKET_EVENTS
// Support for callbacks on asynchronous socket events (when socket becomes readable)
// This divisor is used to reduce the load on the system, so it doesn't poll sockets too often
#define USOCKET_EVENTS_DIVISOR (8)
-STATIC uint8_t usocket_events_divisor;
-STATIC socket_obj_t *usocket_events_head;
+STATIC uint8_t socket_events_divisor;
+STATIC socket_obj_t *socket_events_head;
-void usocket_events_deinit(void) {
- usocket_events_head = NULL;
+void socket_events_deinit(void) {
+ socket_events_head = NULL;
}
// Assumes the socket is not already in the linked list, and adds it
-STATIC void usocket_events_add(socket_obj_t *sock) {
- sock->events_next = usocket_events_head;
- usocket_events_head = sock;
+STATIC void socket_events_add(socket_obj_t *sock) {
+ sock->events_next = socket_events_head;
+ socket_events_head = sock;
}
// Assumes the socket is already in the linked list, and removes it
-STATIC void usocket_events_remove(socket_obj_t *sock) {
- for (socket_obj_t **s = &usocket_events_head;; s = &(*s)->events_next) {
+STATIC void socket_events_remove(socket_obj_t *sock) {
+ for (socket_obj_t **s = &socket_events_head;; s = &(*s)->events_next) {
if (*s == sock) {
*s = (*s)->events_next;
return;
@@ -111,20 +114,20 @@ STATIC void usocket_events_remove(socket_obj_t *sock) {
}
// Polls all registered sockets for readability and calls their callback if they are readable
-void usocket_events_handler(void) {
- if (usocket_events_head == NULL) {
+void socket_events_handler(void) {
+ if (socket_events_head == NULL) {
return;
}
- if (--usocket_events_divisor) {
+ if (--socket_events_divisor) {
return;
}
- usocket_events_divisor = USOCKET_EVENTS_DIVISOR;
+ socket_events_divisor = USOCKET_EVENTS_DIVISOR;
fd_set rfds;
FD_ZERO(&rfds);
int max_fd = 0;
- for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) {
+ for (socket_obj_t *s = socket_events_head; s != NULL; s = s->events_next) {
FD_SET(s->fd, &rfds);
max_fd = MAX(max_fd, s->fd);
}
@@ -137,14 +140,14 @@ void usocket_events_handler(void) {
}
// Call the callbacks
- for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) {
+ for (socket_obj_t *s = socket_events_head; s != NULL; s = s->events_next) {
if (FD_ISSET(s->fd, &rfds)) {
mp_call_function_1_protected(s->events_callback, s);
}
}
}
-#endif // MICROPY_PY_USOCKET_EVENTS
+#endif // MICROPY_PY_SOCKET_EVENTS
static inline void check_for_exceptions(void) {
mp_handle_pending(true);
@@ -164,11 +167,7 @@ static int _socket_getaddrinfo3(const char *nodename, const char *servname,
memcpy(nodename_no_local, nodename, nodename_len - local_len);
nodename_no_local[nodename_len - local_len] = '\0';
- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 1, 0)
- struct ip4_addr addr = {0};
- #else
esp_ip4_addr_t addr = {0};
- #endif
esp_err_t err = mdns_query_a(nodename_no_local, MDNS_QUERY_TIMEOUT_MS, &addr);
if (err != ESP_OK) {
@@ -214,7 +213,7 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc
};
mp_obj_t port = portx;
- if (mp_obj_is_small_int(port)) {
+ if (mp_obj_is_integer(port)) {
// This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but
// that's the API we have to work with ...
port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port);
@@ -299,7 +298,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
STATIC mp_obj_t socket_listen(size_t n_args, const mp_obj_t *args) {
socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- int backlog = MICROPY_PY_USOCKET_LISTEN_BACKLOG_DEFAULT;
+ int backlog = MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT;
if (n_args > 1) {
backlog = mp_obj_get_int(args[1]);
backlog = (backlog < 0) ? 0 : backlog;
@@ -396,18 +395,18 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
break;
}
- #if MICROPY_PY_USOCKET_EVENTS
+ #if MICROPY_PY_SOCKET_EVENTS
// level: SOL_SOCKET
// special "register callback" option
case 20: {
if (args[3] == mp_const_none) {
if (self->events_callback != MP_OBJ_NULL) {
- usocket_events_remove(self);
+ socket_events_remove(self);
self->events_callback = MP_OBJ_NULL;
}
} else {
if (self->events_callback == MP_OBJ_NULL) {
- usocket_events_add(self);
+ socket_events_add(self);
}
self->events_callback = args[3];
}
@@ -552,7 +551,7 @@ mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in,
}
vstr.len = ret;
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
@@ -734,9 +733,9 @@ STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintpt
return ret;
} else if (request == MP_STREAM_CLOSE) {
if (socket->fd >= 0) {
- #if MICROPY_PY_USOCKET_EVENTS
+ #if MICROPY_PY_SOCKET_EVENTS
if (socket->events_callback != MP_OBJ_NULL) {
- usocket_events_remove(socket);
+ socket_events_remove(socket);
socket->events_callback = MP_OBJ_NULL;
}
#endif
@@ -785,13 +784,14 @@ STATIC const mp_stream_p_t socket_stream_p = {
.ioctl = socket_stream_ioctl
};
-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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, socket_make_new,
+ protocol, &socket_stream_p,
+ locals_dict, &socket_locals_dict
+ );
STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
// TODO support additional args beyond the first two
@@ -835,7 +835,7 @@ STATIC mp_obj_t esp_socket_initialize() {
static int initialized = 0;
if (!initialized) {
ESP_LOGI("modsocket", "Initializing");
- tcpip_adapter_init();
+ esp_netif_init();
initialized = 1;
}
return mp_const_none;
@@ -843,7 +843,7 @@ STATIC mp_obj_t esp_socket_initialize() {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_socket_initialize_obj, esp_socket_initialize);
STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) },
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_socket) },
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_socket_initialize_obj) },
{ MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) },
{ MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&esp_socket_getaddrinfo_obj) },
@@ -863,12 +863,12 @@ STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table);
-const mp_obj_module_t mp_module_usocket = {
+const mp_obj_module_t mp_module_socket = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_socket_globals,
};
-// Note: This port doesn't define MICROPY_PY_USOCKET or MICROPY_PY_LWIP so
+// Note: This port doesn't define MICROPY_PY_SOCKET or MICROPY_PY_LWIP so
// this will not conflict with the common implementation provided by
-// extmod/mod{lwip,usocket}.c.
-MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_usocket);
+// extmod/mod{lwip,socket}.c.
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_socket, mp_module_socket);
diff --git a/ports/esp32/modtime.c b/ports/esp32/modtime.c
new file mode 100644
index 0000000000000..7a2b2150869e1
--- /dev/null
+++ b/ports/esp32/modtime.c
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * Development of the code in this file was sponsored by Microbric Pty Ltd
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2023 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 "py/obj.h"
+#include "shared/timeutils/timeutils.h"
+
+// Return the localtime as an 8-tuple.
+STATIC mp_obj_t mp_time_localtime_get(void) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ timeutils_struct_time_t tm;
+ timeutils_seconds_since_epoch_to_struct_time(tv.tv_sec, &tm);
+ mp_obj_t tuple[8] = {
+ tuple[0] = mp_obj_new_int(tm.tm_year),
+ tuple[1] = mp_obj_new_int(tm.tm_mon),
+ tuple[2] = mp_obj_new_int(tm.tm_mday),
+ tuple[3] = mp_obj_new_int(tm.tm_hour),
+ tuple[4] = mp_obj_new_int(tm.tm_min),
+ tuple[5] = mp_obj_new_int(tm.tm_sec),
+ tuple[6] = mp_obj_new_int(tm.tm_wday),
+ tuple[7] = mp_obj_new_int(tm.tm_yday),
+ };
+ return mp_obj_new_tuple(8, tuple);
+}
+
+// Return the number of seconds since the Epoch.
+STATIC mp_obj_t mp_time_time_get(void) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return mp_obj_new_int(tv.tv_sec);
+}
diff --git a/ports/esp32/modules/_boot.py b/ports/esp32/modules/_boot.py
index a7d9813090bfd..651fc7b10cdd8 100644
--- a/ports/esp32/modules/_boot.py
+++ b/ports/esp32/modules/_boot.py
@@ -1,10 +1,10 @@
import gc
-import uos
+import os
from flashbdev import bdev
try:
if bdev:
- uos.mount(bdev, "/")
+ os.mount(bdev, "/")
except OSError:
import inisetup
diff --git a/ports/esp32/modules/espnow.py b/ports/esp32/modules/espnow.py
new file mode 100644
index 0000000000000..6956a3a935573
--- /dev/null
+++ b/ports/esp32/modules/espnow.py
@@ -0,0 +1,30 @@
+# espnow module for MicroPython on ESP32
+# MIT license; Copyright (c) 2022 Glenn Moloney @glenn20
+
+from _espnow import *
+
+
+class ESPNow(ESPNowBase):
+ # Static buffers for alloc free receipt of messages with ESPNow.irecv().
+ _data = [None, bytearray(MAX_DATA_LEN)]
+ _none_tuple = (None, None)
+
+ def __init__(self):
+ super().__init__()
+
+ def irecv(self, timeout_ms=None):
+ n = self.recvinto(self._data, timeout_ms)
+ return self._data if n else self._none_tuple
+
+ def recv(self, timeout_ms=None):
+ n = self.recvinto(self._data, timeout_ms)
+ return [bytes(x) for x in self._data] if n else self._none_tuple
+
+ def irq(self, callback):
+ super().irq(callback, self)
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ return self.irecv() # Use alloc free irecv() method
diff --git a/ports/esp32/modules/inisetup.py b/ports/esp32/modules/inisetup.py
index 426a47a6b45e5..2003864e9f3e8 100644
--- a/ports/esp32/modules/inisetup.py
+++ b/ports/esp32/modules/inisetup.py
@@ -1,4 +1,4 @@
-import uos
+import os
from flashbdev import bdev
@@ -17,6 +17,10 @@ def check_bootsec():
def fs_corrupted():
import time
+ import micropython
+
+ # Allow this loop to be stopped via Ctrl-C.
+ micropython.kbd_intr(3)
while 1:
print(
@@ -33,9 +37,13 @@ def fs_corrupted():
def setup():
check_bootsec()
print("Performing initial setup")
- uos.VfsLfs2.mkfs(bdev)
- vfs = uos.VfsLfs2(bdev)
- uos.mount(vfs, "/")
+ if bdev.info()[4] == "vfs":
+ os.VfsLfs2.mkfs(bdev)
+ vfs = os.VfsLfs2(bdev)
+ elif bdev.info()[4] == "ffat":
+ os.VfsFat.mkfs(bdev)
+ vfs = os.VfsFat(bdev)
+ os.mount(vfs, "/")
with open("boot.py", "w") as f:
f.write(
"""\
diff --git a/ports/esp32/moduos.c b/ports/esp32/moduos.c
deleted file mode 100644
index f307a9ffe05b1..0000000000000
--- a/ports/esp32/moduos.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * Development of the code in this file was sponsored by Microbric Pty Ltd
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 Josef Gajdusek
- * Copyright (c) 2016 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 "esp_system.h"
-
-#include "py/runtime.h"
-#include "py/mphal.h"
-#include "extmod/misc.h"
-
-STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
- mp_int_t n = mp_obj_get_int(num);
- vstr_t vstr;
- vstr_init_len(&vstr, n);
- uint32_t r = 0;
- for (int i = 0; i < n; i++) {
- if ((i & 3) == 0) {
- r = esp_random(); // returns 32-bit hardware random number
- }
- vstr.buf[i] = r;
- r >>= 8;
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
-
-#if MICROPY_PY_UOS_DUPTERM_NOTIFY
-STATIC mp_obj_t mp_uos_dupterm_notify(mp_obj_t obj_in) {
- (void)obj_in;
- for (;;) {
- int c = mp_uos_dupterm_rx_chr();
- if (c < 0) {
- break;
- }
- ringbuf_put(&stdin_ringbuf, c);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_dupterm_notify_obj, mp_uos_dupterm_notify);
-#endif
diff --git a/ports/esp32/modutime.c b/ports/esp32/modutime.c
deleted file mode 100644
index 631d0fe2997d3..0000000000000
--- a/ports/esp32/modutime.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * Development of the code in this file was sponsored by Microbric Pty Ltd
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016 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/runtime.h"
-#include "shared/timeutils/timeutils.h"
-#include "extmod/utime_mphal.h"
-
-STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
- timeutils_struct_time_t tm;
- mp_int_t seconds;
- if (n_args == 0 || args[0] == mp_const_none) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- seconds = tv.tv_sec;
- } else {
- seconds = mp_obj_get_int(args[0]);
- }
- timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
- mp_obj_t tuple[8] = {
- tuple[0] = mp_obj_new_int(tm.tm_year),
- tuple[1] = mp_obj_new_int(tm.tm_mon),
- tuple[2] = mp_obj_new_int(tm.tm_mday),
- tuple[3] = mp_obj_new_int(tm.tm_hour),
- tuple[4] = mp_obj_new_int(tm.tm_min),
- tuple[5] = mp_obj_new_int(tm.tm_sec),
- tuple[6] = mp_obj_new_int(tm.tm_wday),
- tuple[7] = mp_obj_new_int(tm.tm_yday),
- };
- return mp_obj_new_tuple(8, tuple);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
-
-STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
- size_t len;
- mp_obj_t *elem;
- mp_obj_get_array(tuple, &len, &elem);
-
- // localtime generates a tuple of len 8. CPython uses 9, so we accept both.
- if (len < 8 || len > 9) {
- mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9 (%d given)"), len);
- }
-
- return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
- mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
- mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
-
-STATIC mp_obj_t time_time(void) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return mp_obj_new_int(tv.tv_sec);
-}
-MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
-
-STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
-
- { MP_ROM_QSTR(MP_QSTR_gmtime), MP_ROM_PTR(&time_localtime_obj) },
- { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) },
- { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) },
- { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },
- { MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_utime_time_ns_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
-
-const mp_obj_module_t utime_module = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&time_module_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_utime, utime_module);
diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h
index 1877a01437f1c..714871d4fc926 100644
--- a/ports/esp32/mpconfigport.h
+++ b/ports/esp32/mpconfigport.h
@@ -6,9 +6,11 @@
#include
#include
+#include "esp_random.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "driver/i2s.h"
+#include "esp_wifi_types.h"
#ifndef MICROPY_CONFIG_ROM_LEVEL
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
@@ -49,9 +51,6 @@
#define MICROPY_WARNINGS (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_STREAMS_POSIX_API (1)
-#define MICROPY_MODULE_FROZEN_STR (0)
-#define MICROPY_MODULE_FROZEN_MPY (1)
-#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
#define MICROPY_USE_INTERNAL_ERRNO (0) // errno.h from xtensa-esp32-elf/sys-include/sys
#define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf
#define MICROPY_SCHEDULER_DEPTH (8)
@@ -62,36 +61,43 @@
#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT esp32_help_text
#define MICROPY_PY_IO_BUFFEREDWRITER (1)
-#define MICROPY_PY_UTIME_MP_HAL (1)
+#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
+#define MICROPY_PY_TIME_TIME_TIME_NS (1)
+#define MICROPY_PY_TIME_INCLUDEFILE "ports/esp32/modtime.c"
#define MICROPY_PY_THREAD (1)
#define MICROPY_PY_THREAD_GIL (1)
#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32)
// extended modules
+#ifndef MICROPY_ESPNOW
+#define MICROPY_ESPNOW (1)
+#endif
#ifndef MICROPY_PY_BLUETOOTH
#define MICROPY_PY_BLUETOOTH (1)
+#define MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS (1)
+#define MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK (1)
+#define MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE (CONFIG_BT_NIMBLE_TASK_STACK_SIZE)
#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1)
+#define MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING (1)
#define MICROPY_BLUETOOTH_NIMBLE (1)
#define MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY (1)
#endif
-#define MICROPY_PY_UTIMEQ (1)
-#define MICROPY_PY_UHASHLIB_SHA1 (1)
-#define MICROPY_PY_UHASHLIB_SHA256 (1)
-#define MICROPY_PY_UCRYPTOLIB (1)
-#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (esp_random())
-#define MICROPY_PY_UOS_INCLUDEFILE "ports/esp32/moduos.c"
+#define MICROPY_PY_HASHLIB_SHA1 (1)
+#define MICROPY_PY_HASHLIB_SHA256 (1)
+#define MICROPY_PY_CRYPTOLIB (1)
+#define MICROPY_PY_RANDOM_SEED_INIT_FUNC (esp_random())
+#define MICROPY_PY_OS_INCLUDEFILE "ports/esp32/modos.c"
#define MICROPY_PY_OS_DUPTERM (1)
-#define MICROPY_PY_UOS_DUPTERM_NOTIFY (1)
-#define MICROPY_PY_UOS_UNAME (1)
-#define MICROPY_PY_UOS_URANDOM (1)
+#define MICROPY_PY_OS_DUPTERM_NOTIFY (1)
+#define MICROPY_PY_OS_SYNC (1)
+#define MICROPY_PY_OS_UNAME (1)
+#define MICROPY_PY_OS_URANDOM (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_BITSTREAM (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_PWM (1)
-#define MICROPY_PY_MACHINE_PWM_INIT (1)
#define MICROPY_PY_MACHINE_PWM_DUTY (1)
-#define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1)
#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/esp32/machine_pwm.c"
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 (1)
@@ -106,6 +112,20 @@
#ifndef MICROPY_PY_MACHINE_I2S
#define MICROPY_PY_MACHINE_I2S (1)
#endif
+#define MICROPY_PY_NETWORK (1)
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#if CONFIG_IDF_TARGET_ESP32
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s2"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s3"
+#elif CONFIG_IDF_TARGET_ESP32C3
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c3"
+#endif
+#endif
+#define MICROPY_PY_NETWORK_INCLUDEFILE "ports/esp32/modnetwork.h"
+#define MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE "ports/esp32/modnetwork_globals.h"
#ifndef MICROPY_PY_NETWORK_WLAN
#define MICROPY_PY_NETWORK_WLAN (1)
#endif
@@ -113,16 +133,15 @@
#define MICROPY_HW_ENABLE_SDCARD (1)
#endif
#define MICROPY_HW_SOFTSPI_MIN_DELAY (0)
-#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly
-#define MICROPY_PY_USSL (1)
+#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (esp_rom_get_cpu_ticks_per_us() * 1000000 / 200) // roughly
+#define MICROPY_PY_SSL (1)
#define MICROPY_SSL_MBEDTLS (1)
-#define MICROPY_PY_USSL_FINALISER (1)
-#define MICROPY_PY_UWEBSOCKET (1)
+#define MICROPY_PY_SSL_FINALISER (1)
+#define MICROPY_PY_WEBSOCKET (1)
#define MICROPY_PY_WEBREPL (1)
-#define MICROPY_PY_BTREE (1)
#define MICROPY_PY_ONEWIRE (1)
-#define MICROPY_PY_UPLATFORM (1)
-#define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL)
+#define MICROPY_PY_PLATFORM (1)
+#define MICROPY_PY_SOCKET_EVENTS (MICROPY_PY_WEBREPL)
#define MICROPY_PY_BLUETOOTH_RANDOM_ADDR (1)
#define MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME ("ESP32")
@@ -131,28 +150,9 @@
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
#define MP_STATE_PORT MP_STATE_VM
-struct _machine_timer_obj_t;
-
-#if MICROPY_BLUETOOTH_NIMBLE
-struct mp_bluetooth_nimble_root_pointers_t;
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers;
-#else
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
-#endif
-
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- mp_obj_t machine_pin_irq_handler[40]; \
- struct _machine_timer_obj_t *machine_timer_obj_head; \
- struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]; \
- mp_obj_t native_code_pointers; \
- MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
-
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p)))
@@ -164,13 +164,13 @@ void *esp_native_code_commit(void *, size_t, void *);
// the only disable interrupts on the current CPU. To full manage exclusion
// one should use portENTER_CRITICAL/portEXIT_CRITICAL instead.
#include "freertos/FreeRTOS.h"
-#define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED()
-#define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state)
+#define MICROPY_BEGIN_ATOMIC_SECTION() portSET_INTERRUPT_MASK_FROM_ISR()
+#define MICROPY_END_ATOMIC_SECTION(state) portCLEAR_INTERRUPT_MASK_FROM_ISR(state)
-#if MICROPY_PY_USOCKET_EVENTS
-#define MICROPY_PY_USOCKET_EVENTS_HANDLER extern void usocket_events_handler(void); usocket_events_handler();
+#if MICROPY_PY_SOCKET_EVENTS
+#define MICROPY_PY_SOCKET_EVENTS_HANDLER extern void socket_events_handler(void); socket_events_handler();
#else
-#define MICROPY_PY_USOCKET_EVENTS_HANDLER
+#define MICROPY_PY_SOCKET_EVENTS_HANDLER
#endif
#if MICROPY_PY_THREAD
@@ -178,7 +178,7 @@ void *esp_native_code_commit(void *, size_t, void *);
do { \
extern void mp_handle_pending(bool); \
mp_handle_pending(true); \
- MICROPY_PY_USOCKET_EVENTS_HANDLER \
+ MICROPY_PY_SOCKET_EVENTS_HANDLER \
MP_THREAD_GIL_EXIT(); \
ulTaskNotifyTake(pdFALSE, 1); \
MP_THREAD_GIL_ENTER(); \
@@ -188,7 +188,7 @@ void *esp_native_code_commit(void *, size_t, void *);
do { \
extern void mp_handle_pending(bool); \
mp_handle_pending(true); \
- MICROPY_PY_USOCKET_EVENTS_HANDLER \
+ MICROPY_PY_SOCKET_EVENTS_HANDLER \
asm ("waiti 0"); \
} while (0);
#endif
@@ -228,8 +228,30 @@ typedef long mp_off_t;
#define MICROPY_HW_ENABLE_MDNS_RESPONDER (1)
#endif
+#ifndef MICROPY_BOARD_ENTER_BOOTLOADER
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args)
+#endif
+
#ifndef MICROPY_BOARD_STARTUP
#define MICROPY_BOARD_STARTUP boardctrl_startup
#endif
void boardctrl_startup(void);
+
+#ifndef MICROPY_PY_NETWORK_LAN
+#if CONFIG_IDF_TARGET_ESP32 || (CONFIG_ETH_USE_SPI_ETHERNET && (CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL || CONFIG_ETH_SPI_ETHERNET_DM9051 || CONFIG_ETH_SPI_ETHERNET_W5500))
+#define MICROPY_PY_NETWORK_LAN (1)
+#else
+#define MICROPY_PY_NETWORK_LAN (0)
+#endif
+#endif
+
+#if MICROPY_PY_NETWORK_LAN && CONFIG_ETH_USE_SPI_ETHERNET
+#ifndef MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
+#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (12)
+#else
+#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (36)
+#endif
+#endif
+#endif
diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c
index aab534937e137..63a674c24b620 100644
--- a/ports/esp32/mphalport.c
+++ b/ports/esp32/mphalport.c
@@ -32,6 +32,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
+#include "esp_timer.h"
#include "py/obj.h"
#include "py/objstr.h"
@@ -88,6 +89,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) {
ret |= MP_STREAM_POLL_RD;
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ ret |= MP_STREAM_POLL_WR;
+ }
return ret;
}
@@ -107,7 +111,7 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
if (release_gil) {
MP_THREAD_GIL_EXIT();
}
- #if CONFIG_USB_ENABLED
+ #if CONFIG_USB_OTG_SUPPORTED
usb_tx_strn(str, len);
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
usb_serial_jtag_tx_strn(str, len);
@@ -118,7 +122,7 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
if (release_gil) {
MP_THREAD_GIL_ENTER();
}
- mp_uos_dupterm_tx_strn(str, len);
+ mp_os_dupterm_tx_strn(str, len);
}
uint32_t mp_hal_ticks_ms(void) {
@@ -130,16 +134,16 @@ uint32_t mp_hal_ticks_us(void) {
}
void mp_hal_delay_ms(uint32_t ms) {
- uint64_t us = ms * 1000;
+ uint64_t us = (uint64_t)ms * 1000ULL;
uint64_t dt;
uint64_t t0 = esp_timer_get_time();
for (;;) {
mp_handle_pending(true);
- MICROPY_PY_USOCKET_EVENTS_HANDLER
+ MICROPY_PY_SOCKET_EVENTS_HANDLER
MP_THREAD_GIL_EXIT();
uint64_t t1 = esp_timer_get_time();
dt = t1 - t0;
- if (dt + portTICK_PERIOD_MS * 1000 >= us) {
+ if (dt + portTICK_PERIOD_MS * 1000ULL >= us) {
// doing a vTaskDelay would take us beyond requested delay time
taskYIELD();
MP_THREAD_GIL_ENTER();
diff --git a/ports/esp32/mphalport.h b/ports/esp32/mphalport.h
index c838bd228420d..566d6609f110b 100644
--- a/ports/esp32/mphalport.h
+++ b/ports/esp32/mphalport.h
@@ -35,6 +35,8 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
+#include "driver/spi_master.h"
+
#define MICROPY_PLATFORM_VERSION "IDF" IDF_VER
// The core that the MicroPython task(s) are pinned to.
@@ -42,10 +44,10 @@
// and avoid the Wifi/BLE timing problems on the same core.
// Best effort here to remain backwards compatible in rare version edge cases...
// See https://github.com/micropython/micropython/issues/5489 for history
-#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
-#define MP_TASK_COREID (1)
-#else
+#if CONFIG_FREERTOS_UNICORE
#define MP_TASK_COREID (0)
+#else
+#define MP_TASK_COREID (1)
#endif
extern TaskHandle_t mp_main_task_handle;
@@ -67,7 +69,7 @@ __attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) {
}
void mp_hal_delay_us(uint32_t);
-#define mp_hal_delay_us_fast(us) ets_delay_us(us)
+#define mp_hal_delay_us_fast(us) esp_rom_delay_us(us)
void mp_hal_set_interrupt_char(int c);
uint32_t mp_hal_get_cpu_freq(void);
@@ -84,18 +86,17 @@ void mp_hal_wake_main_task_from_isr(void);
#define mp_hal_pin_obj_t gpio_num_t
mp_hal_pin_obj_t machine_pin_get_id(mp_obj_t pin_in);
#define mp_hal_get_pin_obj(o) machine_pin_get_id(o)
-#define mp_obj_get_pin(o) machine_pin_get_id(o) // legacy name; only to support esp8266/modonewire
#define mp_hal_pin_name(p) (p)
static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) {
- gpio_pad_select_gpio(pin);
+ esp_rom_gpio_pad_select_gpio(pin);
gpio_set_direction(pin, GPIO_MODE_INPUT);
}
static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) {
- gpio_pad_select_gpio(pin);
+ esp_rom_gpio_pad_select_gpio(pin);
gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT);
}
static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
- gpio_pad_select_gpio(pin);
+ esp_rom_gpio_pad_select_gpio(pin);
gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT_OD);
}
static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) {
@@ -111,4 +112,6 @@ static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) {
gpio_set_level(pin, v);
}
+spi_host_device_t machine_hw_spi_get_host(mp_obj_t in);
+
#endif // INCLUDED_MPHALPORT_H
diff --git a/ports/esp32/mpnimbleport.c b/ports/esp32/mpnimbleport.c
index a58fcbdbf49f4..8235275be6fd6 100644
--- a/ports/esp32/mpnimbleport.c
+++ b/ports/esp32/mpnimbleport.c
@@ -46,13 +46,13 @@ STATIC void ble_host_task(void *param) {
void mp_bluetooth_nimble_port_hci_init(void) {
DEBUG_printf("mp_bluetooth_nimble_port_hci_init\n");
- esp_nimble_hci_and_controller_init();
+ esp_nimble_hci_init();
}
void mp_bluetooth_nimble_port_hci_deinit(void) {
DEBUG_printf("mp_bluetooth_nimble_port_hci_deinit\n");
- esp_nimble_hci_and_controller_deinit();
+ esp_nimble_hci_deinit();
}
void mp_bluetooth_nimble_port_start(void) {
diff --git a/ports/esp32/network_common.c b/ports/esp32/network_common.c
new file mode 100644
index 0000000000000..082943e2aecc4
--- /dev/null
+++ b/ports/esp32/network_common.c
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * Development of the code in this file was sponsored by Microbric Pty Ltd
+ * and Mnemote Pty Ltd
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016, 2017 Nick Moore @mnemote
+ * Copyright (c) 2017 "Eric Poulsen"
+ *
+ * Based on esp8266/modnetwork.c which is Copyright (c) 2015 Paul Sokolovsky
+ * And the ESP IDF example code which is Public Domain / CC0
+ *
+ * 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 "py/runtime.h"
+#include "py/mperrno.h"
+#include "shared/netutils/netutils.h"
+#include "modnetwork.h"
+
+#include "esp_log.h"
+#include "esp_netif.h"
+#include "esp_wifi.h"
+// #include "lwip/dns.h"
+
+NORETURN void esp_exceptions_helper(esp_err_t e) {
+ switch (e) {
+ case ESP_ERR_WIFI_NOT_INIT:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Initialized"));
+ case ESP_ERR_WIFI_NOT_STARTED:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Started"));
+ case ESP_ERR_WIFI_NOT_STOPPED:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Stopped"));
+ case ESP_ERR_WIFI_IF:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Interface"));
+ case ESP_ERR_WIFI_MODE:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Mode"));
+ case ESP_ERR_WIFI_STATE:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Internal State Error"));
+ case ESP_ERR_WIFI_CONN:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Internal Error"));
+ case ESP_ERR_WIFI_NVS:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Internal NVS Error"));
+ case ESP_ERR_WIFI_MAC:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid MAC Address"));
+ case ESP_ERR_WIFI_SSID:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi SSID Invalid"));
+ case ESP_ERR_WIFI_PASSWORD:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Invalid Password"));
+ case ESP_ERR_WIFI_TIMEOUT:
+ mp_raise_OSError(MP_ETIMEDOUT);
+ case ESP_ERR_WIFI_WAKE_FAIL:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Wakeup Failure"));
+ case ESP_ERR_WIFI_WOULD_BLOCK:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Would Block"));
+ case ESP_ERR_WIFI_NOT_CONNECT:
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Wifi Not Connected"));
+ default:
+ mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Wifi Unknown Error 0x%04x"), e);
+ }
+}
+
+STATIC mp_obj_t esp_initialize() {
+ static int initialized = 0;
+ if (!initialized) {
+ esp_exceptions(esp_netif_init());
+ initialized = 1;
+ }
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_0(esp_network_initialize_obj, esp_initialize);
+
+STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
+ base_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ esp_netif_ip_info_t info;
+ esp_netif_dns_info_t dns_info;
+ esp_netif_get_ip_info(self->netif, &info);
+ esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info);
+ if (n_args == 1) {
+ // get
+ mp_obj_t tuple[4] = {
+ netutils_format_ipv4_addr((uint8_t *)&info.ip, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&info.netmask, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&info.gw, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&dns_info.ip, NETUTILS_BIG),
+ };
+ return mp_obj_new_tuple(4, tuple);
+ } else {
+ // set
+ if (mp_obj_is_type(args[1], &mp_type_tuple) || mp_obj_is_type(args[1], &mp_type_list)) {
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(args[1], 4, &items);
+ netutils_parse_ipv4_addr(items[0], (void *)&info.ip, NETUTILS_BIG);
+ if (mp_obj_is_integer(items[1])) {
+ // allow numeric netmask, i.e.:
+ // 24 -> 255.255.255.0
+ // 16 -> 255.255.0.0
+ // etc...
+ uint32_t *m = (uint32_t *)&info.netmask;
+ *m = esp_netif_htonl(0xffffffff << (32 - mp_obj_get_int(items[1])));
+ } else {
+ netutils_parse_ipv4_addr(items[1], (void *)&info.netmask, NETUTILS_BIG);
+ }
+ netutils_parse_ipv4_addr(items[2], (void *)&info.gw, NETUTILS_BIG);
+ netutils_parse_ipv4_addr(items[3], (void *)&dns_info.ip, NETUTILS_BIG);
+ // To set a static IP we have to disable DHCP first
+ if (self->if_id == ESP_IF_WIFI_STA || self->if_id == ESP_IF_ETH) {
+ esp_err_t e = esp_netif_dhcpc_stop(self->netif);
+ if (e != ESP_OK && e != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) {
+ esp_exceptions_helper(e);
+ }
+ esp_exceptions(esp_netif_set_ip_info(self->netif, &info));
+ esp_exceptions(esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info));
+ } else if (self->if_id == ESP_IF_WIFI_AP) {
+ esp_err_t e = esp_netif_dhcps_stop(self->netif);
+ if (e != ESP_OK && e != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) {
+ esp_exceptions_helper(e);
+ }
+ esp_exceptions(esp_netif_set_ip_info(self->netif, &info));
+ esp_exceptions(esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info));
+ esp_exceptions(esp_netif_dhcps_start(self->netif));
+ }
+ } else {
+ // check for the correct string
+ const char *mode = mp_obj_str_get_str(args[1]);
+ if ((self->if_id != ESP_IF_WIFI_STA && self->if_id != ESP_IF_ETH) || strcmp("dhcp", mode)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
+ }
+ esp_exceptions(esp_netif_dhcpc_start(self->netif));
+ }
+ return mp_const_none;
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_ifconfig_obj, 1, 2, esp_ifconfig);
+
+STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj, 0, 1, esp_phy_mode);
+
+_Static_assert(WIFI_AUTH_MAX == 10, "Synchronize WIFI_AUTH_XXX constants with the ESP-IDF. Look at esp-idf/components/esp_wifi/include/esp_wifi_types.h");
diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c
index f302d70fec1d5..fe3ff6f772a8a 100644
--- a/ports/esp32/network_lan.c
+++ b/ports/esp32/network_lan.c
@@ -32,34 +32,35 @@
#include "esp_idf_version.h"
-// LAN only for ESP32 (not ESP32S2) and only for ESP-IDF v4.1 and higher
-#if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32)
+#if MICROPY_PY_NETWORK_LAN
#include "esp_eth.h"
#include "esp_eth_mac.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
+#if CONFIG_ETH_USE_SPI_ETHERNET
+#include "driver/spi_master.h"
+#endif
#include "modnetwork.h"
typedef struct _lan_if_obj_t {
- mp_obj_base_t base;
- int if_id; // MUST BE FIRST to match wlan_if_obj_t
+ base_if_obj_t base;
bool initialized;
- bool active;
- uint8_t mdc_pin;
- uint8_t mdio_pin;
+ int8_t mdc_pin;
+ int8_t mdio_pin;
int8_t phy_power_pin;
+ int8_t phy_cs_pin;
+ int8_t phy_int_pin;
uint8_t phy_addr;
uint8_t phy_type;
esp_eth_phy_t *phy;
- esp_netif_t *eth_netif;
esp_eth_handle_t eth_handle;
} lan_if_obj_t;
const mp_obj_type_t lan_if_type;
-STATIC lan_if_obj_t lan_obj = {{&lan_if_type}, ESP_IF_ETH, false, false};
+STATIC lan_if_obj_t lan_obj = {{{&lan_if_type}, ESP_IF_ETH, NULL}, false, false};
STATIC uint8_t eth_status = 0;
static void eth_event_handler(void *arg, esp_event_base_t event_base,
@@ -97,14 +98,20 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
return MP_OBJ_FROM_PTR(&lan_obj);
}
- enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type };
+ enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type,
+ ARG_spi, ARG_cs, ARG_int, ARG_ref_clk_mode, ARG_ref_clk };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_spi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_int, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_ref_clk_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_ref_clk, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -116,38 +123,101 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
}
}
- self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj);
- self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj);
- self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj);
+ #define GET_PIN(XXX) args[XXX].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[XXX].u_obj);
+
+ self->mdc_pin = GET_PIN(ARG_mdc);
+ self->mdio_pin = GET_PIN(ARG_mdio);
+ self->phy_power_pin = GET_PIN(ARG_power);
+ self->phy_cs_pin = GET_PIN(ARG_cs);
+ self->phy_int_pin = GET_PIN(ARG_int);
if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid phy address"));
}
self->phy_addr = args[ARG_phy_addr].u_int;
- if (args[ARG_phy_type].u_int != PHY_LAN8720 &&
+ if (args[ARG_phy_type].u_int != PHY_LAN8710 &&
+ args[ARG_phy_type].u_int != PHY_LAN8720 &&
args[ARG_phy_type].u_int != PHY_IP101 &&
args[ARG_phy_type].u_int != PHY_RTL8201 &&
- #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3
args[ARG_phy_type].u_int != PHY_KSZ8041 &&
+ args[ARG_phy_type].u_int != PHY_KSZ8081 &&
+ #if CONFIG_ETH_USE_SPI_ETHERNET
+ #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
+ args[ARG_phy_type].u_int != PHY_KSZ8851SNL &&
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_DM9051
+ args[ARG_phy_type].u_int != PHY_DM9051 &&
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_W5500
+ args[ARG_phy_type].u_int != PHY_W5500 &&
+ #endif
#endif
args[ARG_phy_type].u_int != PHY_DP83848) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid phy type"));
}
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
- mac_config.smi_mdc_gpio_num = self->mdc_pin;
- mac_config.smi_mdio_gpio_num = self->mdio_pin;
- esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
+ #if CONFIG_IDF_TARGET_ESP32
+ eth_esp32_emac_config_t esp32_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
+ #endif
+
+ esp_eth_mac_t *mac = NULL;
+
+ #if CONFIG_IDF_TARGET_ESP32
+ // Dynamic ref_clk configuration.
+ if (args[ARG_ref_clk_mode].u_int != -1) {
+ // Map the GPIO_MODE constants to EMAC_CLK constants.
+ esp32_config.clock_config.rmii.clock_mode =
+ args[ARG_ref_clk_mode].u_int == GPIO_MODE_INPUT ? EMAC_CLK_EXT_IN : EMAC_CLK_OUT;
+ }
+ if (args[ARG_ref_clk].u_obj != mp_const_none) {
+ esp32_config.clock_config.rmii.clock_gpio = machine_pin_get_id(args[ARG_ref_clk].u_obj);
+ }
+ #endif
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = self->phy_addr;
phy_config.reset_gpio_num = self->phy_power_pin;
self->phy = NULL;
+ #if CONFIG_ETH_USE_SPI_ETHERNET
+ spi_device_handle_t spi_handle = NULL;
+ if (IS_SPI_PHY(args[ARG_phy_type].u_int)) {
+ spi_device_interface_config_t devcfg = {
+ .mode = 0,
+ .clock_speed_hz = MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ * 1000 * 1000,
+ .queue_size = 20,
+ .spics_io_num = self->phy_cs_pin,
+ };
+ switch (args[ARG_phy_type].u_int) {
+ #if CONFIG_ETH_SPI_ETHERNET_DM9051
+ case PHY_DM9051: {
+ devcfg.command_bits = 1;
+ devcfg.address_bits = 7;
+ break;
+ }
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_W5500
+ case PHY_W5500: {
+ devcfg.command_bits = 16;
+ devcfg.address_bits = 8;
+ break;
+ }
+ #endif
+ }
+ spi_host_device_t host = machine_hw_spi_get_host(args[ARG_spi].u_obj);
+ if (spi_bus_add_device(host, &devcfg, &spi_handle) != ESP_OK) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("spi_bus_add_device failed"));
+ }
+ }
+ #endif
+
switch (args[ARG_phy_type].u_int) {
+ #if CONFIG_IDF_TARGET_ESP32
+ case PHY_LAN8710:
case PHY_LAN8720:
- self->phy = esp_eth_phy_new_lan8720(&phy_config);
+ self->phy = esp_eth_phy_new_lan87xx(&phy_config);
break;
case PHY_IP101:
self->phy = esp_eth_phy_new_ip101(&phy_config);
@@ -159,24 +229,58 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
self->phy = esp_eth_phy_new_dp83848(&phy_config);
break;
case PHY_KSZ8041:
- #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3
- self->phy = esp_eth_phy_new_ksz8041(&phy_config);
+ case PHY_KSZ8081:
+ self->phy = esp_eth_phy_new_ksz80xx(&phy_config);
break;
- #endif
- default:
- mp_raise_ValueError(MP_ERROR_TEXT("unknown phy"));
+ #endif
+ #if CONFIG_ETH_USE_SPI_ETHERNET
+ #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
+ case PHY_KSZ8851SNL: {
+ eth_ksz8851snl_config_t chip_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle);
+ chip_config.int_gpio_num = self->phy_int_pin;
+ mac = esp_eth_mac_new_ksz8851snl(&chip_config, &mac_config);
+ self->phy = esp_eth_phy_new_ksz8851snl(&phy_config);
+ break;
+ }
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_DM9051
+ case PHY_DM9051: {
+ eth_dm9051_config_t chip_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
+ chip_config.int_gpio_num = self->phy_int_pin;
+ mac = esp_eth_mac_new_dm9051(&chip_config, &mac_config);
+ self->phy = esp_eth_phy_new_dm9051(&phy_config);
+ break;
+ }
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_W5500
+ case PHY_W5500: {
+ eth_w5500_config_t chip_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
+ chip_config.int_gpio_num = self->phy_int_pin;
+ mac = esp_eth_mac_new_w5500(&chip_config, &mac_config);
+ self->phy = esp_eth_phy_new_w5500(&phy_config);
+ break;
+ }
+ #endif
+ #endif
+ }
+
+ #if CONFIG_IDF_TARGET_ESP32
+ if (!IS_SPI_PHY(args[ARG_phy_type].u_int)) {
+ if (self->mdc_pin == -1 || self->mdio_pin == -1) {
+ mp_raise_ValueError(MP_ERROR_TEXT("mdc and mdio must be specified"));
+ }
+ esp32_config.smi_mdc_gpio_num = self->mdc_pin;
+ esp32_config.smi_mdio_gpio_num = self->mdio_pin;
+ mac = esp_eth_mac_new_esp32(&esp32_config, &mac_config);
}
+ #endif
if (esp_netif_init() != ESP_OK) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("esp_netif_init failed"));
}
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
- self->eth_netif = esp_netif_new(&cfg);
-
- if (esp_eth_set_default_handlers(self->eth_netif) != ESP_OK) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("esp_eth_set_default_handlers failed (invalid parameter)"));
- }
+ self->base.netif = esp_netif_new(&cfg);
if (esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL) != ESP_OK) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("esp_event_handler_register failed"));
@@ -190,7 +294,7 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
esp_err_t esp_err = esp_eth_driver_install(&config, &self->eth_handle);
if (esp_err == ESP_OK) {
- self->active = false;
+ self->base.active = false;
self->initialized = true;
} else {
if (esp_err == ESP_ERR_INVALID_ARG) {
@@ -202,7 +306,7 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
}
}
- if (esp_netif_attach(self->eth_netif, esp_eth_new_netif_glue(self->eth_handle)) != ESP_OK) {
+ if (esp_netif_attach(self->base.netif, esp_eth_new_netif_glue(self->eth_handle)) != ESP_OK) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("esp_netif_attach failed"));
}
@@ -210,26 +314,26 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
return MP_OBJ_FROM_PTR(&lan_obj);
}
-MP_DEFINE_CONST_FUN_OBJ_KW(get_lan_obj, 0, get_lan);
+MP_DEFINE_CONST_FUN_OBJ_KW(esp_network_get_lan_obj, 0, get_lan);
STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) {
lan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args > 1) {
if (mp_obj_is_true(args[1])) {
- self->active = (esp_eth_start(self->eth_handle) == ESP_OK);
- if (!self->active) {
+ self->base.active = (esp_eth_start(self->eth_handle) == ESP_OK);
+ if (!self->base.active) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("ethernet enable failed"));
}
} else {
- self->active = !(esp_eth_stop(self->eth_handle) == ESP_OK);
- if (self->active) {
+ self->base.active = !(esp_eth_stop(self->eth_handle) == ESP_OK);
+ if (self->base.active) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("ethernet disable failed"));
}
}
}
- return mp_obj_new_bool(self->active);
+ return mp_obj_new_bool(self->base.active);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lan_active_obj, 1, 2, lan_active);
@@ -240,7 +344,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_status_obj, lan_status);
STATIC mp_obj_t lan_isconnected(mp_obj_t self_in) {
lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return self->active ? mp_obj_new_bool(self->phy->get_link(self->phy) == ETH_LINK_UP) : mp_const_false;
+ return self->base.active ? mp_obj_new_bool(self->phy->get_link(self->phy) == ETH_LINK_UP) : mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_isconnected_obj, lan_isconnected);
@@ -261,7 +365,12 @@ STATIC mp_obj_t lan_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
if (bufinfo.len != 6) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer length"));
}
- esp_eth_ioctl(self->eth_handle, ETH_CMD_S_MAC_ADDR, bufinfo.buf);
+ if (
+ (esp_eth_ioctl(self->eth_handle, ETH_CMD_S_MAC_ADDR, bufinfo.buf) != ESP_OK) ||
+ (esp_netif_set_mac(self->base.netif, bufinfo.buf) != ESP_OK)
+ ) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed setting MAC address"));
+ }
break;
}
default:
@@ -297,15 +406,16 @@ STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&lan_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&lan_config_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_network_ifconfig_obj) },
};
STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table);
-const mp_obj_type_t lan_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_LAN,
- .locals_dict = (mp_obj_dict_t *)&lan_if_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ lan_if_type,
+ MP_QSTR_LAN,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &lan_if_locals_dict
+ );
#endif
diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c
index d74283c19cf63..caad7eb48bfe5 100644
--- a/ports/esp32/network_ppp.c
+++ b/ports/esp32/network_ppp.c
@@ -32,6 +32,7 @@
#include "py/stream.h"
#include "shared/netutils/netutils.h"
#include "modmachine.h"
+#include "ppp_set_auth.h"
#include "netif/ppp/ppp.h"
#include "netif/ppp/pppos.h"
@@ -91,7 +92,7 @@ STATIC mp_obj_t ppp_make_new(mp_obj_t stream) {
return MP_OBJ_FROM_PTR(self);
}
-MP_DEFINE_CONST_FUN_OBJ_1(ppp_make_new_obj, ppp_make_new);
+MP_DEFINE_CONST_FUN_OBJ_1(esp_network_ppp_make_new_obj, ppp_make_new);
static u32_t ppp_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
ppp_if_obj_t *self = ctx;
@@ -278,8 +279,9 @@ STATIC const mp_rom_map_elem_t ppp_if_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(ppp_if_locals_dict, ppp_if_locals_dict_table);
-const mp_obj_type_t ppp_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_PPP,
- .locals_dict = (mp_obj_dict_t *)&ppp_if_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ppp_if_type,
+ MP_QSTR_PPP,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &ppp_if_locals_dict
+ );
diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c
index 48b398c8f023d..8287731c31b89 100644
--- a/ports/esp32/network_wlan.c
+++ b/ports/esp32/network_wlan.c
@@ -35,11 +35,16 @@
#include "py/objlist.h"
#include "py/runtime.h"
+#include "py/mphal.h"
+#include "extmod/modnetwork.h"
#include "modnetwork.h"
#include "esp_wifi.h"
#include "esp_log.h"
+
+#ifndef NO_QSTR
#include "mdns.h"
+#endif
#if MICROPY_PY_NETWORK_WLAN
@@ -47,9 +52,10 @@
#error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields!
#endif
-STATIC const mp_obj_type_t wlan_if_type;
-STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA};
-STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP};
+typedef base_if_obj_t wlan_if_obj_t;
+
+STATIC wlan_if_obj_t wlan_sta_obj;
+STATIC wlan_if_obj_t wlan_ap_obj;
// Set to "true" if esp_wifi_start() was called
static bool wifi_started = false;
@@ -74,38 +80,27 @@ static uint8_t wifi_sta_reconnects;
// This function is called by the system-event task and so runs in a different
// thread to the main MicroPython task. It must not raise any Python exceptions.
-void network_wlan_event_handler(system_event_t *event) {
- switch (event->event_id) {
- case SYSTEM_EVENT_STA_START:
+static void network_wlan_wifi_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
+ switch (event_id) {
+ case WIFI_EVENT_STA_START:
ESP_LOGI("wifi", "STA_START");
+ wlan_sta_obj.active = true;
wifi_sta_reconnects = 0;
break;
- case SYSTEM_EVENT_STA_CONNECTED:
- ESP_LOGI("network", "CONNECTED");
+
+ case WIFI_EVENT_STA_STOP:
+ wlan_sta_obj.active = false;
break;
- case SYSTEM_EVENT_STA_GOT_IP:
- ESP_LOGI("network", "GOT_IP");
- wifi_sta_connected = true;
- wifi_sta_disconn_reason = 0; // Success so clear error. (in case of new error will be replaced anyway)
- #if MICROPY_HW_ENABLE_MDNS_QUERIES || MICROPY_HW_ENABLE_MDNS_RESPONDER
- if (!mdns_initialised) {
- mdns_init();
- #if MICROPY_HW_ENABLE_MDNS_RESPONDER
- const char *hostname = NULL;
- if (tcpip_adapter_get_hostname(WIFI_IF_STA, &hostname) != ESP_OK || hostname == NULL) {
- hostname = "esp32";
- }
- mdns_hostname_set(hostname);
- mdns_instance_name_set(hostname);
- #endif
- mdns_initialised = true;
- }
- #endif
+
+ case WIFI_EVENT_STA_CONNECTED:
+ ESP_LOGI("network", "CONNECTED");
break;
- case SYSTEM_EVENT_STA_DISCONNECTED: {
+
+ case WIFI_EVENT_STA_DISCONNECTED: {
// This is a workaround as ESP32 WiFi libs don't currently
// auto-reassociate.
- system_event_sta_disconnected_t *disconn = &event->event_info.disconnected;
+
+ wifi_event_sta_disconnected_t *disconn = event_data;
char *message = "";
wifi_sta_disconn_reason = disconn->reason;
switch (disconn->reason) {
@@ -150,6 +145,38 @@ void network_wlan_event_handler(system_event_t *event) {
}
break;
}
+
+ case WIFI_EVENT_AP_START:
+ wlan_ap_obj.active = true;
+ break;
+
+ case WIFI_EVENT_AP_STOP:
+ wlan_ap_obj.active = false;
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void network_wlan_ip_event_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
+ switch (event_id) {
+ case IP_EVENT_STA_GOT_IP:
+ ESP_LOGI("network", "GOT_IP");
+ wifi_sta_connected = true;
+ wifi_sta_disconn_reason = 0; // Success so clear error. (in case of new error will be replaced anyway)
+ #if MICROPY_HW_ENABLE_MDNS_QUERIES || MICROPY_HW_ENABLE_MDNS_RESPONDER
+ if (!mdns_initialised) {
+ mdns_init();
+ #if MICROPY_HW_ENABLE_MDNS_RESPONDER
+ mdns_hostname_set(mod_network_hostname);
+ mdns_instance_name_set(mod_network_hostname);
+ #endif
+ mdns_initialised = true;
+ }
+ #endif
+ break;
+
default:
break;
}
@@ -158,31 +185,50 @@ void network_wlan_event_handler(system_event_t *event) {
STATIC void require_if(mp_obj_t wlan_if, int if_no) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
if (self->if_id != if_no) {
- mp_raise_msg(&mp_type_OSError, if_no == WIFI_IF_STA ? MP_ERROR_TEXT("STA required") : MP_ERROR_TEXT("AP required"));
+ mp_raise_msg(&mp_type_OSError, if_no == ESP_IF_WIFI_STA ? MP_ERROR_TEXT("STA required") : MP_ERROR_TEXT("AP required"));
}
}
-STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
- static int initialized = 0;
- if (!initialized) {
+void esp_initialise_wifi(void) {
+ static int wifi_initialized = 0;
+ if (!wifi_initialized) {
+ esp_exceptions(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, network_wlan_wifi_event_handler, NULL, NULL));
+ esp_exceptions(esp_event_handler_instance_register(IP_EVENT, ESP_EVENT_ANY_ID, network_wlan_ip_event_handler, NULL, NULL));
+
+ wlan_sta_obj.base.type = &esp_network_wlan_type;
+ wlan_sta_obj.if_id = ESP_IF_WIFI_STA;
+ wlan_sta_obj.netif = esp_netif_create_default_wifi_sta();
+ wlan_sta_obj.active = false;
+
+ wlan_ap_obj.base.type = &esp_network_wlan_type;
+ wlan_ap_obj.if_id = ESP_IF_WIFI_AP;
+ wlan_ap_obj.netif = esp_netif_create_default_wifi_ap();
+ wlan_ap_obj.active = false;
+
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_LOGD("modnetwork", "Initializing WiFi");
esp_exceptions(esp_wifi_init(&cfg));
esp_exceptions(esp_wifi_set_storage(WIFI_STORAGE_RAM));
+
ESP_LOGD("modnetwork", "Initialized");
- initialized = 1;
+ wifi_initialized = 1;
}
+}
+
+STATIC mp_obj_t network_wlan_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, 1, false);
+
+ esp_initialise_wifi();
- int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : WIFI_IF_STA;
- if (idx == WIFI_IF_STA) {
+ int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : ESP_IF_WIFI_STA;
+ if (idx == ESP_IF_WIFI_STA) {
return MP_OBJ_FROM_PTR(&wlan_sta_obj);
- } else if (idx == WIFI_IF_AP) {
+ } else if (idx == ESP_IF_WIFI_AP) {
return MP_OBJ_FROM_PTR(&wlan_ap_obj);
} else {
mp_raise_ValueError(MP_ERROR_TEXT("invalid WLAN interface identifier"));
}
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
@@ -194,7 +240,7 @@ STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) {
esp_exceptions(esp_wifi_get_mode(&mode));
}
- int bit = (self->if_id == WIFI_IF_STA) ? WIFI_MODE_STA : WIFI_MODE_AP;
+ int bit = (self->if_id == ESP_IF_WIFI_STA) ? WIFI_MODE_STA : WIFI_MODE_AP;
if (n_args > 1) {
bool active = mp_obj_is_true(args[1]);
@@ -211,6 +257,11 @@ STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) {
wifi_started = true;
}
}
+
+ // Wait for the interface to be in the correct state.
+ while (self->active != active) {
+ MICROPY_EVENT_POLL_HOOK;
+ }
}
return (mode & bit) ? mp_const_true : mp_const_false;
@@ -254,6 +305,8 @@ STATIC mp_obj_t network_wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp
esp_exceptions(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config));
}
+ esp_exceptions(esp_netif_set_hostname(wlan_sta_obj.netif, mod_network_hostname));
+
wifi_sta_reconnects = 0;
// connect to the WiFi AP
MP_THREAD_GIL_EXIT();
@@ -275,7 +328,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_wlan_disconnect_obj, network_wlan_disco
STATIC mp_obj_t network_wlan_status(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) {
- if (self->if_id == WIFI_IF_STA) {
+ if (self->if_id == ESP_IF_WIFI_STA) {
// Case of no arg is only for the STA interface
if (wifi_sta_connected) {
// Happy path, connected with IP
@@ -300,7 +353,7 @@ STATIC mp_obj_t network_wlan_status(size_t n_args, const mp_obj_t *args) {
switch ((uintptr_t)args[1]) {
case (uintptr_t)MP_OBJ_NEW_QSTR(MP_QSTR_stations): {
// return list of connected stations, only if in soft-AP mode
- require_if(args[0], WIFI_IF_AP);
+ require_if(args[0], ESP_IF_WIFI_AP);
wifi_sta_list_t station_list;
esp_exceptions(esp_wifi_ap_get_sta_list(&station_list));
wifi_sta_info_t *stations = (wifi_sta_info_t *)station_list.sta;
@@ -314,7 +367,7 @@ STATIC mp_obj_t network_wlan_status(size_t n_args, const mp_obj_t *args) {
}
case (uintptr_t)MP_OBJ_NEW_QSTR(MP_QSTR_rssi): {
// return signal of AP, only in STA mode
- require_if(args[0], WIFI_IF_STA);
+ require_if(args[0], ESP_IF_WIFI_STA);
wifi_ap_record_t info;
esp_exceptions(esp_wifi_sta_get_ap_info(&info));
@@ -373,7 +426,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_wlan_scan_obj, network_wlan_scan);
STATIC mp_obj_t network_wlan_isconnected(mp_obj_t self_in) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->if_id == WIFI_IF_STA) {
+ if (self->if_id == ESP_IF_WIFI_STA) {
return mp_obj_new_bool(wifi_sta_connected);
} else {
wifi_sta_list_t sta;
@@ -390,7 +443,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- bool is_wifi = self->if_id == WIFI_IF_AP || self->if_id == WIFI_IF_STA;
+ bool is_wifi = self->if_id == ESP_IF_WIFI_AP || self->if_id == ESP_IF_WIFI_STA;
wifi_config_t cfg;
if (is_wifi) {
@@ -418,7 +471,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
}
case MP_QSTR_ssid:
case MP_QSTR_essid: {
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
size_t len;
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
len = MIN(len, sizeof(cfg.ap.ssid));
@@ -427,19 +480,19 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
break;
}
case MP_QSTR_hidden: {
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value);
break;
}
case MP_QSTR_security:
case MP_QSTR_authmode: {
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
break;
}
case MP_QSTR_key:
case MP_QSTR_password: {
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
size_t len;
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
len = MIN(len, sizeof(cfg.ap.password) - 1);
@@ -448,23 +501,43 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
break;
}
case MP_QSTR_channel: {
- req_if = WIFI_IF_AP;
- cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
+ uint8_t primary;
+ wifi_second_chan_t secondary;
+ // Get the current value of secondary
+ esp_exceptions(esp_wifi_get_channel(&primary, &secondary));
+ primary = mp_obj_get_int(kwargs->table[i].value);
+ esp_err_t err = esp_wifi_set_channel(primary, secondary);
+ if (err == ESP_ERR_INVALID_ARG) {
+ // May need to swap secondary channel above to below or below to above
+ secondary = (
+ (secondary == WIFI_SECOND_CHAN_ABOVE)
+ ? WIFI_SECOND_CHAN_BELOW
+ : (secondary == WIFI_SECOND_CHAN_BELOW)
+ ? WIFI_SECOND_CHAN_ABOVE
+ : WIFI_SECOND_CHAN_NONE);
+ esp_exceptions(esp_wifi_set_channel(primary, secondary));
+ }
break;
}
+ case MP_QSTR_hostname:
case MP_QSTR_dhcp_hostname: {
- const char *s = mp_obj_str_get_str(kwargs->table[i].value);
- esp_exceptions(tcpip_adapter_set_hostname(self->if_id, s));
+ // TODO: Deprecated. Use network.hostname(name) instead.
+ size_t len;
+ const char *str = mp_obj_str_get_data(kwargs->table[i].value, &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
+ }
+ strcpy(mod_network_hostname, str);
break;
}
case MP_QSTR_max_clients: {
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
cfg.ap.max_connection = mp_obj_get_int(kwargs->table[i].value);
break;
}
case MP_QSTR_reconnects: {
int reconnects = mp_obj_get_int(kwargs->table[i].value);
- req_if = WIFI_IF_STA;
+ req_if = ESP_IF_WIFI_STA;
// parameter reconnects == -1 means to retry forever.
// here means conf_wifi_sta_reconnects == 0 to retry forever.
conf_wifi_sta_reconnects = (reconnects == -1) ? 0 : reconnects + 1;
@@ -475,6 +548,14 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
esp_exceptions(esp_wifi_set_max_tx_power(power));
break;
}
+ case MP_QSTR_protocol: {
+ esp_exceptions(esp_wifi_set_protocol(self->if_id, mp_obj_get_int(kwargs->table[i].value)));
+ break;
+ }
+ case MP_QSTR_pm: {
+ esp_exceptions(esp_wifi_set_ps(mp_obj_get_int(kwargs->table[i].value)));
+ break;
+ }
default:
goto unknown;
}
@@ -504,8 +585,8 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
case MP_QSTR_mac: {
uint8_t mac[6];
switch (self->if_id) {
- case WIFI_IF_AP: // fallthrough intentional
- case WIFI_IF_STA:
+ case ESP_IF_WIFI_AP: // fallthrough intentional
+ case ESP_IF_WIFI_STA:
esp_exceptions(esp_wifi_get_mac(self->if_id, mac));
return mp_obj_new_bytes(mac, sizeof(mac));
default:
@@ -515,33 +596,37 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
case MP_QSTR_ssid:
case MP_QSTR_essid:
switch (self->if_id) {
- case WIFI_IF_STA:
+ case ESP_IF_WIFI_STA:
val = mp_obj_new_str((char *)cfg.sta.ssid, strlen((char *)cfg.sta.ssid));
break;
- case WIFI_IF_AP:
+ case ESP_IF_WIFI_AP:
val = mp_obj_new_str((char *)cfg.ap.ssid, cfg.ap.ssid_len);
break;
default:
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
}
break;
case MP_QSTR_hidden:
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
val = mp_obj_new_bool(cfg.ap.ssid_hidden);
break;
case MP_QSTR_security:
case MP_QSTR_authmode:
- req_if = WIFI_IF_AP;
+ req_if = ESP_IF_WIFI_AP;
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
break;
- case MP_QSTR_channel:
- req_if = WIFI_IF_AP;
- val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
+ case MP_QSTR_channel: {
+ uint8_t channel;
+ wifi_second_chan_t second;
+ esp_exceptions(esp_wifi_get_channel(&channel, &second));
+ val = MP_OBJ_NEW_SMALL_INT(channel);
break;
+ }
+ case MP_QSTR_hostname:
case MP_QSTR_dhcp_hostname: {
- const char *s;
- esp_exceptions(tcpip_adapter_get_hostname(self->if_id, &s));
- val = mp_obj_new_str(s, strlen(s));
+ // TODO: Deprecated. Use network.hostname() instead.
+ req_if = ESP_IF_WIFI_STA;
+ val = mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
break;
}
case MP_QSTR_max_clients: {
@@ -549,7 +634,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
break;
}
case MP_QSTR_reconnects:
- req_if = WIFI_IF_STA;
+ req_if = ESP_IF_WIFI_STA;
int rec = conf_wifi_sta_reconnects - 1;
val = MP_OBJ_NEW_SMALL_INT(rec);
break;
@@ -559,6 +644,18 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
val = mp_obj_new_float(power * 0.25);
break;
}
+ case MP_QSTR_protocol: {
+ uint8_t protocol_bitmap;
+ esp_exceptions(esp_wifi_get_protocol(self->if_id, &protocol_bitmap));
+ val = MP_OBJ_NEW_SMALL_INT(protocol_bitmap);
+ break;
+ }
+ case MP_QSTR_pm: {
+ wifi_ps_type_t ps_type;
+ esp_exceptions(esp_wifi_get_ps(&ps_type));
+ val = MP_OBJ_NEW_SMALL_INT(ps_type);
+ break;
+ }
default:
goto unknown;
}
@@ -583,14 +680,21 @@ STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_wlan_scan_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_wlan_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_wlan_config_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_network_ifconfig_obj) },
+
+ // Constants
+ { MP_ROM_QSTR(MP_QSTR_PM_NONE), MP_ROM_INT(WIFI_PS_NONE) },
+ { MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(WIFI_PS_MIN_MODEM) },
+ { MP_ROM_QSTR(MP_QSTR_PM_POWERSAVE), MP_ROM_INT(WIFI_PS_MAX_MODEM) },
};
STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
-STATIC const mp_obj_type_t wlan_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_WLAN,
- .locals_dict = (mp_obj_t)&wlan_if_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_network_wlan_type,
+ MP_QSTR_WLAN,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_wlan_make_new,
+ locals_dict, &wlan_if_locals_dict
+ );
#endif // MICROPY_PY_NETWORK_WLAN
diff --git a/ports/esp32/partitions-32MiB-ota.csv b/ports/esp32/partitions-32MiB-ota.csv
new file mode 100644
index 0000000000000..7366a2ad8df79
--- /dev/null
+++ b/ports/esp32/partitions-32MiB-ota.csv
@@ -0,0 +1,10 @@
+# Partition table for MicroPython with OTA support using 32MB flash
+# Notes: the offset of the partition table itself is set in
+# $IDF_PATH/components/partition_table/Kconfig.projbuild.
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x4000,
+otadata, data, ota, 0xd000, 0x2000,
+phy_init, data, phy, 0xf000, 0x1000,
+ota_0, app, ota_0, 0x10000, 0x270000,
+ota_1, app, ota_1, 0x280000, 0x270000,
+vfs, data, fat, 0x4f0000, 0x1B10000,
diff --git a/ports/esp32/partitions-32MiB.csv b/ports/esp32/partitions-32MiB.csv
new file mode 100644
index 0000000000000..31591c99495f9
--- /dev/null
+++ b/ports/esp32/partitions-32MiB.csv
@@ -0,0 +1,7 @@
+# Notes: the offset of the partition table itself is set in
+# $IDF_PATH/components/partition_table/Kconfig.projbuild.
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x6000,
+phy_init, data, phy, 0xf000, 0x1000,
+factory, app, factory, 0x10000, 0x1F0000,
+vfs, data, fat, 0x200000, 0x1E00000,
diff --git a/ports/esp32/ppp_set_auth.c b/ports/esp32/ppp_set_auth.c
new file mode 100644
index 0000000000000..88ab668d48d3a
--- /dev/null
+++ b/ports/esp32/ppp_set_auth.c
@@ -0,0 +1,35 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// The pppapi_set_auth function was made static in the ESP-IDF, so it's re-added here.
+// See ESP-IDF commit c67f4c2b4c2bb4b7740f988fc0f8a3e911e56afe
+
+#include "ppp_set_auth.h"
+
+#ifdef CONFIG_ESP_NETIF_TCPIP_LWIP
+
+#include "netif/ppp/pppapi.h"
+
+typedef struct {
+ struct tcpip_api_call_data call;
+ ppp_pcb *ppp;
+ u8_t authtype;
+ const char *user;
+ const char *passwd;
+} set_auth_msg_t;
+
+static err_t pppapi_do_ppp_set_auth(struct tcpip_api_call_data *m) {
+ set_auth_msg_t *msg = (set_auth_msg_t *)m;
+ ppp_set_auth(msg->ppp, msg->authtype, msg->user, msg->passwd);
+ return ERR_OK;
+}
+
+void pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) {
+ set_auth_msg_t msg = { .ppp = pcb, .authtype = authtype, .user = user, .passwd = passwd};
+ tcpip_api_call(pppapi_do_ppp_set_auth, &msg.call);
+}
+
+#endif
diff --git a/ports/esp32/ppp_set_auth.h b/ports/esp32/ppp_set_auth.h
new file mode 100644
index 0000000000000..67676ef4d6c76
--- /dev/null
+++ b/ports/esp32/ppp_set_auth.h
@@ -0,0 +1,22 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// The pppapi_set_auth function was made static in the ESP-IDF, so it's re-added here.
+// See ESP-IDF commit c67f4c2b4c2bb4b7740f988fc0f8a3e911e56afe
+
+#pragma once
+
+#include "esp_netif.h"
+
+#ifdef CONFIG_ESP_NETIF_TCPIP_LWIP
+
+#include "lwip/netif.h"
+
+typedef struct ppp_pcb_s ppp_pcb;
+
+void pppapi_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd);
+
+#endif
diff --git a/ports/esp32/uart.c b/ports/esp32/uart.c
index f6493dc796797..358d434709951 100644
--- a/ports/esp32/uart.c
+++ b/ports/esp32/uart.c
@@ -28,77 +28,93 @@
#include
-#include "driver/uart.h"
-#include "soc/uart_periph.h"
+#include "hal/uart_hal.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "uart.h"
+// Backwards compatibility for when MICROPY_HW_UART_REPL was a ESP-IDF UART
+// driver enum. Only UART_NUM_0 was supported with that version of the driver.
+#define UART_NUM_0 0
+
STATIC void uart_irq_handler(void *arg);
+// Declaring the HAL structure on the stack saves a tiny amount of static RAM
+#define REPL_HAL_DEFN() { .dev = UART_LL_GET_HW(MICROPY_HW_UART_REPL) }
+
+// RXFIFO Full interrupt threshold. Set the same as the ESP-IDF UART driver
+#define RXFIFO_FULL_THR (SOC_UART_FIFO_LEN - 8)
+
+// RXFIFO RX timeout threshold. This is in bit periods, so 10==one byte. Same as ESP-IDF UART driver.
+#define RXFIFO_RX_TIMEOUT (10)
+
void uart_stdout_init(void) {
- uart_config_t uartcfg = {
- .baud_rate = MICROPY_HW_UART_REPL_BAUD,
- .data_bits = UART_DATA_8_BITS,
- .parity = UART_PARITY_DISABLE,
- .stop_bits = UART_STOP_BITS_1,
- .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
- .rx_flow_ctrl_thresh = 0
- };
- uart_param_config(MICROPY_HW_UART_REPL, &uartcfg);
-
- const uint32_t rxbuf = 129; // IDF requires > 128 min
- const uint32_t txbuf = 0;
-
- uart_driver_install(MICROPY_HW_UART_REPL, rxbuf, txbuf, 0, NULL, 0);
-
- uart_isr_handle_t handle;
- uart_isr_free(MICROPY_HW_UART_REPL);
- uart_isr_register(MICROPY_HW_UART_REPL, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle);
- uart_enable_rx_intr(MICROPY_HW_UART_REPL);
+ uart_hal_context_t repl_hal = REPL_HAL_DEFN();
+ uint32_t sclk_freq;
+
+ #if UART_SCLK_DEFAULT == SOC_MOD_CLK_APB
+ sclk_freq = APB_CLK_FREQ; // Assumes no frequency scaling
+ #else
+ // ESP32-H2 and ESP32-C2, I think
+ #error "This SoC uses a different default UART SCLK source, code needs updating."
+ #endif
+
+ uart_hal_init(&repl_hal, MICROPY_HW_UART_REPL); // Sets defaults: 8n1, no flow control
+ uart_hal_set_baudrate(&repl_hal, MICROPY_HW_UART_REPL_BAUD, sclk_freq);
+ uart_hal_rxfifo_rst(&repl_hal);
+ uart_hal_txfifo_rst(&repl_hal);
+
+ ESP_ERROR_CHECK(
+ esp_intr_alloc(uart_periph_signal[MICROPY_HW_UART_REPL].irq,
+ ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM,
+ uart_irq_handler,
+ NULL,
+ NULL)
+ );
+
+ // Enable RX interrupts
+ uart_hal_set_rxfifo_full_thr(&repl_hal, RXFIFO_FULL_THR);
+ uart_hal_set_rx_timeout(&repl_hal, RXFIFO_RX_TIMEOUT);
+ uart_hal_ena_intr_mask(&repl_hal, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT);
}
int uart_stdout_tx_strn(const char *str, size_t len) {
+ uart_hal_context_t repl_hal = REPL_HAL_DEFN();
size_t remaining = len;
+ uint32_t written = 0;
// TODO add a timeout
for (;;) {
- int ret = uart_tx_chars(MICROPY_HW_UART_REPL, str, remaining);
- if (ret == -1) {
- return -1;
- }
- remaining -= ret;
- if (remaining <= 0) {
+ uart_hal_write_txfifo(&repl_hal, (const void *)str, remaining, &written);
+
+ if (written >= remaining) {
break;
}
- str += ret;
+ remaining -= written;
+ str += written;
ulTaskNotifyTake(pdFALSE, 1);
}
- return len - remaining;
+ return len;
}
// all code executed in ISR must be in IRAM, and any const data must be in DRAM
STATIC void IRAM_ATTR uart_irq_handler(void *arg) {
- volatile uart_dev_t *uart = &UART0;
- #if CONFIG_IDF_TARGET_ESP32S3
- uart->int_clr.rxfifo_full_int_clr = 1;
- uart->int_clr.rxfifo_tout_int_clr = 1;
- #else
- uart->int_clr.rxfifo_full = 1;
- uart->int_clr.rxfifo_tout = 1;
- uart->int_clr.frm_err = 1;
- #endif
- while (uart->status.rxfifo_cnt) {
- #if CONFIG_IDF_TARGET_ESP32
- uint8_t c = uart->fifo.rw_byte;
- #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
- uint8_t c = READ_PERI_REG(UART_FIFO_AHB_REG(0)); // UART0
- #endif
- if (c == mp_interrupt_char) {
+ uint8_t rbuf[SOC_UART_FIFO_LEN];
+ int len;
+ uart_hal_context_t repl_hal = REPL_HAL_DEFN();
+
+ uart_hal_clr_intsts_mask(&repl_hal, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT | UART_INTR_FRAM_ERR);
+
+ len = uart_hal_get_rxfifo_len(&repl_hal);
+
+ uart_hal_read_rxfifo(&repl_hal, rbuf, &len);
+
+ for (int i = 0; i < len; i++) {
+ if (rbuf[i] == mp_interrupt_char) {
mp_sched_keyboard_interrupt();
} else {
// this is an inline function so will be in IRAM
- ringbuf_put(&stdin_ringbuf, c);
+ ringbuf_put(&stdin_ringbuf, rbuf[i]);
}
}
}
diff --git a/ports/esp32/uart.h b/ports/esp32/uart.h
index e3c7482e7b485..6410db24c9577 100644
--- a/ports/esp32/uart.h
+++ b/ports/esp32/uart.h
@@ -30,11 +30,11 @@
// Whether to enable the REPL on a UART.
#ifndef MICROPY_HW_ENABLE_UART_REPL
-#define MICROPY_HW_ENABLE_UART_REPL (!CONFIG_USB_ENABLED && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG)
+#define MICROPY_HW_ENABLE_UART_REPL (!CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG)
#endif
#ifndef MICROPY_HW_UART_REPL
-#define MICROPY_HW_UART_REPL (UART_NUM_0)
+#define MICROPY_HW_UART_REPL (0)
#endif
#ifndef MICROPY_HW_UART_REPL_BAUD
diff --git a/ports/esp32/usb.c b/ports/esp32/usb.c
index 5a613d24412c8..b9d99676d3c5c 100644
--- a/ports/esp32/usb.c
+++ b/ports/esp32/usb.c
@@ -28,15 +28,17 @@
#include "py/mphal.h"
#include "usb.h"
-#if CONFIG_USB_ENABLED
+#if CONFIG_USB_OTG_SUPPORTED
+#include "esp_timer.h"
+#ifndef NO_QSTR
#include "tinyusb.h"
#include "tusb_cdc_acm.h"
+#endif
#define CDC_ITF TINYUSB_CDC_ACM_0
-static uint8_t usb_rx_buf[CONFIG_USB_CDC_RX_BUFSIZE];
-static uint8_t usb_cdc_connected;
+static uint8_t usb_rx_buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE];
static void usb_callback_rx(int itf, cdcacm_event_t *event) {
// TODO: what happens if more chars come in during this function, are they lost?
@@ -59,36 +61,35 @@ static void usb_callback_rx(int itf, cdcacm_event_t *event) {
}
}
-void usb_callback_line_state_changed(int itf, cdcacm_event_t *event) {
- int dtr = event->line_state_changed_data.dtr;
- int rts = event->line_state_changed_data.rts;
- // If dtr && rts are both true, the CDC is connected to a HOST.
- usb_cdc_connected = dtr && rts;
-}
-
void usb_init(void) {
// Initialise the USB with defaults.
tinyusb_config_t tusb_cfg = {0};
ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
// Initialise the USB serial interface.
- tinyusb_config_cdcacm_t amc_cfg = {
+ tinyusb_config_cdcacm_t acm_cfg = {
.usb_dev = TINYUSB_USBDEV_0,
.cdc_port = CDC_ITF,
.rx_unread_buf_sz = 256,
.callback_rx = &usb_callback_rx,
- .callback_rx_wanted_char = NULL,
- .callback_line_state_changed = &usb_callback_line_state_changed,
- .callback_line_coding_changed = NULL
+ #ifdef MICROPY_HW_USB_CUSTOM_RX_WANTED_CHAR_CB
+ .callback_rx_wanted_char = &MICROPY_HW_USB_CUSTOM_RX_WANTED_CHAR_CB,
+ #endif
+ #ifdef MICROPY_HW_USB_CUSTOM_LINE_STATE_CB
+ .callback_line_state_changed = &MICROPY_HW_USB_CUSTOM_LINE_STATE_CB,
+ #endif
+ #ifdef MICROPY_HW_USB_CUSTOM_LINE_CODING_CB
+ .callback_line_coding_changed = &MICROPY_HW_USB_CUSTOM_LINE_CODING_CB,
+ #endif
};
- usb_cdc_connected = 0;
- ESP_ERROR_CHECK(tusb_cdc_acm_init(&amc_cfg));
+ ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));
}
void usb_tx_strn(const char *str, size_t len) {
// Write out the data to the CDC interface, but only while the USB host is connected.
- while (usb_cdc_connected && len) {
+ uint64_t timeout = esp_timer_get_time() + (uint64_t)(MICROPY_HW_USB_CDC_TX_TIMEOUT_MS * 1000);
+ while (tud_cdc_n_connected(CDC_ITF) && len && esp_timer_get_time() < timeout) {
size_t l = tinyusb_cdcacm_write_queue(CDC_ITF, (uint8_t *)str, len);
str += l;
len -= l;
@@ -96,4 +97,4 @@ void usb_tx_strn(const char *str, size_t len) {
}
}
-#endif // CONFIG_USB_ENABLED
+#endif // CONFIG_USB_OTG_SUPPORTED
diff --git a/ports/esp32/usb.h b/ports/esp32/usb.h
index a1037803337f8..a4c7d40701dfc 100644
--- a/ports/esp32/usb.h
+++ b/ports/esp32/usb.h
@@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_ESP32_USB_H
#define MICROPY_INCLUDED_ESP32_USB_H
+#define MICROPY_HW_USB_CDC_TX_TIMEOUT_MS (500)
+
void usb_init(void);
void usb_tx_strn(const char *str, size_t len);
diff --git a/ports/esp32/usb_serial_jtag.c b/ports/esp32/usb_serial_jtag.c
index a7d06a355a2ea..3289a1b5c0783 100644
--- a/ports/esp32/usb_serial_jtag.c
+++ b/ports/esp32/usb_serial_jtag.c
@@ -79,9 +79,9 @@ void usb_serial_jtag_tx_strn(const char *str, size_t len) {
if (l > USB_SERIAL_JTAG_PACKET_SZ_BYTES) {
l = USB_SERIAL_JTAG_PACKET_SZ_BYTES;
}
- portTickType start_tick = xTaskGetTickCount();
+ TickType_t start_tick = xTaskGetTickCount();
while (!usb_serial_jtag_ll_txfifo_writable()) {
- portTickType now_tick = xTaskGetTickCount();
+ TickType_t now_tick = xTaskGetTickCount();
if (!terminal_connected || now_tick > (start_tick + pdMS_TO_TICKS(200))) {
terminal_connected = false;
return;
diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile
index f70fbd2284063..1cdcafa031bc6 100644
--- a/ports/esp8266/Makefile
+++ b/ports/esp8266/Makefile
@@ -1,15 +1,21 @@
-# Select the board to build for: if not given on the command line,
-# then default to GENERIC.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to GENERIC.
BOARD ?= GENERIC
-
-# If the build directory is not given, make it reflect the board name.
-BUILD ?= build-$(BOARD)
-
BOARD_DIR ?= boards/$(BOARD)
+endif
+
ifeq ($(wildcard $(BOARD_DIR)/.),)
$(error Invalid BOARD specified: $(BOARD_DIR))
endif
+# If the build directory is not given, make it reflect the board name.
+BUILD ?= build-$(BOARD)
+
include ../../py/mkenv.mk
# Optional
@@ -21,7 +27,7 @@ QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h
# MicroPython feature configurations
MICROPY_ROM_TEXT_COMPRESSION ?= 1
-MICROPY_PY_USSL = 1
+MICROPY_PY_SSL = 1
MICROPY_SSL_AXTLS = 1
AXTLS_DEFS_EXTRA = -Dabort=abort_ -DRT_MAX_PLAIN_LENGTH=1024 -DRT_EXTRA=4096
BTREE_DEFS_EXTRA = -DDEFPSIZE=1024 -DMINCACHE=3
@@ -32,7 +38,7 @@ FROZEN_MANIFEST ?= boards/manifest.py
include $(TOP)/py/py.mk
include $(TOP)/extmod/extmod.mk
-GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx
+GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx
FWBIN = $(BUILD)/firmware-combined.bin
PORT ?= /dev/ttyACM0
@@ -57,19 +63,24 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
-Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \
-DLWIP_OPEN_SRC
-CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
- $(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR)
+CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
+ $(CFLAGS_XTENSA) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR)
LD_FILES ?= boards/esp8266_2m.ld
-LDFLAGS = -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref
-LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD)
+LDFLAGS += -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref
+LIBS += -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211
+
+ifeq ($(MICROPY_ESPNOW),1)
+CFLAGS += -DMICROPY_ESPNOW=1
+LIBS += -lespnow
+endif
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
# Debugging/Optimization
+CFLAGS += -g # always include debug info in the ELF
ifeq ($(DEBUG), 1)
-CFLAGS += -g
COPT = -O0
else
CFLAGS += -fdata-sections -ffunction-sections
@@ -100,18 +111,17 @@ SRC_C = \
machine_wdt.c \
machine_hspi.c \
modesp.c \
- modnetwork.c \
- modutime.c \
+ network_wlan.c \
ets_alt_task.c \
fatfs_port.c \
posix_helpers.c \
hspi.c \
$(wildcard $(BOARD_DIR)/*.c) \
- $(SRC_MOD)
-EXTMOD_SRC_C = $(addprefix extmod/,\
- modonewire.c \
- )
+ifeq ($(MICROPY_ESPNOW),1)
+SRC_C += \
+ modespnow.c
+endif
LIB_SRC_C = $(addprefix lib/,\
libm/math.c \
@@ -163,17 +173,15 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
SRC_S = \
gchelper.s \
-OBJ =
OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
-OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(SHARED_SRC_C) $(DRIVERS_SRC_C)
+SRC_QSTR += $(SRC_C) $(SHARED_SRC_C)
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
SRC_QSTR_AUTO_DEPS +=
@@ -192,12 +200,6 @@ $(BUILD)/uart.o: $(CONFVARS_FILE)
FROZEN_EXTRA_DEPS = $(CONFVARS_FILE)
-ifneq ($(FROZEN_MANIFEST),)
-CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
-CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
-CFLAGS += -DMICROPY_MODULE_FROZEN_STR
-endif
-
.PHONY: deploy
deploy: $(BUILD)/firmware-combined.bin
diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md
index 15ca7f891c263..1e0cae213937b 100644
--- a/ports/esp8266/README.md
+++ b/ports/esp8266/README.md
@@ -1,10 +1,9 @@
MicroPython port to ESP8266
===========================
-This is an experimental port of MicroPython for the WiFi modules based
-on Espressif ESP8266 chip.
-
-WARNING: The port is experimental and many APIs are subject to change.
+This is a port of MicroPython to the Espressif ESP8266 WiFi microcontroller.
+MicroPython runs on this chip without any underlying operating system, using
+the ESP8266 NONOS SDK.
Supported features include:
- REPL (Python prompt) over UART0.
@@ -27,52 +26,106 @@ Documentation is available at http://docs.micropython.org/en/latest/esp8266/quic
Build instructions
------------------
-You need the esp-open-sdk toolchain (which provides both the compiler and libraries), which
-you can obtain using one of the following two options:
+You need the esp-open-sdk toolchain, which provides both the compiler and libraries.
- - Use a Docker image with a pre-built toolchain (**recommended**).
- To use this, install Docker, then prepend
- `docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk ` to the start
- of the mpy-cross and firmware `make` commands below. This will run the commands using the
- toolchain inside the container but using the files on your local filesystem.
+There are two ways to do this:
+ - By running the toolchain in [Docker](https://www.docker.com/) (**recommended**).
+ - By installing a pre-built toolchain and adding it to your `$PATH`.
- - or, install the esp-open-sdk directly on your PC, which can be found at
- . Clone this repository and
- run `make` in its directory to build and install the SDK locally. Make sure
- to add toolchain bin directory to your PATH. Read esp-open-sdk's README for
- additional important information on toolchain setup.
- If you use this approach, then the command below will work exactly.
+Regardless of which toolchain you use, the first step is to make sure required
+submodules are available:
-Add the external dependencies to the MicroPython repository checkout:
```bash
$ make -C ports/esp8266 submodules
```
+
See the README in the repository root for more information about external
dependencies.
-The MicroPython cross-compiler must be built to pre-compile some of the
-built-in scripts to bytecode. This can be done using:
+__Building with Docker__
+
+Once you have installed Docker, you can run all of the following build
+commands inside the Docker container by prefixing them with `docker
+run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk ...command...`.
+This will automatically download the Docker image provided by @larsks which
+contains the full toolchain and SDK.
+
+Then you need to compile the MicroPython cross-compiler (`mpy-cross`). From
+the root of this repository, run:
+
```bash
-$ make -C mpy-cross
+$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -C mpy-cross
+```
+
+**Note:** The `mpy-cross` binary will likely only work inside the Docker
+container. This will not be a problem if you're only building ESP8266
+firmware, but if you're also working on other ports then you will need to
+recompile for your host when switching between ports. To avoid this, use
+the local toolchain instead.
+
+Then to compile the ESP8266 firmware:
+
```
-(Prepend the Docker command if using Docker, see above)
+$ cd ports/esp8266
+$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -j BOARD=GENERIC
+```
+
+This will produce binary images in the `build-GENERIC/` subdirectory.
+Substitute the board for whichever board you're using.
+
+__Building with a local toolchain__
+
+First download the pre-built toolchain (thanks to @jepler from Adafruit). You
+will need to find somewhere to put it in your filesystem, e.g. `~/espressif`.
+Create that directory first if necessary.
+
+```
+$ cd ~/espressif # Change as necessary
+$ wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz
+$ tar zxvf xtensa-lx106-elf-standalone.tar.gz
+$ rm xtensa-lx106-elf/bin/esptool.py # Use system version of esptool.py instead.
+```
+
+Then append this to your `$PATH` variable so the compiler binaries can be
+found:
+
+```
+$ export "PATH=$HOME/espressif/xtensa-lx106-elf/bin/:$PATH"
+```
+
+(You will need to do this each time you start a new terminal)
+
+Then you need to compile the MicroPython cross-compiler (`mpy-cross`). From
+the root of this repository, run:
-Then, to build MicroPython for the ESP8266, just run:
```bash
+$ make -C mpy-cross
+```
+
+Then to compile the ESP8266 firmware:
+
+```
$ cd ports/esp8266
-$ make
+$ make -j BOARD=GENERIC
```
-(Prepend the Docker command if using Docker, see above)
-This will produce binary images in the `build-GENERIC/` subdirectory. If you
-install MicroPython to your module for the first time, or after installing any
-other firmware, you should erase flash completely:
+This will produce binary images in the `build-GENERIC/` subdirectory.
+Substitute the board for whichever board you're using.
+
+
+Installing MicroPython
+----------------------
+
+To communicate with the board you will need to install `esptool.py`. This can
+be obtained from your system package manager or from PyPi via `pip`.
+
+If you install MicroPython to your module for the first time, or after
+installing any other firmware, you should erase flash completely:
+
```bash
$ esptool.py --port /dev/ttyXXX erase_flash
```
-You can install esptool.py either from your system package manager or from PyPi.
-
Erasing the flash is also useful as a troubleshooting measure, if a module doesn't
behave as expected.
@@ -80,7 +133,9 @@ To flash MicroPython image to your ESP8266, use:
```bash
$ make deploy
```
-(This should not be run inside Docker as it will need access to the serial port.)
+
+(If using the Docker instructions above, do not run this command via Docker as
+it will need access to the serial port. Run it directly instead.)
This will use the `esptool.py` script to download the images. You must have
your ESP module in the bootloader mode, and connected to a serial port on your PC.
@@ -144,20 +199,22 @@ Python prompt over WiFi, connecting through a browser.
- GitHub repository https://github.com/micropython/webrepl.
Please follow the instructions there.
-__upip__
+__mip__
-The ESP8266 port comes with builtin `upip` package manager, which can
-be used to install additional modules (see the main README for more
-information):
+The ESP8266 port comes with the built-in `mip` package manager, which can
+be used to install additional modules:
```
->>> import upip
->>> upip.install("micropython-pystone_lowmem")
+>>> import mip
+>>> mip.install("hmac")
[...]
->>> import pystone_lowmem
->>> pystone_lowmem.main()
+>>> import hmac
+>>> hmac.new(b"1234567890", msg="hello world").hexdigest()
```
+See [Package management](https://docs.micropython.org/en/latest/reference/packages.html) for more
+information about `mip`.
+
Downloading and installing packages may requite a lot of free memory,
if you get an error, retry immediately after the hard reset.
diff --git a/ports/esp8266/boards/GENERIC/board.md b/ports/esp8266/boards/GENERIC/board.md
index b93ca509f89c7..fa0cf410d66fa 100644
--- a/ports/esp8266/boards/GENERIC/board.md
+++ b/ports/esp8266/boards/GENERIC/board.md
@@ -6,7 +6,7 @@ Note: v1.12-334 and newer (including v1.13) require an ESP8266 module with
2MiB of flash or more, and use littlefs as the filesystem by default. When
upgrading from older firmware please backup your files first, and either
erase all flash before upgrading, or after upgrading execute
-`uos.VfsLfs2.mkfs(bdev)`.
+`os.VfsLfs2.mkfs(bdev)`.
### OTA builds
Over-The-Air (OTA) builds of the ESP8266 firmware are also provided.
diff --git a/ports/esp8266/boards/GENERIC/manifest.py b/ports/esp8266/boards/GENERIC/manifest.py
index 9ce3ffe3aae15..fd9c41dc5423f 100644
--- a/ports/esp8266/boards/GENERIC/manifest.py
+++ b/ports/esp8266/boards/GENERIC/manifest.py
@@ -1,21 +1,19 @@
# base modules
include("$(PORT_DIR)/boards/manifest.py")
-# uasyncio
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
+# asyncio
+include("$(MPY_DIR)/extmod/asyncio")
# drivers
-freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
+require("ssd1306")
-# Libraries from micropython-lib, include only if the library directory exists
-if os.path.isdir(convert_path("$(MPY_LIB_DIR)")):
- # file utilities
- freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")
+# micropython-lib: file utilities
+require("upysh")
- # requests
- freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
- freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py")
+# micropython-lib: requests
+require("urequests")
+require("urllib.urequest")
- # umqtt
- freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
- freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")
+# micropython-lib: umqtt
+require("umqtt.simple")
+require("umqtt.robust")
diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.h b/ports/esp8266/boards/GENERIC/mpconfigboard.h
index 1d9b8e6f70dd3..52c93f83a3684 100644
--- a/ports/esp8266/boards/GENERIC/mpconfigboard.h
+++ b/ports/esp8266/boards/GENERIC/mpconfigboard.h
@@ -11,4 +11,4 @@
#define MICROPY_READER_VFS (MICROPY_VFS)
#define MICROPY_VFS (1)
-#define MICROPY_PY_UCRYPTOLIB (1)
+#define MICROPY_PY_CRYPTOLIB (1)
diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.mk b/ports/esp8266/boards/GENERIC/mpconfigboard.mk
index 6861317218b37..8d7babdc84483 100644
--- a/ports/esp8266/boards/GENERIC/mpconfigboard.mk
+++ b/ports/esp8266/boards/GENERIC/mpconfigboard.mk
@@ -1,5 +1,6 @@
LD_FILES = boards/esp8266_2m.ld
+MICROPY_ESPNOW ?= 1
MICROPY_PY_BTREE ?= 1
MICROPY_VFS_FAT ?= 1
MICROPY_VFS_LFS2 ?= 1
diff --git a/ports/esp8266/boards/GENERIC_1M/board.md b/ports/esp8266/boards/GENERIC_1M/board.md
index 4a0e677078713..17cc6e3a6bdf0 100644
--- a/ports/esp8266/boards/GENERIC_1M/board.md
+++ b/ports/esp8266/boards/GENERIC_1M/board.md
@@ -2,4 +2,4 @@ The following are daily builds of the ESP8266 firmware tailored for modules with
only 1MiB of flash. This firmware uses littlefs as the filesystem.
When upgrading from older firmware that uses a FAT filesystem please backup your files
first, and either erase all flash before upgrading, or after upgrading execute
-`uos.VfsLfs2.mkfs(bdev)`.
+`os.VfsLfs2.mkfs(bdev)`.
diff --git a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h
index 10e8adcda7ecc..41752e692b315 100644
--- a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h
+++ b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h
@@ -12,5 +12,6 @@
#define MICROPY_VFS (1)
#define MICROPY_PY_FSTRINGS (0)
-#define MICROPY_PY_UASYNCIO (0)
-#define MICROPY_PY_UCRYPTOLIB (1)
+#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
+#define MICROPY_PY_ASYNCIO (0)
+#define MICROPY_PY_CRYPTOLIB (1)
diff --git a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.mk b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.mk
index fdbb0d82451e7..adc31702e0de7 100644
--- a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.mk
+++ b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.mk
@@ -1,4 +1,5 @@
LD_FILES = boards/esp8266_1m.ld
+MICROPY_ESPNOW ?= 1
MICROPY_PY_BTREE ?= 1
MICROPY_VFS_LFS2 ?= 1
diff --git a/ports/esp8266/boards/GENERIC_512K/manifest.py b/ports/esp8266/boards/GENERIC_512K/manifest.py
index ee148c80892d8..15f6cffc3f94a 100644
--- a/ports/esp8266/boards/GENERIC_512K/manifest.py
+++ b/ports/esp8266/boards/GENERIC_512K/manifest.py
@@ -1,6 +1,9 @@
-freeze("$(BOARD_DIR)", "_boot.py", opt=3)
-freeze("$(PORT_DIR)/modules", ("apa102.py", "ntptime.py", "port_diag.py"))
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-freeze("$(MPY_DIR)/drivers/onewire")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-include("$(MPY_DIR)/drivers/neopixel/manifest.py")
+module("_boot.py", opt=3)
+module("apa102.py", base_path="$(PORT_DIR)/modules", opt=3)
+module("port_diag.py", base_path="$(PORT_DIR)/modules", opt=3)
+require("ntptime")
+require("dht")
+require("onewire")
+require("ds18x20")
+require("webrepl")
+require("neopixel")
diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h
index ef37e22fb6c71..c29e23d5ad114 100644
--- a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h
+++ b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h
@@ -6,7 +6,8 @@
#define MICROPY_PY_FSTRINGS (0)
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0)
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
+#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
#define MICROPY_PY_SYS_STDIO_BUFFER (0)
-#define MICROPY_PY_UASYNCIO (0)
-#define MICROPY_PY_URE_SUB (0)
+#define MICROPY_PY_ASYNCIO (0)
+#define MICROPY_PY_RE_SUB (0)
#define MICROPY_PY_FRAMEBUF (0)
diff --git a/ports/esp8266/boards/esp8266_common.ld b/ports/esp8266/boards/esp8266_common.ld
index c2d62e9dd4ce6..083e84d9afe5c 100644
--- a/ports/esp8266/boards/esp8266_common.ld
+++ b/ports/esp8266/boards/esp8266_common.ld
@@ -83,6 +83,7 @@ SECTIONS
*libnet80211.a:(.literal.* .text.*)
*libwpa.a:(.literal.* .text.*)
*libwpa2.a:(.literal.* .text.*)
+ *libespnow.a:(.literal.* .text.*)
/* we put some specific text in this section */
@@ -163,12 +164,11 @@ SECTIONS
*machine_hspi.o(.literal*, .text*)
*hspi.o(.literal*, .text*)
*modesp.o(.literal* .text*)
- *modnetwork.o(.literal* .text*)
- *moduos.o(.literal* .text*)
- *modutime.o(.literal* .text*)
+ *modos.o(.literal* .text*)
*modlwip.o(.literal* .text*)
*modsocket.o(.literal* .text*)
*modonewire.o(.literal* .text*)
+ *network_wlan.o(.literal* .text*)
*esp_mphal.o(.literal* .text*)
/* we put as much rodata as possible in this section */
diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py
index 598572d62ad48..17f58feac88ae 100644
--- a/ports/esp8266/boards/manifest.py
+++ b/ports/esp8266/boards/manifest.py
@@ -1,6 +1,7 @@
freeze("$(PORT_DIR)/modules")
-freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py"))
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-freeze("$(MPY_DIR)/drivers/onewire")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-include("$(MPY_DIR)/drivers/neopixel/manifest.py")
+# require("aioespnow")
+require("bundle-networking")
+require("dht")
+require("ds18x20")
+require("neopixel")
+require("onewire")
diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c
index 3cb4807333c4a..7606bd4f63131 100644
--- a/ports/esp8266/esp_mphal.c
+++ b/ports/esp8266/esp_mphal.c
@@ -62,6 +62,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) {
ret |= MP_STREAM_POLL_RD;
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ ret |= mp_os_dupterm_poll(poll_flags);
+ }
return ret;
}
@@ -92,7 +95,7 @@ void mp_hal_debug_str(const char *str) {
#endif
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
- mp_uos_dupterm_tx_strn(str, len);
+ mp_os_dupterm_tx_strn(str, len);
}
void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) {
@@ -143,7 +146,7 @@ STATIC void dupterm_task_handler(os_event_t *evt) {
}
lock = 1;
while (1) {
- int c = mp_uos_dupterm_rx_chr();
+ int c = mp_os_dupterm_rx_chr();
if (c < 0) {
break;
}
diff --git a/ports/esp8266/esppwm.c b/ports/esp8266/esppwm.c
index 6164e2fc8b111..d7ac44a1786c8 100644
--- a/ports/esp8266/esppwm.c
+++ b/ports/esp8266/esppwm.c
@@ -165,7 +165,7 @@ pwm_start(void) {
}
}
PWM_DBG("2channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n", *local_channel, local_single[0].h_time, local_single[1].h_time, local_single[2].h_time, local_single[3].h_time);
- // step 4: cacl delt time
+ // step 4: calc delta time
for (i = *local_channel - 1; i > 0; i--) {
local_single[i].h_time -= local_single[i - 1].h_time;
}
@@ -389,7 +389,6 @@ pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func) {
pwm.duty[i] = 0;
pwm_gpio |= (1 << pin_num[channel]);
PIN_FUNC_SELECT(pin_mux, pin_func);
- GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel])), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel]))) & (~GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); // disable open drain;
pwm_channel_num++;
UNLOCK_PWM(critical); // leave critical
return channel;
diff --git a/ports/esp8266/help.c b/ports/esp8266/help.c
index a755a10a76173..a9cb27bad51c8 100644
--- a/ports/esp8266/help.c
+++ b/ports/esp8266/help.c
@@ -29,7 +29,8 @@
const char esp_help_text[] =
"Welcome to MicroPython!\n"
"\n"
- "For online docs please visit http://docs.micropython.org/en/latest/esp8266/ .\n"
+ "For online docs please visit http://docs.micropython.org/\n"
+ "\n"
"For diagnostic information to include in bug reports execute 'import port_diag'.\n"
"\n"
"Basic WiFi configuration:\n"
diff --git a/ports/esp8266/hspi_register.h b/ports/esp8266/hspi_register.h
index 50ef2fdca3e19..0d0cf2f747b81 100644
--- a/ports/esp8266/hspi_register.h
+++ b/ports/esp8266/hspi_register.h
@@ -79,7 +79,7 @@
#define SPI_MOSI_DELAY_NUM 0x00000007
#define SPI_MOSI_DELAY_NUM_S 23
#define SPI_MOSI_DELAY_MODE 0x00000003 //mode 0 : posedge; data set at positive edge of clk
- //mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk
+ //mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negative edge of clk
//mode 2 : Do not use this mode.
#define SPI_MOSI_DELAY_MODE_S 21
#define SPI_MISO_DELAY_NUM 0x00000007
diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c
index 471e14d8dfbed..f4fd32db9c765 100644
--- a/ports/esp8266/machine_adc.c
+++ b/ports/esp8266/machine_adc.c
@@ -89,10 +89,11 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = machine_adc_print,
- .make_new = machine_adc_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_adc_make_new,
+ print, machine_adc_print,
+ locals_dict, &machine_adc_locals_dict
+ );
diff --git a/ports/esp8266/machine_hspi.c b/ports/esp8266/machine_hspi.c
index 3ff76f5a02e04..2edb294adeff6 100644
--- a/ports/esp8266/machine_hspi.c
+++ b/ports/esp8266/machine_hspi.c
@@ -175,13 +175,14 @@ STATIC const mp_machine_spi_p_t machine_hspi_p = {
.transfer = machine_hspi_transfer,
};
-const mp_obj_type_t machine_hspi_type = {
- { &mp_type_type },
- .name = MP_QSTR_HSPI,
- .print = machine_hspi_print,
- .make_new = machine_hspi_make_new,
- .protocol = &machine_hspi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_hspi_type,
+ MP_QSTR_HSPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hspi_make_new,
+ print, machine_hspi_print,
+ protocol, &machine_hspi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_SPI
diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c
index 419ee87a7332b..344197da94720 100644
--- a/ports/esp8266/machine_pin.c
+++ b/ports/esp8266/machine_pin.c
@@ -46,13 +46,15 @@
(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)) & ~GPIO_PIN_INT_TYPE_MASK) \
| GPIO_PIN_INT_TYPE_SET(trig))) \
-#define GPIO_MODE_INPUT (0)
-#define GPIO_MODE_OUTPUT (1)
-#define GPIO_MODE_OPEN_DRAIN (2) // synthesised
-#define GPIO_PULL_NONE (0)
-#define GPIO_PULL_UP (1)
-// Removed in SDK 1.1.0
-// #define GPIO_PULL_DOWN (2)
+#define ENABLE_OPEN_DRAIN(phys_port) \
+ (GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port)), \
+ GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port))) \
+ | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)))
+
+#define DISABLE_OPEN_DRAIN(phys_port) \
+ (GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port)), \
+ GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port))) \
+ & ~GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))) \
typedef struct _pin_irq_obj_t {
mp_obj_base_t base;
@@ -84,7 +86,7 @@ const pyb_pin_obj_t pyb_pin_obj[16 + 1] = {
{{&pyb_pin_type}, 16, -1, -1},
};
-STATIC uint8_t pin_mode[16 + 1];
+uint8_t pin_mode[16 + 1];
// forward declaration
STATIC const pin_irq_obj_t pin_irq_obj[16];
@@ -120,11 +122,22 @@ void MP_FASTCODE(pin_intr_handler_part2)(uint32_t status) {
}
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) {
- if (mp_obj_get_type(pin_in) != &pyb_pin_type) {
- mp_raise_ValueError(MP_ERROR_TEXT("expecting a pin"));
+ if (mp_obj_is_type(pin_in, &pyb_pin_type)) {
+ return pin_in;
}
- pyb_pin_obj_t *self = pin_in;
- return self;
+ // Get the wanted pin object.
+ if (mp_obj_is_small_int(pin_in)) {
+ int wanted_pin = mp_obj_get_int(pin_in);
+ if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(pyb_pin_obj)) {
+ pyb_pin_obj_t *pin = (pyb_pin_obj_t *)&pyb_pin_obj[wanted_pin];
+ if (pin->base.type != NULL) {
+ return pin;
+ }
+ }
+ }
+ // At this place a check for named pins may be added.
+ //
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
}
uint mp_obj_get_pin(mp_obj_t pin_in) {
@@ -173,9 +186,7 @@ void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin_id) {
ETS_GPIO_INTR_DISABLE();
PIN_FUNC_SELECT(pin->periph, pin->func);
- GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port)),
- GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port)))
- | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); // open drain
+ ENABLE_OPEN_DRAIN(pin->phys_port);
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS,
GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << pin->phys_port));
ETS_GPIO_INTR_ENABLE();
@@ -279,6 +290,7 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, size_t n_args, cons
mp_raise_ValueError(MP_ERROR_TEXT("Pin(16) doesn't support pull"));
}
} else {
+ DISABLE_OPEN_DRAIN(self->phys_port);
PIN_FUNC_SELECT(self->periph, self->func);
#if 0
// Removed in SDK 1.1.0
@@ -309,14 +321,7 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted pin object
- int wanted_pin = mp_obj_get_int(args[0]);
- pyb_pin_obj_t *pin = NULL;
- if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(pyb_pin_obj)) {
- pin = (pyb_pin_obj_t *)&pyb_pin_obj[wanted_pin];
- }
- if (pin == NULL || pin->base.type == NULL) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
- }
+ pyb_pin_obj_t *pin = mp_obj_get_pin_obj(args[0]);
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
@@ -450,15 +455,16 @@ STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
-const mp_obj_type_t pyb_pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = pyb_pin_print,
- .make_new = mp_pin_make_new,
- .call = pyb_pin_call,
- .protocol = &pin_pin_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, pyb_pin_print,
+ call, pyb_pin_call,
+ protocol, &pin_pin_p,
+ locals_dict, &pyb_pin_locals_dict
+ );
/******************************************************************************/
// Pin IRQ object
@@ -509,9 +515,12 @@ STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table);
-STATIC const mp_obj_type_t pin_irq_type = {
- { &mp_type_type },
- .name = MP_QSTR_IRQ,
- .call = pin_irq_call,
- .locals_dict = (mp_obj_dict_t *)&pin_irq_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pin_irq_type,
+ MP_QSTR_IRQ,
+ MP_TYPE_FLAG_NONE,
+ call, pin_irq_call,
+ locals_dict, &pin_irq_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pin_irq_handler[16]);
diff --git a/ports/esp8266/machine_pwm.c b/ports/esp8266/machine_pwm.c
index 00547195f9a9f..58c8fa915fd56 100644
--- a/ports/esp8266/machine_pwm.c
+++ b/ports/esp8266/machine_pwm.c
@@ -25,6 +25,7 @@
*/
#include "py/runtime.h"
+#include "py/mphal.h"
#include "modmachine.h"
#include "esppwm.h"
@@ -34,8 +35,11 @@ typedef struct _machine_pwm_obj_t {
pyb_pin_obj_t *pin;
uint8_t active;
uint8_t channel;
+ int32_t duty_ns;
} machine_pwm_obj_t;
+STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty);
+
STATIC bool pwm_inited = false;
/******************************************************************************/
@@ -52,10 +56,12 @@ STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_p
}
STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_freq, ARG_duty };
+ enum { ARG_freq, ARG_duty, ARG_duty_u16, ARG_duty_ns };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_duty, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_u16, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_ns, MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
@@ -73,6 +79,19 @@ STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, c
if (args[ARG_duty].u_int != -1) {
pwm_set_duty(args[ARG_duty].u_int, self->channel);
}
+ if (args[ARG_duty_u16].u_int != -1) {
+ pwm_set_duty(args[ARG_duty_u16].u_int * 1000 / 65536, self->channel);
+ }
+ if (args[ARG_duty_ns].u_int != -1) {
+ uint32_t freq = pwm_get_freq(0);
+ if (freq > 0) {
+ pwm_set_duty((uint64_t)args[ARG_duty_ns].u_int * freq / 1000000, self->channel);
+ }
+ }
+
+ if (pin_mode[self->pin->phys_port] == GPIO_MODE_OPEN_DRAIN) {
+ mp_hal_pin_open_drain(self->pin->phys_port);
+ }
pwm_start();
}
@@ -86,6 +105,7 @@ STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
self->pin = pin;
self->active = 0;
self->channel = -1;
+ self->duty_ns = -1;
// start the PWM subsystem if it's not already running
if (!pwm_inited) {
@@ -113,22 +133,57 @@ STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
pwm_set_freq(freq, 0);
- pwm_start();
+ if (self->duty_ns != -1) {
+ mp_machine_pwm_duty_set_ns(self, self->duty_ns);
+ } else {
+ pwm_start();
+ }
}
-STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self) {
+STATIC void set_active(machine_pwm_obj_t *self, bool set_pin) {
if (!self->active) {
pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func);
self->active = 1;
+ if (set_pin && pin_mode[self->pin->phys_port] == GPIO_MODE_OPEN_DRAIN) {
+ mp_hal_pin_open_drain(self->pin->phys_port);
+ }
}
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self) {
+ set_active(self, true);
return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel));
}
STATIC void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty) {
- if (!self->active) {
- pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func);
- self->active = 1;
- }
+ set_active(self, false);
+ self->duty_ns = -1;
pwm_set_duty(duty, self->channel);
pwm_start();
}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) {
+ set_active(self, true);
+ return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel) * 65536 / 1024);
+}
+
+STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty) {
+ set_active(self, false);
+ self->duty_ns = -1;
+ pwm_set_duty(duty * 1024 / 65536, self->channel);
+ pwm_start();
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) {
+ set_active(self, true);
+ uint32_t freq = pwm_get_freq(0);
+ return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel) * 976563 / freq);
+}
+
+STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty) {
+ set_active(self, false);
+ self->duty_ns = duty;
+ uint32_t freq = pwm_get_freq(0);
+ pwm_set_duty(duty * freq / 976562, self->channel); // 1e9/1024 = 976562.5
+ pwm_start();
+}
diff --git a/ports/esp8266/machine_rtc.c b/ports/esp8266/machine_rtc.c
index 38049ce724939..d8cbb8f8247dc 100644
--- a/ports/esp8266/machine_rtc.c
+++ b/ports/esp8266/machine_rtc.c
@@ -262,9 +262,10 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
-const mp_obj_type_t pyb_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = pyb_rtc_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_rtc_make_new,
+ locals_dict, &pyb_rtc_locals_dict
+ );
diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c
index b774419d2d321..873b12b2fab9c 100644
--- a/ports/esp8266/machine_uart.c
+++ b/ports/esp8266/machine_uart.c
@@ -231,10 +231,20 @@ STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return uart_txdone(self->uart_id) == true ? mp_const_true : mp_const_false;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
@@ -305,6 +315,20 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
if ((flags & MP_STREAM_POLL_WR) && uart_tx_any_room(self->uart_id)) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint64_t timeout = (uint64_t)(3 + 127) * 13000000ll * 2 / self->baudrate
+ + system_get_time();
+ do {
+ if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (system_get_time() < timeout);
+
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -319,13 +343,14 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t pyb_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = pyb_uart_print,
- .make_new = pyb_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, pyb_uart_make_new,
+ print, pyb_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &pyb_uart_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(byte * uart0_rxbuf);
diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c
index b06e752277288..39a5d51119efb 100644
--- a/ports/esp8266/machine_wdt.c
+++ b/ports/esp8266/machine_wdt.c
@@ -69,9 +69,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
-const mp_obj_type_t esp_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = machine_wdt_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_wdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_wdt_make_new,
+ locals_dict, &machine_wdt_locals_dict
+ );
diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c
index ded5e58abf7ab..3083fe364e77c 100644
--- a/ports/esp8266/main.c
+++ b/ports/esp8266/main.c
@@ -45,6 +45,10 @@
#include "gccollect.h"
#include "user_interface.h"
+#if MICROPY_ESPNOW
+#include "modespnow.h"
+#endif
+
STATIC char heap[38 * 1024];
STATIC void mp_reset(void) {
@@ -68,13 +72,17 @@ STATIC void mp_reset(void) {
mp_obj_t args[2];
args[0] = MP_OBJ_NEW_SMALL_INT(0);
args[1] = MP_OBJ_NEW_SMALL_INT(115200);
- args[0] = pyb_uart_type.make_new(&pyb_uart_type, 2, 0, args);
+ args[0] = MP_OBJ_TYPE_GET_SLOT(&pyb_uart_type, make_new)(&pyb_uart_type, 2, 0, args);
args[1] = MP_OBJ_NEW_SMALL_INT(1);
- mp_uos_dupterm_obj.fun.var(2, args);
+ mp_os_dupterm_obj.fun.var(2, args);
}
+ #if MICROPY_ESPNOW
+ espnow_deinit(mp_const_none);
+ #endif
+
#if MICROPY_MODULE_FROZEN
- pyexec_frozen_module("_boot.py");
+ pyexec_frozen_module("_boot.py", false);
pyexec_file_if_exists("boot.py");
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
pyexec_file_if_exists("main.py");
diff --git a/ports/esp8266/makeimg.py b/ports/esp8266/makeimg.py
index 4d31cc0799604..662e6f83204a3 100644
--- a/ports/esp8266/makeimg.py
+++ b/ports/esp8266/makeimg.py
@@ -14,7 +14,6 @@
md5 = hashlib.md5()
with open(sys.argv[3], "wb") as fout:
-
with open(sys.argv[1], "rb") as f:
data_flash = f.read()
fout.write(data_flash)
diff --git a/ports/esp8266/modesp.c b/ports/esp8266/modesp.c
index 645de7fe9b0a5..95595faebc792 100644
--- a/ports/esp8266/modesp.c
+++ b/ports/esp8266/modesp.c
@@ -31,7 +31,6 @@
#include "py/persistentcode.h"
#include "py/mperrno.h"
#include "py/mphal.h"
-#include "drivers/dht/dht.h"
#include "uart.h"
#include "user_interface.h"
#include "mem.h"
@@ -202,8 +201,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_check_fw_obj, esp_check_fw);
STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
- esp_apa102_write(mp_obj_get_pin_obj(clockPin)->phys_port,
- mp_obj_get_pin_obj(dataPin)->phys_port,
+ esp_apa102_write(mp_obj_get_pin(clockPin),
+ mp_obj_get_pin(dataPin),
(uint8_t *)bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@@ -355,7 +354,6 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
#if MICROPY_ESP8266_APA102
{ MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) },
#endif
- { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_freemem), MP_ROM_PTR(&esp_freemem_obj) },
{ MP_ROM_QSTR(MP_QSTR_meminfo), MP_ROM_PTR(&esp_meminfo_obj) },
{ MP_ROM_QSTR(MP_QSTR_check_fw), MP_ROM_PTR(&esp_check_fw_obj) },
diff --git a/ports/esp8266/modespnow.c b/ports/esp8266/modespnow.c
new file mode 100644
index 0000000000000..1f89204676c03
--- /dev/null
+++ b/ports/esp8266/modespnow.c
@@ -0,0 +1,507 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017-2020 Nick Moore
+ * Copyright (c) 2018 shawwwn
+ * Copyright (c) 2020-2021 Glenn Moloney @glenn20
+ *
+ * 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/runtime.h"
+
+#if MICROPY_ESPNOW
+
+#include "c_types.h"
+#include "espnow.h"
+
+#include "py/mphal.h"
+#include "py/mperrno.h"
+#include "py/qstr.h"
+#include "py/objstr.h"
+#include "py/objarray.h"
+#include "py/stream.h"
+#include "py/binary.h"
+#include "py/ringbuf.h"
+
+#include "mpconfigport.h"
+
+#include "modespnow.h"
+
+// For the esp8266
+#define ESP_NOW_MAX_DATA_LEN (250)
+#define ESP_NOW_KEY_LEN (16)
+#define ESP_NOW_ETH_ALEN (6)
+#define ESP_NOW_SEND_SUCCESS (0)
+#define ESP_ERR_ESPNOW_NO_MEM (-77777)
+#define ESP_OK (0)
+#define ESP_NOW_MAX_TOTAL_PEER_NUM (20)
+#define ESP_NOW_MAX_ENCRYPT_PEER_NUM (6)
+#define ESP_ERR_ESPNOW_NOT_INIT (0x300 + 100 + 1)
+typedef int esp_err_t;
+
+static const uint8_t ESPNOW_MAGIC = 0x99;
+
+// Use this for peeking at the header of the next packet in the buffer.
+typedef struct {
+ uint8_t magic; // = ESPNOW_MAGIC
+ uint8_t msg_len; // Length of the message
+} __attribute__((packed)) espnow_hdr_t;
+
+// ESPNow packet format for the receive buffer.
+typedef struct {
+ espnow_hdr_t hdr; // The header
+ uint8_t peer[6]; // Peer address
+ uint8_t msg[0]; // Message is up to 250 bytes
+} __attribute__((packed)) espnow_pkt_t;
+
+// The maximum length of an espnow packet (bytes)
+static const size_t MAX_PACKET_LEN = (
+ sizeof(espnow_pkt_t) + ESP_NOW_MAX_DATA_LEN);
+
+// Enough for 2 full-size packets: 2 * (6 + 2 + 250) = 516 bytes
+// Will allocate an additional 7 bytes for buffer overhead
+#define DEFAULT_RECV_BUFFER_SIZE \
+ (2 * (sizeof(espnow_pkt_t) + ESP_NOW_MAX_DATA_LEN))
+
+// Default timeout (millisec) to wait for incoming ESPNow messages (5 minutes).
+#define DEFAULT_RECV_TIMEOUT_MS (5 * 60 * 1000)
+
+// Number of milliseconds to wait for pending responses to sent packets.
+// This is a fallback which should never be reached.
+#define PENDING_RESPONSES_TIMEOUT_MS 100
+
+// The data structure for the espnow_singleton.
+typedef struct _esp_espnow_obj_t {
+ mp_obj_base_t base;
+ ringbuf_t *recv_buffer; // A buffer for received packets
+ size_t recv_buffer_size; // Size of recv buffer
+ size_t recv_timeout_ms; // Timeout for irecv()
+ size_t tx_packets; // Count of sent packets
+ volatile size_t tx_responses; // # of sent packet responses received
+ volatile size_t tx_failures; // # of sent packet responses failed
+} esp_espnow_obj_t;
+
+// Initialised below.
+const mp_obj_type_t esp_espnow_type;
+
+static esp_espnow_obj_t espnow_singleton = {
+ .base.type = &esp_espnow_type,
+ .recv_buffer = NULL,
+ .recv_buffer_size = DEFAULT_RECV_BUFFER_SIZE,
+ .recv_timeout_ms = DEFAULT_RECV_TIMEOUT_MS,
+};
+
+// ### Initialisation and Config functions
+//
+
+static void check_esp_err(int e) {
+ if (e != 0) {
+ mp_raise_OSError(e);
+ }
+}
+
+// Return a pointer to the ESPNow module singleton
+// If state == INITIALISED check the device has been initialised.
+// Raises OSError if not initialised and state == INITIALISED.
+static esp_espnow_obj_t *_get_singleton() {
+ return &espnow_singleton;
+}
+
+static esp_espnow_obj_t *_get_singleton_initialised() {
+ esp_espnow_obj_t *self = _get_singleton();
+ if (self->recv_buffer == NULL) {
+ // Throw an espnow not initialised error
+ check_esp_err(ESP_ERR_ESPNOW_NOT_INIT);
+ }
+ return self;
+}
+
+// Allocate and initialise the ESPNow module as a singleton.
+// Returns the initialised espnow_singleton.
+STATIC mp_obj_t espnow_make_new(const mp_obj_type_t *type, size_t n_args,
+ size_t n_kw, const mp_obj_t *all_args) {
+
+ return _get_singleton();
+}
+
+// Forward declare the send and recv ESPNow callbacks
+STATIC void send_cb(uint8_t *mac_addr, uint8_t status);
+
+STATIC void recv_cb(uint8_t *mac_addr, uint8_t *data, uint8_t len);
+
+// ESPNow.deinit(): De-initialise the ESPNOW software stack, disable callbacks
+// and deallocate the recv data buffers.
+// Note: this function is called from main.c:mp_task() to cleanup before soft
+// reset, so cannot be declared STATIC and must guard against self == NULL;.
+mp_obj_t espnow_deinit(mp_obj_t _) {
+ esp_espnow_obj_t *self = _get_singleton();
+ if (self->recv_buffer != NULL) {
+ // esp_now_unregister_recv_cb();
+ esp_now_deinit();
+ self->recv_buffer->buf = NULL;
+ self->recv_buffer = NULL;
+ self->tx_packets = self->tx_responses;
+ }
+ MP_STATE_PORT(espnow_buffer) = NULL;
+ return mp_const_none;
+}
+
+// ESPNow.active(): Initialise the data buffers and ESP-NOW functions.
+// Initialise the Espressif ESPNOW software stack, register callbacks and
+// allocate the recv data buffers.
+// Returns True if interface is active, else False.
+STATIC mp_obj_t espnow_active(size_t n_args, const mp_obj_t *args) {
+ esp_espnow_obj_t *self = args[0];
+ if (n_args > 1) {
+ if (mp_obj_is_true(args[1])) {
+ if (self->recv_buffer == NULL) { // Already initialised
+ self->recv_buffer = m_new_obj(ringbuf_t);
+ ringbuf_alloc(self->recv_buffer, self->recv_buffer_size);
+ MP_STATE_PORT(espnow_buffer) = self->recv_buffer;
+ esp_now_init();
+ esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
+ esp_now_register_recv_cb(recv_cb);
+ esp_now_register_send_cb(send_cb);
+ }
+ } else {
+ espnow_deinit(self);
+ }
+ }
+ return mp_obj_new_bool(self->recv_buffer != NULL);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_active_obj, 1, 2, espnow_active);
+
+// ESPNow.config(): Initialise the data buffers and ESP-NOW functions.
+// Initialise the Espressif ESPNOW software stack, register callbacks and
+// allocate the recv data buffers.
+// Returns True if interface is active, else False.
+STATIC mp_obj_t espnow_config(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ esp_espnow_obj_t *self = _get_singleton();
+ enum { ARG_rxbuf, ARG_timeout_ms };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_timeout_ms, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ };
+ 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);
+ if (args[ARG_rxbuf].u_int >= 0) {
+ self->recv_buffer_size = args[ARG_rxbuf].u_int;
+ }
+ if (args[ARG_timeout_ms].u_int >= 0) {
+ self->recv_timeout_ms = args[ARG_timeout_ms].u_int;
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(espnow_config_obj, 1, espnow_config);
+
+// ### The ESP_Now send and recv callback routines
+//
+
+// Callback triggered when a sent packet is acknowledged by the peer (or not).
+// Just count the number of responses and number of failures.
+// These are used in the send()/write() logic.
+STATIC void send_cb(uint8_t *mac_addr, uint8_t status) {
+ esp_espnow_obj_t *self = _get_singleton();
+ self->tx_responses++;
+ if (status != ESP_NOW_SEND_SUCCESS) {
+ self->tx_failures++;
+ }
+}
+
+// Callback triggered when an ESP-Now packet is received.
+// Write the peer MAC address and the message into the recv_buffer as an
+// ESPNow packet.
+// If the buffer is full, drop the message and increment the dropped count.
+// Schedules the user callback if one has been registered (ESPNow.config()).
+STATIC void recv_cb(uint8_t *mac_addr, uint8_t *msg, uint8_t msg_len) {
+ esp_espnow_obj_t *self = _get_singleton();
+ ringbuf_t *buf = self->recv_buffer;
+ // TODO: Test this works with ">".
+ if (buf == NULL || sizeof(espnow_pkt_t) + msg_len >= ringbuf_free(buf)) {
+ return;
+ }
+ espnow_hdr_t header;
+ header.magic = ESPNOW_MAGIC;
+ header.msg_len = msg_len;
+
+ ringbuf_put_bytes(buf, (uint8_t *)&header, sizeof(header));
+ ringbuf_put_bytes(buf, mac_addr, ESP_NOW_ETH_ALEN);
+ ringbuf_put_bytes(buf, msg, msg_len);
+}
+
+// Return C pointer to byte memory string/bytes/bytearray in obj.
+// Raise ValueError if the length does not match expected len.
+static uint8_t *_get_bytes_len_rw(mp_obj_t obj, size_t len, mp_uint_t rw) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(obj, &bufinfo, rw);
+ if (bufinfo.len != len) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer length"));
+ }
+ return (uint8_t *)bufinfo.buf;
+}
+
+static uint8_t *_get_bytes_len(mp_obj_t obj, size_t len) {
+ return _get_bytes_len_rw(obj, len, MP_BUFFER_READ);
+}
+
+static uint8_t *_get_bytes_len_w(mp_obj_t obj, size_t len) {
+ return _get_bytes_len_rw(obj, len, MP_BUFFER_WRITE);
+}
+
+// ### Handling espnow packets in the recv buffer
+//
+
+// Copy data from the ring buffer - wait if buffer is empty up to timeout_ms
+// 0: Success
+// -1: Not enough data available to complete read (try again later)
+// -2: Requested read is larger than buffer - will never succeed
+static int ringbuf_get_bytes_wait(ringbuf_t *r, uint8_t *data, size_t len, mp_int_t timeout_ms) {
+ mp_uint_t start = mp_hal_ticks_ms();
+ int status = 0;
+ while (((status = ringbuf_get_bytes(r, data, len)) == -1)
+ && (timeout_ms < 0 || (mp_uint_t)(mp_hal_ticks_ms() - start) < (mp_uint_t)timeout_ms)) {
+ MICROPY_EVENT_POLL_HOOK;
+ }
+ return status;
+}
+
+// ESPNow.recvinto([timeout_ms, []]):
+// Returns a list of byte strings: (peer_addr, message) where peer_addr is
+// the MAC address of the sending peer.
+// Arguments:
+// timeout_ms: timeout in milliseconds (or None).
+// buffers: list of bytearrays to store values: [peer, message].
+// Default timeout is set with ESPNow.config(timeout=milliseconds).
+// Return (None, None) on timeout.
+STATIC mp_obj_t espnow_recvinto(size_t n_args, const mp_obj_t *args) {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+
+ size_t timeout_ms = ((n_args > 2 && args[2] != mp_const_none)
+ ? mp_obj_get_int(args[2]) : self->recv_timeout_ms);
+
+ mp_obj_list_t *list = MP_OBJ_TO_PTR(args[1]);
+ if (!mp_obj_is_type(list, &mp_type_list) || list->len < 2) {
+ mp_raise_ValueError(MP_ERROR_TEXT("ESPNow.recvinto(): Invalid argument"));
+ }
+ mp_obj_array_t *msg = MP_OBJ_TO_PTR(list->items[1]);
+ size_t msg_size = msg->len + msg->free;
+ if (mp_obj_is_type(msg, &mp_type_bytearray)) {
+ msg->len = msg_size; // Make all the space in msg array available
+ msg->free = 0;
+ }
+ uint8_t *peer_buf = _get_bytes_len_w(list->items[0], ESP_NOW_ETH_ALEN);
+ uint8_t *msg_buf = _get_bytes_len_w(msg, ESP_NOW_MAX_DATA_LEN);
+
+ // Read the packet header from the incoming buffer
+ espnow_hdr_t hdr;
+ if (ringbuf_get_bytes_wait(self->recv_buffer, (uint8_t *)&hdr, sizeof(hdr), timeout_ms) < 0) {
+ return MP_OBJ_NEW_SMALL_INT(0); // Timeout waiting for packet
+ }
+ int msg_len = hdr.msg_len;
+
+ // Check the message packet header format and read the message data
+ if (hdr.magic != ESPNOW_MAGIC
+ || msg_len > ESP_NOW_MAX_DATA_LEN
+ || ringbuf_get_bytes(self->recv_buffer, peer_buf, ESP_NOW_ETH_ALEN) < 0
+ || ringbuf_get_bytes(self->recv_buffer, msg_buf, msg_len) < 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("ESPNow.recv(): buffer error"));
+ }
+ if (mp_obj_is_type(msg, &mp_type_bytearray)) {
+ // Set the length of the message bytearray.
+ msg->len = msg_len;
+ msg->free = msg_size - msg_len;
+ }
+
+ return MP_OBJ_NEW_SMALL_INT(msg_len);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_recvinto_obj, 2, 3, espnow_recvinto);
+
+// Used by espnow_send() for sends() with sync==True.
+// Wait till all pending sent packet responses have been received.
+// ie. self->tx_responses == self->tx_packets.
+// Return the number of responses where status != ESP_NOW_SEND_SUCCESS.
+static void _wait_for_pending_responses(esp_espnow_obj_t *self) {
+ for (int i = 0; i < PENDING_RESPONSES_TIMEOUT_MS; i++) {
+ if (self->tx_responses >= self->tx_packets) {
+ return;
+ }
+ mp_hal_delay_ms(1); // Allow other tasks to run
+ }
+ // Note: the loop timeout is just a fallback - in normal operation
+ // we should never reach that timeout.
+}
+
+// ESPNow.send(peer_addr, message, [sync (=true)])
+// ESPNow.send(message)
+// Send a message to the peer's mac address. Optionally wait for a response.
+// If sync == True, wait for response after sending.
+// Returns:
+// True if sync==False and message sent successfully.
+// True if sync==True and message is received successfully by all recipients
+// False if sync==True and message is not received by at least one recipient
+// Raises: EAGAIN if the internal espnow buffers are full.
+STATIC mp_obj_t espnow_send(size_t n_args, const mp_obj_t *args) {
+ esp_espnow_obj_t *self = _get_singleton_initialised();
+
+ bool sync = n_args <= 3 || args[3] == mp_const_none || mp_obj_is_true(args[3]);
+ // Get a pointer to the buffer of obj
+ mp_buffer_info_t message;
+ mp_get_buffer_raise(args[2], &message, MP_BUFFER_READ);
+
+ // Bugfix: esp_now_send() generates a panic if message buffer points
+ // to an address in ROM (eg. a statically interned QSTR).
+ // Fix: if message is not in gc pool, copy to a temp buffer.
+ static char temp[ESP_NOW_MAX_DATA_LEN]; // Static to save code space
+ byte *p = (byte *)message.buf;
+ // if (p < MP_STATE_MEM(area.gc_pool_start) || MP_STATE_MEM(area.gc_pool_end) < p) {
+ if (MP_STATE_MEM(area.gc_pool_end) < p) {
+ // If buffer is not in GC pool copy from ROM to stack
+ memcpy(temp, message.buf, message.len);
+ message.buf = temp;
+ }
+
+ if (sync) {
+ // If the last call was sync==False there may be outstanding responses.
+ // We need to wait for all pending responses if this call has sync=True.
+ _wait_for_pending_responses(self);
+ }
+ int saved_failures = self->tx_failures;
+
+ check_esp_err(
+ esp_now_send(_get_bytes_len(args[1], ESP_NOW_ETH_ALEN), message.buf, message.len));
+ self->tx_packets++;
+ if (sync) {
+ // Wait for message to be received by peer
+ _wait_for_pending_responses(self);
+ }
+ // Return False if sync and any peers did not respond.
+ return mp_obj_new_bool(!(sync && self->tx_failures != saved_failures));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_send_obj, 3, 4, espnow_send);
+
+// ### Peer Management Functions
+//
+
+// Set the ESP-NOW Primary Master Key (pmk) (for encrypted communications).
+// Raise OSError if not initialised.
+// Raise ValueError if key is not a bytes-like object exactly 16 bytes long.
+STATIC mp_obj_t espnow_set_pmk(mp_obj_t _, mp_obj_t key) {
+ check_esp_err(esp_now_set_kok(_get_bytes_len(key, ESP_NOW_KEY_LEN), ESP_NOW_KEY_LEN));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_set_pmk_obj, espnow_set_pmk);
+
+// ESPNow.add_peer(peer_mac, [lmk, [channel, [ifidx, [encrypt]]]])
+// Positional args set to None will be left at defaults.
+// Raise OSError if not initialised.
+// Raise ValueError if mac or LMK are not bytes-like objects or wrong length.
+// Raise TypeError if invalid keyword args or too many positional args.
+// Return None.
+STATIC mp_obj_t espnow_add_peer(size_t n_args, const mp_obj_t *args) {
+ check_esp_err(
+ esp_now_add_peer(
+ _get_bytes_len(args[1], ESP_NOW_ETH_ALEN),
+ ESP_NOW_ROLE_COMBO,
+ (n_args > 3) ? mp_obj_get_int(args[3]) : 0,
+ (n_args > 2) ? _get_bytes_len(args[2], ESP_NOW_KEY_LEN) : NULL,
+ ESP_NOW_KEY_LEN));
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_add_peer_obj, 2, 4, espnow_add_peer);
+
+// ESPNow.del_peer(peer_mac): Unregister peer_mac.
+// Raise OSError if not initialised.
+// Raise ValueError if peer is not a bytes-like objects or wrong length.
+// Return None.
+STATIC mp_obj_t espnow_del_peer(mp_obj_t _, mp_obj_t peer) {
+ esp_now_del_peer(_get_bytes_len(peer, ESP_NOW_ETH_ALEN));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(espnow_del_peer_obj, espnow_del_peer);
+
+STATIC const mp_rom_map_elem_t esp_espnow_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&espnow_active_obj) },
+ { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&espnow_config_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recvinto), MP_ROM_PTR(&espnow_recvinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&espnow_send_obj) },
+
+ // Peer management functions
+ { MP_ROM_QSTR(MP_QSTR_set_pmk), MP_ROM_PTR(&espnow_set_pmk_obj) },
+ { MP_ROM_QSTR(MP_QSTR_add_peer), MP_ROM_PTR(&espnow_add_peer_obj) },
+ { MP_ROM_QSTR(MP_QSTR_del_peer), MP_ROM_PTR(&espnow_del_peer_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(esp_espnow_locals_dict, esp_espnow_locals_dict_table);
+
+STATIC const mp_rom_map_elem_t espnow_globals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__espnow) },
+ { MP_ROM_QSTR(MP_QSTR_ESPNowBase), MP_ROM_PTR(&esp_espnow_type) },
+ { MP_ROM_QSTR(MP_QSTR_MAX_DATA_LEN), MP_ROM_INT(ESP_NOW_MAX_DATA_LEN)},
+ { MP_ROM_QSTR(MP_QSTR_ADDR_LEN), MP_ROM_INT(ESP_NOW_ETH_ALEN)},
+ { MP_ROM_QSTR(MP_QSTR_KEY_LEN), MP_ROM_INT(ESP_NOW_KEY_LEN)},
+ { MP_ROM_QSTR(MP_QSTR_MAX_TOTAL_PEER_NUM), MP_ROM_INT(ESP_NOW_MAX_TOTAL_PEER_NUM)},
+ { MP_ROM_QSTR(MP_QSTR_MAX_ENCRYPT_PEER_NUM), MP_ROM_INT(ESP_NOW_MAX_ENCRYPT_PEER_NUM)},
+};
+STATIC MP_DEFINE_CONST_DICT(espnow_globals_dict, espnow_globals_dict_table);
+
+// ### Dummy Buffer Protocol support
+// ...so asyncio can poll.ipoll() on this device
+
+// Support ioctl(MP_STREAM_POLL, ) for asyncio
+STATIC mp_uint_t espnow_stream_ioctl(mp_obj_t self_in, mp_uint_t request,
+ uintptr_t arg, int *errcode) {
+ if (request != MP_STREAM_POLL) {
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+ esp_espnow_obj_t *self = _get_singleton();
+ return (self->recv_buffer == NULL) ? 0 : // If not initialised
+ arg ^ ((ringbuf_avail(self->recv_buffer) == 0) ? MP_STREAM_POLL_RD : 0);
+}
+
+STATIC const mp_stream_p_t espnow_stream_p = {
+ .ioctl = espnow_stream_ioctl,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_espnow_type,
+ MP_QSTR_ESPNowBase,
+ MP_TYPE_FLAG_NONE,
+ make_new, espnow_make_new,
+ protocol, &espnow_stream_p,
+ locals_dict, &esp_espnow_locals_dict
+ );
+
+const mp_obj_module_t mp_module_espnow = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&espnow_globals_dict,
+};
+
+MP_REGISTER_MODULE(MP_QSTR__espnow, mp_module_espnow);
+MP_REGISTER_ROOT_POINTER(void *espnow_buffer);
+#endif
diff --git a/ports/esp8266/modespnow.h b/ports/esp8266/modespnow.h
new file mode 100644
index 0000000000000..b42a615db885f
--- /dev/null
+++ b/ports/esp8266/modespnow.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Glenn Moloney @glenn20
+ *
+ * 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.
+ */
+
+// Called from main.c:mp_task() to reset the espnow software stack
+mp_obj_t espnow_deinit(mp_obj_t _);
diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c
index 1dd87b9af8f74..64346b4debdc4 100644
--- a/ports/esp8266/modmachine.c
+++ b/ports/esp8266/modmachine.c
@@ -31,6 +31,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "shared/runtime/pyexec.h"
+#include "drivers/dht/dht.h"
// This needs to be set before we include the RTOS headers
#define USE_US_TIMER 1
@@ -337,13 +338,14 @@ STATIC const mp_rom_map_elem_t esp_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp_timer_locals_dict, esp_timer_locals_dict_table);
-const mp_obj_type_t esp_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = esp_timer_print,
- .make_new = esp_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp_timer_make_new,
+ print, esp_timer_print,
+ locals_dict, &esp_timer_locals_dict
+ );
// this bit is unused in the Xtensa PS register
#define ETS_LOOP_ITER_BIT (12)
@@ -394,7 +396,7 @@ mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t
}
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
@@ -417,6 +419,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#endif
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) },
@@ -453,6 +456,6 @@ const mp_obj_module_t mp_module_machine = {
.globals = (mp_obj_dict_t *)&machine_module_globals,
};
-MP_REGISTER_MODULE(MP_QSTR_umachine, mp_module_machine);
+MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_machine, mp_module_machine);
#endif // MICROPY_PY_MACHINE
diff --git a/ports/esp8266/modmachine.h b/ports/esp8266/modmachine.h
index 4a73d3b8e8013..9b7a5e3cb226e 100644
--- a/ports/esp8266/modmachine.h
+++ b/ports/esp8266/modmachine.h
@@ -21,6 +21,16 @@ typedef struct _pyb_pin_obj_t {
const pyb_pin_obj_t pyb_pin_obj[16 + 1];
+#define GPIO_MODE_INPUT (0)
+#define GPIO_MODE_OUTPUT (1)
+#define GPIO_MODE_OPEN_DRAIN (2) // synthesised
+#define GPIO_PULL_NONE (0)
+#define GPIO_PULL_UP (1)
+// Removed in SDK 1.1.0
+// #define GPIO_PULL_DOWN (2)
+
+extern uint8_t pin_mode[16 + 1];
+
void pin_init0(void);
uint mp_obj_get_pin(mp_obj_t pin_in);
diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c
deleted file mode 100644
index e32a0ff0c9176..0000000000000
--- a/ports/esp8266/modnetwork.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015-2016 Paul Sokolovsky
- *
- * 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 "shared/netutils/netutils.h"
-#include "queue.h"
-#include "user_interface.h"
-#include "espconn.h"
-#include "spi_flash.h"
-#include "ets_alt_task.h"
-#include "lwip/dns.h"
-
-#define MODNETWORK_INCLUDE_CONSTANTS (1)
-
-typedef struct _wlan_if_obj_t {
- mp_obj_base_t base;
- int if_id;
-} wlan_if_obj_t;
-
-void error_check(bool status, const char *msg);
-const mp_obj_type_t wlan_if_type;
-
-STATIC const wlan_if_obj_t wlan_objs[] = {
- {{&wlan_if_type}, STATION_IF},
- {{&wlan_if_type}, SOFTAP_IF},
-};
-
-STATIC void require_if(mp_obj_t wlan_if, int if_no) {
- wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
- if (self->if_id != if_no) {
- error_check(false, if_no == STATION_IF ? "STA required" : "AP required");
- }
-}
-
-STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
- int idx = 0;
- if (n_args > 0) {
- idx = mp_obj_get_int(args[0]);
- if (idx < 0 || idx >= sizeof(wlan_objs)) {
- mp_raise_ValueError(NULL);
- }
- }
- return MP_OBJ_FROM_PTR(&wlan_objs[idx]);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
-
-STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) {
- wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- uint32_t mode = wifi_get_opmode();
- if (n_args > 1) {
- int mask = self->if_id == STATION_IF ? STATION_MODE : SOFTAP_MODE;
- if (mp_obj_get_int(args[1]) != 0) {
- mode |= mask;
- } else {
- mode &= ~mask;
- }
- if (mode != NULL_MODE) {
- wifi_fpm_do_wakeup();
- wifi_fpm_close();
- }
- error_check(wifi_set_opmode(mode), "Cannot update i/f status");
- if (mode == NULL_MODE) {
- // Wait for the interfaces to go down before forcing power management
- while (wifi_get_opmode() != NULL_MODE) {
- ets_loop_iter();
- }
- wifi_fpm_open();
- wifi_fpm_do_sleep(0xfffffff);
- }
- return mp_const_none;
- }
-
- // Get active status
- if (self->if_id == STATION_IF) {
- return mp_obj_new_bool(mode & STATION_MODE);
- } else {
- return mp_obj_new_bool(mode & SOFTAP_MODE);
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
-
-STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_ssid, ARG_key, ARG_bssid };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- };
-
- // 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);
-
- require_if(pos_args[0], STATION_IF);
- struct station_config config = {{0}};
- size_t len;
- const char *p;
- bool set_config = false;
-
- // set parameters based on given args
- if (args[ARG_ssid].u_obj != mp_const_none) {
- p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len);
- len = MIN(len, sizeof(config.ssid));
- memcpy(config.ssid, p, len);
- set_config = true;
- }
- if (args[ARG_key].u_obj != mp_const_none) {
- p = mp_obj_str_get_data(args[ARG_key].u_obj, &len);
- len = MIN(len, sizeof(config.password));
- memcpy(config.password, p, len);
- set_config = true;
- }
- if (args[ARG_bssid].u_obj != mp_const_none) {
- p = mp_obj_str_get_data(args[ARG_bssid].u_obj, &len);
- if (len != sizeof(config.bssid)) {
- mp_raise_ValueError(NULL);
- }
- config.bssid_set = 1;
- memcpy(config.bssid, p, sizeof(config.bssid));
- set_config = true;
- }
-
- if (set_config) {
- error_check(wifi_station_set_config(&config), "Cannot set STA config");
- }
- error_check(wifi_station_connect(), "Cannot connect to AP");
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_connect_obj, 1, esp_connect);
-
-STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) {
- require_if(self_in, STATION_IF);
- error_check(wifi_station_disconnect(), "Cannot disconnect from AP");
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect);
-
-STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
- wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- if (n_args == 1) {
- // Get link status
- if (self->if_id == STATION_IF) {
- return MP_OBJ_NEW_SMALL_INT(wifi_station_get_connect_status());
- }
- return MP_OBJ_NEW_SMALL_INT(-1);
- } else {
- // Get specific status parameter
- switch (mp_obj_str_get_qstr(args[1])) {
- case MP_QSTR_rssi:
- if (self->if_id == STATION_IF) {
- return MP_OBJ_NEW_SMALL_INT(wifi_station_get_rssi());
- }
- }
- mp_raise_ValueError(MP_ERROR_TEXT("unknown status param"));
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status);
-
-STATIC mp_obj_t *esp_scan_list = NULL;
-
-STATIC void esp_scan_cb(void *result, STATUS status) {
- if (esp_scan_list == NULL) {
- // called unexpectedly
- return;
- }
- if (result && status == 0) {
- // we need to catch any memory errors
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- for (struct bss_info *bs = result; bs; bs = STAILQ_NEXT(bs, next)) {
- mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
- #if 1
- // struct bss_info::ssid_len is not documented in SDK API Guide,
- // but is present in SDK headers since 1.4.0
- t->items[0] = mp_obj_new_bytes(bs->ssid, bs->ssid_len);
- #else
- t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char *)bs->ssid));
- #endif
- t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid));
- t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel);
- t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
- t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
- t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
- mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t));
- }
- nlr_pop();
- } else {
- mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
- // indicate error
- *esp_scan_list = MP_OBJ_NULL;
- }
- } else {
- // indicate error
- *esp_scan_list = MP_OBJ_NULL;
- }
- esp_scan_list = NULL;
-}
-
-STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
- require_if(self_in, STATION_IF);
- if ((wifi_get_opmode() & STATION_MODE) == 0) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("STA must be active"));
- }
- mp_obj_t list = mp_obj_new_list(0, NULL);
- esp_scan_list = &list;
- struct scan_config config = {0};
- config.show_hidden = 1;
- wifi_station_scan(&config, (scan_done_cb_t)esp_scan_cb);
- while (esp_scan_list != NULL) {
- // our esp_scan_cb is called via ets_loop_iter so it's safe to set the
- // esp_scan_list variable to NULL without disabling interrupts
- if (MP_STATE_THREAD(mp_pending_exception) != NULL) {
- esp_scan_list = NULL;
- mp_handle_pending(true);
- }
- ets_loop_iter();
- }
- if (list == MP_OBJ_NULL) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("scan failed"));
- }
- return list;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan);
-
-/// \method isconnected()
-/// Return True if connected to an AP and an IP address has been assigned,
-/// false otherwise.
-STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) {
- wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (self->if_id == STATION_IF) {
- if (wifi_station_get_connect_status() == STATION_GOT_IP) {
- return mp_const_true;
- }
- } else {
- if (wifi_softap_get_station_num() > 0) {
- return mp_const_true;
- }
- }
- return mp_const_false;
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected);
-
-STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
- wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- struct ip_info info;
- ip_addr_t dns_addr;
- wifi_get_ip_info(self->if_id, &info);
- if (n_args == 1) {
- // get
- dns_addr = dns_getserver(0);
- mp_obj_t tuple[4] = {
- netutils_format_ipv4_addr((uint8_t *)&info.ip, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&info.netmask, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&info.gw, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&dns_addr, NETUTILS_BIG),
- };
- return mp_obj_new_tuple(4, tuple);
- } else if (args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_dhcp)) {
- // use DHCP to configure the IP addresses
- require_if(args[0], STATION_IF);
- wifi_station_dhcpc_start();
- return mp_const_none;
- } else {
- // set
- mp_obj_t *items;
- bool restart_dhcp_server = false;
- mp_obj_get_array_fixed_n(args[1], 4, &items);
- netutils_parse_ipv4_addr(items[0], (void *)&info.ip, NETUTILS_BIG);
- if (mp_obj_is_integer(items[1])) {
- // allow numeric netmask, i.e.:
- // 24 -> 255.255.255.0
- // 16 -> 255.255.0.0
- // etc...
- uint32_t *m = (uint32_t *)&info.netmask;
- *m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1])));
- } else {
- netutils_parse_ipv4_addr(items[1], (void *)&info.netmask, NETUTILS_BIG);
- }
- netutils_parse_ipv4_addr(items[2], (void *)&info.gw, NETUTILS_BIG);
- netutils_parse_ipv4_addr(items[3], (void *)&dns_addr, NETUTILS_BIG);
- // To set a static IP we have to disable DHCP first
- if (self->if_id == STATION_IF) {
- wifi_station_dhcpc_stop();
- } else {
- restart_dhcp_server = wifi_softap_dhcps_status();
- wifi_softap_dhcps_stop();
- }
- if (!wifi_set_ip_info(self->if_id, &info)) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("wifi_set_ip_info() failed"));
- }
- dns_setserver(0, &dns_addr);
- if (restart_dhcp_server) {
- wifi_softap_dhcps_start();
- }
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
-
-STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
- if (n_args != 1 && kwargs->used != 0) {
- mp_raise_TypeError(MP_ERROR_TEXT("either pos or kw args are allowed"));
- }
-
- wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- union {
- struct station_config sta;
- struct softap_config ap;
- } cfg;
-
- if (self->if_id == STATION_IF) {
- error_check(wifi_station_get_config(&cfg.sta), "can't get STA config");
- } else {
- error_check(wifi_softap_get_config(&cfg.ap), "can't get AP config");
- }
-
- int req_if = -1;
-
- if (kwargs->used != 0) {
-
- for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
- if (mp_map_slot_is_filled(kwargs, i)) {
- switch (mp_obj_str_get_qstr(kwargs->table[i].key)) {
- case MP_QSTR_mac: {
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ);
- if (bufinfo.len != 6) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer length"));
- }
- wifi_set_macaddr(self->if_id, bufinfo.buf);
- break;
- }
- case MP_QSTR_ssid:
- case MP_QSTR_essid: {
- req_if = SOFTAP_IF;
- size_t len;
- const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
- len = MIN(len, sizeof(cfg.ap.ssid));
- memcpy(cfg.ap.ssid, s, len);
- cfg.ap.ssid_len = len;
- break;
- }
- case MP_QSTR_hidden: {
- req_if = SOFTAP_IF;
- cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value);
- break;
- }
- case MP_QSTR_security:
- case MP_QSTR_authmode: {
- req_if = SOFTAP_IF;
- cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
- break;
- }
- case MP_QSTR_key:
- case MP_QSTR_password: {
- req_if = SOFTAP_IF;
- size_t len;
- const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
- len = MIN(len, sizeof(cfg.ap.password) - 1);
- memcpy(cfg.ap.password, s, len);
- cfg.ap.password[len] = 0;
- break;
- }
- case MP_QSTR_channel: {
- req_if = SOFTAP_IF;
- cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
- break;
- }
- case MP_QSTR_dhcp_hostname: {
- req_if = STATION_IF;
- if (self->if_id == STATION_IF) {
- const char *s = mp_obj_str_get_str(kwargs->table[i].value);
- wifi_station_set_hostname((char *)s);
- }
- break;
- }
- default:
- goto unknown;
- }
- }
- }
-
- // We post-check interface requirements to save on code size
- if (req_if >= 0) {
- require_if(args[0], req_if);
- }
-
- if (self->if_id == STATION_IF) {
- error_check(wifi_station_set_config(&cfg.sta), "can't set STA config");
- } else {
- error_check(wifi_softap_set_config(&cfg.ap), "can't set AP config");
- }
-
- return mp_const_none;
- }
-
- // Get config
-
- if (n_args != 2) {
- mp_raise_TypeError(MP_ERROR_TEXT("can query only one param"));
- }
-
- mp_obj_t val;
-
- qstr key = mp_obj_str_get_qstr(args[1]);
- switch (key) {
- case MP_QSTR_mac: {
- uint8_t mac[6];
- wifi_get_macaddr(self->if_id, mac);
- return mp_obj_new_bytes(mac, sizeof(mac));
- }
- case MP_QSTR_ssid:
- case MP_QSTR_essid:
- if (self->if_id == STATION_IF) {
- val = mp_obj_new_str((char *)cfg.sta.ssid, strlen((char *)cfg.sta.ssid));
- } else {
- val = mp_obj_new_str((char *)cfg.ap.ssid, cfg.ap.ssid_len);
- }
- break;
- case MP_QSTR_hidden:
- req_if = SOFTAP_IF;
- val = mp_obj_new_bool(cfg.ap.ssid_hidden);
- break;
- case MP_QSTR_security:
- case MP_QSTR_authmode:
- req_if = SOFTAP_IF;
- val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
- break;
- case MP_QSTR_channel:
- req_if = SOFTAP_IF;
- val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
- break;
- case MP_QSTR_dhcp_hostname: {
- req_if = STATION_IF;
- char *s = wifi_station_get_hostname();
- if (s == NULL) {
- val = MP_OBJ_NEW_QSTR(MP_QSTR_);
- } else {
- val = mp_obj_new_str(s, strlen(s));
- }
- break;
- }
- default:
- goto unknown;
- }
-
- // We post-check interface requirements to save on code size
- if (req_if >= 0) {
- require_if(args[0], req_if);
- }
-
- return val;
-
-unknown:
- mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config);
-
-STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&esp_active_obj) },
- { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&esp_connect_obj) },
- { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&esp_disconnect_obj) },
- { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&esp_status_obj) },
- { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&esp_scan_obj) },
- { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&esp_isconnected_obj) },
- { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
-
-const mp_obj_type_t wlan_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_WLAN,
- .locals_dict = (mp_obj_dict_t *)&wlan_if_locals_dict,
-};
-
-STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- return mp_obj_new_int(wifi_get_phy_mode());
- } else {
- wifi_set_phy_mode(mp_obj_get_int(args[0]));
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode);
-
-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(&get_wlan_obj) },
- { MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) },
-
- #if MODNETWORK_INCLUDE_CONSTANTS
- { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(STATION_IF)},
- { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(SOFTAP_IF)},
-
- { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STATION_IDLE)},
- { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STATION_CONNECTING)},
- { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(STATION_WRONG_PASSWORD)},
- { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(STATION_NO_AP_FOUND)},
- { MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(STATION_CONNECT_FAIL)},
- { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STATION_GOT_IP)},
-
- { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(PHY_MODE_11B) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(PHY_MODE_11G) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(PHY_MODE_11N) },
-
- { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(AUTH_OPEN) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(AUTH_WEP) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(AUTH_WPA_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(AUTH_WPA2_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(AUTH_WPA_WPA2_PSK) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
-
-const mp_obj_module_t network_module = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_network_globals,
-};
-
-// Note: This port doesn't define MICROPY_PY_NETWORK so this will not conflict
-// with the common implementation provided by extmod/modnetwork.c.
-MP_REGISTER_MODULE(MP_QSTR_network, network_module);
diff --git a/ports/esp8266/modnetwork.h b/ports/esp8266/modnetwork.h
new file mode 100644
index 0000000000000..5fd142e71eefb
--- /dev/null
+++ b/ports/esp8266/modnetwork.h
@@ -0,0 +1,3 @@
+extern const mp_obj_type_t esp_network_wlan_type;
+
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj);
diff --git a/ports/esp8266/modnetwork_globals.h b/ports/esp8266/modnetwork_globals.h
new file mode 100644
index 0000000000000..1a04568024b56
--- /dev/null
+++ b/ports/esp8266/modnetwork_globals.h
@@ -0,0 +1,22 @@
+{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&esp_network_wlan_type) },
+{ MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_network_phy_mode_obj) },
+
+{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(STATION_IF)},
+{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(SOFTAP_IF)},
+
+{ MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STATION_IDLE)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STATION_CONNECTING)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(STATION_WRONG_PASSWORD)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(STATION_NO_AP_FOUND)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(STATION_CONNECT_FAIL)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STATION_GOT_IP)},
+
+{ MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(PHY_MODE_11B) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(PHY_MODE_11G) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(PHY_MODE_11N) },
+
+{ MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(AUTH_OPEN) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(AUTH_WEP) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(AUTH_WPA_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(AUTH_WPA2_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(AUTH_WPA_WPA2_PSK) },
diff --git a/ports/esp8266/modos.c b/ports/esp8266/modos.c
new file mode 100644
index 0000000000000..78072d4f44869
--- /dev/null
+++ b/ports/esp8266/modos.c
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Josef Gajdusek
+ * Copyright (c) 2016 Paul Sokolovsky
+ *
+ * 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 "py/objtuple.h"
+#include "py/objstr.h"
+#include "extmod/misc.h"
+#include "extmod/vfs.h"
+#include "extmod/vfs_fat.h"
+#include "extmod/vfs_lfs.h"
+#include "genhdr/mpversion.h"
+#include "esp_mphal.h"
+#include "user_interface.h"
+
+STATIC const char *mp_os_uname_release(void) {
+ return system_get_sdk_version();
+}
+
+STATIC mp_obj_t mp_os_urandom(mp_obj_t num) {
+ mp_int_t n = mp_obj_get_int(num);
+ vstr_t vstr;
+ vstr_init_len(&vstr, n);
+ for (int i = 0; i < n; i++) {
+ vstr.buf[i] = *WDEV_HWRNG;
+ }
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_urandom_obj, mp_os_urandom);
+
+void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached) {
+ if (mp_obj_get_type(stream_attached) == &pyb_uart_type) {
+ ++uart_attached_to_dupterm;
+ }
+ if (mp_obj_get_type(stream_detached) == &pyb_uart_type) {
+ --uart_attached_to_dupterm;
+ }
+}
+
+STATIC mp_obj_t mp_os_dupterm_notify(mp_obj_t obj_in) {
+ (void)obj_in;
+ mp_hal_signal_dupterm_input();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_dupterm_notify_obj, mp_os_dupterm_notify);
diff --git a/ports/esp8266/modtime.c b/ports/esp8266/modtime.c
new file mode 100644
index 0000000000000..21dd3cbcd9099
--- /dev/null
+++ b/ports/esp8266/modtime.c
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2023 Damien P. George
+ * Copyright (c) 2015 Josef Gajdusek
+ *
+ * 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/obj.h"
+#include "shared/timeutils/timeutils.h"
+#include "modmachine.h"
+
+// Return the localtime as an 8-tuple.
+STATIC mp_obj_t mp_time_localtime_get(void) {
+ mp_int_t seconds = pyb_rtc_get_us_since_epoch() / 1000 / 1000;
+ timeutils_struct_time_t tm;
+ timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
+ mp_obj_t tuple[8] = {
+ tuple[0] = mp_obj_new_int(tm.tm_year),
+ tuple[1] = mp_obj_new_int(tm.tm_mon),
+ tuple[2] = mp_obj_new_int(tm.tm_mday),
+ tuple[3] = mp_obj_new_int(tm.tm_hour),
+ tuple[4] = mp_obj_new_int(tm.tm_min),
+ tuple[5] = mp_obj_new_int(tm.tm_sec),
+ tuple[6] = mp_obj_new_int(tm.tm_wday),
+ tuple[7] = mp_obj_new_int(tm.tm_yday),
+ };
+ return mp_obj_new_tuple(8, tuple);
+}
+
+// Returns the number of seconds, as an integer, since the Epoch.
+STATIC mp_obj_t mp_time_time_get(void) {
+ // get date and time
+ return mp_obj_new_int(pyb_rtc_get_us_since_epoch() / 1000 / 1000);
+}
diff --git a/ports/esp8266/modules/_boot.py b/ports/esp8266/modules/_boot.py
index 1f77d88024635..06b372990a52d 100644
--- a/ports/esp8266/modules/_boot.py
+++ b/ports/esp8266/modules/_boot.py
@@ -1,12 +1,12 @@
import gc
gc.threshold((gc.mem_free() + gc.mem_alloc()) // 4)
-import uos
+import os
from flashbdev import bdev
if bdev:
try:
- uos.mount(bdev, "/")
+ os.mount(bdev, "/")
except:
import inisetup
diff --git a/ports/esp8266/modules/espnow.py b/ports/esp8266/modules/espnow.py
new file mode 100644
index 0000000000000..1d2b946552e7d
--- /dev/null
+++ b/ports/esp8266/modules/espnow.py
@@ -0,0 +1,37 @@
+# espnow module for MicroPython on ESP8266
+# MIT license; Copyright (c) 2022 Glenn Moloney @glenn20
+
+from _espnow import *
+from select import poll, POLLIN
+
+
+class ESPNow(ESPNowBase):
+ # Static buffers for alloc free receipt of messages with ESPNow.irecv().
+ _data = [bytearray(ADDR_LEN), bytearray(MAX_DATA_LEN)]
+ _none_tuple = (None, None)
+
+ def __init__(self):
+ super().__init__()
+ self._poll = poll() # For any() method below...
+ self._poll.register(self, POLLIN)
+
+ def irecv(self, timeout_ms=None):
+ n = self.recvinto(self._data, timeout_ms)
+ return self._data if n else self._none_tuple
+
+ def recv(self, timeout_ms=None):
+ n = self.recvinto(self._data, timeout_ms)
+ return [bytes(x) for x in self._data] if n else self._none_tuple
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ return self.irecv() # Use alloc free irecv() method
+
+ def any(self): # For the ESP8266 which does not have ESPNow.any()
+ try:
+ next(self._poll.ipoll(0))
+ return True
+ except StopIteration:
+ return False
diff --git a/ports/esp8266/modules/inisetup.py b/ports/esp8266/modules/inisetup.py
index e5ce00138eccb..3f3edcf6d0af0 100644
--- a/ports/esp8266/modules/inisetup.py
+++ b/ports/esp8266/modules/inisetup.py
@@ -1,13 +1,13 @@
-import uos
+import os
import network
from flashbdev import bdev
def wifi():
- import ubinascii
+ import binascii
ap_if = network.WLAN(network.AP_IF)
- ssid = b"MicroPython-%s" % ubinascii.hexlify(ap_if.config("mac")[-3:])
+ ssid = b"MicroPython-%s" % binascii.hexlify(ap_if.config("mac")[-3:])
ap_if.config(ssid=ssid, security=network.AUTH_WPA_WPA2_PSK, key=b"micropythoN")
@@ -26,13 +26,17 @@ def check_bootsec():
def fs_corrupted():
import time
+ import micropython
+
+ # Allow this loop to be stopped via Ctrl-C.
+ micropython.kbd_intr(3)
while 1:
print(
"""\
The filesystem starting at sector %d with size %d sectors looks corrupt.
You may want to make a flash snapshot and try to recover it. Otherwise,
-format it with uos.VfsLfs2.mkfs(bdev), or completely erase the flash and
+format it with os.VfsLfs2.mkfs(bdev), or completely erase the flash and
reprogram MicroPython.
"""
% (bdev.start_sec, bdev.blocks)
@@ -44,17 +48,17 @@ def setup():
check_bootsec()
print("Performing initial setup")
wifi()
- uos.VfsLfs2.mkfs(bdev)
- vfs = uos.VfsLfs2(bdev)
- uos.mount(vfs, "/")
+ os.VfsLfs2.mkfs(bdev)
+ vfs = os.VfsLfs2(bdev)
+ os.mount(vfs, "/")
with open("boot.py", "w") as f:
f.write(
"""\
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
-import uos, machine
-#uos.dupterm(None, 1) # disable REPL on UART(0)
+import os, machine
+#os.dupterm(None, 1) # disable REPL on UART(0)
import gc
#import webrepl
#webrepl.start()
diff --git a/ports/esp8266/modules/ntptime.py b/ports/esp8266/modules/ntptime.py
deleted file mode 100644
index dd07e46f1d3b4..0000000000000
--- a/ports/esp8266/modules/ntptime.py
+++ /dev/null
@@ -1,39 +0,0 @@
-try:
- import usocket as socket
-except:
- import socket
-try:
- import ustruct as struct
-except:
- import struct
-
-# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
-NTP_DELTA = 3155673600
-
-# The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org'
-host = "pool.ntp.org"
-
-
-def time():
- NTP_QUERY = bytearray(48)
- NTP_QUERY[0] = 0x1B
- addr = socket.getaddrinfo(host, 123)[0][-1]
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- try:
- s.settimeout(1)
- res = s.sendto(NTP_QUERY, addr)
- msg = s.recv(48)
- finally:
- s.close()
- val = struct.unpack("!I", msg[40:44])[0]
- return val - NTP_DELTA
-
-
-# There's currently no timezone support in MicroPython, and the RTC is set in UTC time.
-def settime():
- t = time()
- import machine
- import utime
-
- tm = utime.gmtime(t)
- machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))
diff --git a/ports/esp8266/modules/port_diag.py b/ports/esp8266/modules/port_diag.py
index f2c69ecacd96b..4eea6a6d90d36 100644
--- a/ports/esp8266/modules/port_diag.py
+++ b/ports/esp8266/modules/port_diag.py
@@ -5,7 +5,6 @@
def main():
-
ROM = uctypes.bytearray_at(0x40200000, 16)
fid = esp.flash_id()
diff --git a/ports/esp8266/moduos.c b/ports/esp8266/moduos.c
deleted file mode 100644
index 9a235e61b9b9f..0000000000000
--- a/ports/esp8266/moduos.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 Josef Gajdusek
- * Copyright (c) 2016 Paul Sokolovsky
- *
- * 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 "py/objtuple.h"
-#include "py/objstr.h"
-#include "extmod/misc.h"
-#include "extmod/vfs.h"
-#include "extmod/vfs_fat.h"
-#include "extmod/vfs_lfs.h"
-#include "genhdr/mpversion.h"
-#include "esp_mphal.h"
-#include "user_interface.h"
-
-STATIC const char *mp_uos_uname_release(void) {
- return system_get_sdk_version();
-}
-
-STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
- mp_int_t n = mp_obj_get_int(num);
- vstr_t vstr;
- vstr_init_len(&vstr, n);
- for (int i = 0; i < n; i++) {
- vstr.buf[i] = *WDEV_HWRNG;
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
-
-void mp_uos_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached) {
- if (mp_obj_get_type(stream_attached) == &pyb_uart_type) {
- ++uart_attached_to_dupterm;
- }
- if (mp_obj_get_type(stream_detached) == &pyb_uart_type) {
- --uart_attached_to_dupterm;
- }
-}
-
-STATIC mp_obj_t mp_uos_dupterm_notify(mp_obj_t obj_in) {
- (void)obj_in;
- mp_hal_signal_dupterm_input();
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_dupterm_notify_obj, mp_uos_dupterm_notify);
diff --git a/ports/esp8266/modutime.c b/ports/esp8266/modutime.c
deleted file mode 100644
index 08508f8818a6c..0000000000000
--- a/ports/esp8266/modutime.c
+++ /dev/null
@@ -1,133 +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 Josef Gajdusek
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-#include "py/gc.h"
-#include "py/runtime.h"
-#include "py/mphal.h"
-#include "py/smallint.h"
-#include "shared/timeutils/timeutils.h"
-#include "modmachine.h"
-#include "user_interface.h"
-#include "extmod/utime_mphal.h"
-
-/// \module time - time related functions
-///
-/// The `time` module provides functions for getting the current time and date,
-/// and for sleeping.
-
-/// \function localtime([secs])
-/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
-/// contains: (year, month, mday, hour, minute, second, weekday, yearday)
-/// If secs is not provided or None, then the current time from the RTC is used.
-/// year includes the century (for example 2014)
-/// month is 1-12
-/// mday is 1-31
-/// hour is 0-23
-/// minute is 0-59
-/// second is 0-59
-/// weekday is 0-6 for Mon-Sun.
-/// yearday is 1-366
-STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
- timeutils_struct_time_t tm;
- mp_int_t seconds;
- if (n_args == 0 || args[0] == mp_const_none) {
- seconds = pyb_rtc_get_us_since_epoch() / 1000 / 1000;
- } else {
- seconds = mp_obj_get_int(args[0]);
- }
- timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
- mp_obj_t tuple[8] = {
- tuple[0] = mp_obj_new_int(tm.tm_year),
- tuple[1] = mp_obj_new_int(tm.tm_mon),
- tuple[2] = mp_obj_new_int(tm.tm_mday),
- tuple[3] = mp_obj_new_int(tm.tm_hour),
- tuple[4] = mp_obj_new_int(tm.tm_min),
- tuple[5] = mp_obj_new_int(tm.tm_sec),
- tuple[6] = mp_obj_new_int(tm.tm_wday),
- tuple[7] = mp_obj_new_int(tm.tm_yday),
- };
- return mp_obj_new_tuple(8, tuple);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
-
-/// \function mktime()
-/// This is inverse function of localtime. It's argument is a full 8-tuple
-/// which expresses a time as per localtime. It returns an integer which is
-/// the number of seconds since Jan 1, 2000.
-STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
- size_t len;
- mp_obj_t *elem;
- mp_obj_get_array(tuple, &len, &elem);
-
- // localtime generates a tuple of len 8. CPython uses 9, so we accept both.
- if (len < 8 || len > 9) {
- mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9 (%d given)"), len);
- }
-
- return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
- mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
- mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
-}
-MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
-
-/// \function time()
-/// Returns the number of seconds, as an integer, since the Epoch.
-STATIC mp_obj_t time_time(void) {
- // get date and time
- return mp_obj_new_int(pyb_rtc_get_us_since_epoch() / 1000 / 1000);
-}
-MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
-
-STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
-
- { MP_ROM_QSTR(MP_QSTR_gmtime), MP_ROM_PTR(&time_localtime_obj) },
- { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) },
- { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
- { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },
- { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },
- { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
- { MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_utime_time_ns_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
-
-const mp_obj_module_t utime_module = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&time_module_globals,
-};
-
-MP_REGISTER_MODULE(MP_QSTR_utime, utime_module);
diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h
index c78ae3ce0bb9e..18b2e47e29dc0 100644
--- a/ports/esp8266/mpconfigport.h
+++ b/ports/esp8266/mpconfigport.h
@@ -19,14 +19,12 @@
#define MICROPY_OPT_MATH_FACTORIAL (0)
#define MICROPY_REPL_EMACS_KEYS (0)
#define MICROPY_PY_BUILTINS_COMPLEX (0)
-#define MICROPY_MODULE_ATTR_DELEGATION (0)
#define MICROPY_PY_FUNCTION_ATTRS (0)
#define MICROPY_PY_DELATTR_SETATTR (0)
#define MICROPY_PY_BUILTINS_STR_CENTER (0)
#define MICROPY_PY_BUILTINS_STR_PARTITION (0)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)
#define MICROPY_PY_BUILTINS_SLICE_INDICES (0)
-#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
#define MICROPY_PY_BUILTINS_COMPILE (0)
#define MICROPY_PY_BUILTINS_EXECFILE (0)
#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0)
@@ -36,10 +34,9 @@
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0)
#define MICROPY_PY_MATH_FACTORIAL (0)
#define MICROPY_PY_MATH_ISCLOSE (0)
-#define MICROPY_PY_IO_FILEIO (MICROPY_VFS)
#define MICROPY_PY_SYS_PS1_PS2 (0)
-#define MICROPY_PY_UBINASCII_CRC32 (0)
-#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0)
+#define MICROPY_PY_BINASCII_CRC32 (0)
+#define MICROPY_PY_RANDOM_EXTRA_FUNCS (0)
// Configure other options.
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
@@ -56,9 +53,11 @@
#define MICROPY_REPL_EVENT_DRIVEN (0)
#define MICROPY_USE_INTERNAL_ERRNO (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text
-#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS)
-#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (*WDEV_HWRNG)
-#define MICROPY_PY_UTIME_MP_HAL (1)
+#define MICROPY_PY_HASHLIB_SHA1 (MICROPY_PY_SSL && MICROPY_SSL_AXTLS)
+#define MICROPY_PY_RANDOM_SEED_INIT_FUNC (*WDEV_HWRNG)
+#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
+#define MICROPY_PY_TIME_TIME_TIME_NS (1)
+#define MICROPY_PY_TIME_INCLUDEFILE "ports/esp8266/modtime.c"
#define MICROPY_PY_LWIP (1)
#define MICROPY_PY_LWIP_SOCK_RAW (1)
#define MICROPY_PY_MACHINE (1)
@@ -66,25 +65,31 @@
#define MICROPY_PY_MACHINE_BITSTREAM (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_PWM (1)
-#define MICROPY_PY_MACHINE_PWM_INIT (1)
#define MICROPY_PY_MACHINE_PWM_DUTY (1)
#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/esp8266/machine_pwm.c"
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_MACHINE_SOFTSPI (1)
-#define MICROPY_PY_UWEBSOCKET (1)
+#define MICROPY_PY_NETWORK (1)
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp8266"
+#endif
+#define MICROPY_PY_NETWORK_INCLUDEFILE "ports/esp8266/modnetwork.h"
+#define MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE "ports/esp8266/modnetwork_globals.h"
+#define MICROPY_PY_WEBSOCKET (1)
#define MICROPY_PY_ONEWIRE (1)
#define MICROPY_PY_WEBREPL (1)
#define MICROPY_PY_WEBREPL_DELAY (20)
#define MICROPY_PY_WEBREPL_STATIC_FILEBUF (1)
-#define MICROPY_PY_UOS_INCLUDEFILE "ports/esp8266/moduos.c"
+#define MICROPY_PY_OS_INCLUDEFILE "ports/esp8266/modos.c"
#define MICROPY_PY_OS_DUPTERM (2)
-#define MICROPY_PY_UOS_DUPTERM_NOTIFY (1)
-#define MICROPY_PY_UOS_DUPTERM_STREAM_DETACHED_ATTACHED (1)
-#define MICROPY_PY_UOS_UNAME (1)
-#define MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC (1)
-#define MICROPY_PY_UOS_URANDOM (1)
+#define MICROPY_PY_OS_DUPTERM_NOTIFY (1)
+#define MICROPY_PY_OS_DUPTERM_STREAM_DETACHED_ATTACHED (1)
+#define MICROPY_PY_OS_SYNC (1)
+#define MICROPY_PY_OS_UNAME (1)
+#define MICROPY_PY_OS_UNAME_RELEASE_DYNAMIC (1)
+#define MICROPY_PY_OS_URANDOM (1)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_WARNINGS (1)
@@ -135,24 +140,8 @@ void *esp_native_code_commit(void *, size_t, void *);
// printer for debugging output, goes to UART only
extern const struct _mp_print_t mp_debug_print;
-#if MICROPY_VFS_FAT
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-#elif MICROPY_VFS_LFS1
-#define mp_type_fileio mp_type_vfs_lfs1_fileio
-#define mp_type_textio mp_type_vfs_lfs1_textio
-#elif MICROPY_VFS_LFS2
-#define mp_type_fileio mp_type_vfs_lfs2_fileio
-#define mp_type_textio mp_type_vfs_lfs2_textio
-#endif
-
#define MP_STATE_PORT MP_STATE_VM
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- mp_obj_t pin_irq_handler[16]; \
- byte *uart0_rxbuf; \
-
// We need an implementation of the log2 function which is not a macro
#define MP_NEED_LOG2 (1)
diff --git a/ports/esp8266/network_wlan.c b/ports/esp8266/network_wlan.c
new file mode 100644
index 0000000000000..348d7f63550cf
--- /dev/null
+++ b/ports/esp8266/network_wlan.c
@@ -0,0 +1,547 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2016 Paul Sokolovsky
+ *
+ * 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 "extmod/modnetwork.h"
+#include "shared/netutils/netutils.h"
+#include "queue.h"
+#include "user_interface.h"
+#include "espconn.h"
+#include "spi_flash.h"
+#include "ets_alt_task.h"
+#include "lwip/dns.h"
+#include "modnetwork.h"
+
+typedef struct _wlan_if_obj_t {
+ mp_obj_base_t base;
+ int if_id;
+} wlan_if_obj_t;
+
+void error_check(bool status, const char *msg);
+
+STATIC const wlan_if_obj_t wlan_objs[] = {
+ {{&esp_network_wlan_type}, STATION_IF},
+ {{&esp_network_wlan_type}, SOFTAP_IF},
+};
+
+STATIC void require_if(mp_obj_t wlan_if, int if_no) {
+ wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
+ if (self->if_id != if_no) {
+ error_check(false, if_no == STATION_IF ? "STA required" : "AP required");
+ }
+}
+
+STATIC mp_obj_t esp_wlan_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, 1, false);
+ int idx = 0;
+ if (n_args > 0) {
+ idx = mp_obj_get_int(args[0]);
+ if (idx < 0 || idx >= sizeof(wlan_objs)) {
+ mp_raise_ValueError(NULL);
+ }
+ }
+ return MP_OBJ_FROM_PTR(&wlan_objs[idx]);
+}
+
+STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) {
+ wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ uint32_t mode = wifi_get_opmode();
+ if (n_args > 1) {
+ int mask = self->if_id == STATION_IF ? STATION_MODE : SOFTAP_MODE;
+ if (mp_obj_get_int(args[1]) != 0) {
+ mode |= mask;
+ } else {
+ mode &= ~mask;
+ }
+ if (mode != NULL_MODE) {
+ wifi_fpm_do_wakeup();
+ wifi_fpm_close();
+ }
+ error_check(wifi_set_opmode(mode), "Cannot update i/f status");
+ if (mode == NULL_MODE) {
+ // Wait for the interfaces to go down before forcing power management
+ while (wifi_get_opmode() != NULL_MODE) {
+ ets_loop_iter();
+ }
+ wifi_fpm_open();
+ wifi_fpm_do_sleep(0xfffffff);
+ }
+ return mp_const_none;
+ }
+
+ // Get active status
+ if (self->if_id == STATION_IF) {
+ return mp_obj_new_bool(mode & STATION_MODE);
+ } else {
+ return mp_obj_new_bool(mode & SOFTAP_MODE);
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
+
+STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_ssid, ARG_key, ARG_bssid };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ // 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);
+
+ require_if(pos_args[0], STATION_IF);
+ struct station_config config = {{0}};
+ size_t len;
+ const char *p;
+ bool set_config = false;
+
+ // set parameters based on given args
+ if (args[ARG_ssid].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len);
+ len = MIN(len, sizeof(config.ssid));
+ memcpy(config.ssid, p, len);
+ set_config = true;
+ }
+ if (args[ARG_key].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_key].u_obj, &len);
+ len = MIN(len, sizeof(config.password));
+ memcpy(config.password, p, len);
+ set_config = true;
+ }
+ if (args[ARG_bssid].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_bssid].u_obj, &len);
+ if (len != sizeof(config.bssid)) {
+ mp_raise_ValueError(NULL);
+ }
+ config.bssid_set = 1;
+ memcpy(config.bssid, p, sizeof(config.bssid));
+ set_config = true;
+ }
+
+ if (set_config) {
+ error_check(wifi_station_set_config(&config), "Cannot set STA config");
+ }
+
+ wifi_station_set_hostname(mod_network_hostname);
+
+ error_check(wifi_station_connect(), "Cannot connect to AP");
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_connect_obj, 1, esp_connect);
+
+STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) {
+ require_if(self_in, STATION_IF);
+ error_check(wifi_station_disconnect(), "Cannot disconnect from AP");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect);
+
+STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
+ wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (n_args == 1) {
+ // Get link status
+ if (self->if_id == STATION_IF) {
+ return MP_OBJ_NEW_SMALL_INT(wifi_station_get_connect_status());
+ }
+ return MP_OBJ_NEW_SMALL_INT(-1);
+ } else {
+ // Get specific status parameter
+ switch (mp_obj_str_get_qstr(args[1])) {
+ case MP_QSTR_rssi:
+ if (self->if_id == STATION_IF) {
+ return MP_OBJ_NEW_SMALL_INT(wifi_station_get_rssi());
+ }
+ }
+ mp_raise_ValueError(MP_ERROR_TEXT("unknown status param"));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status);
+
+STATIC mp_obj_t *esp_scan_list = NULL;
+
+STATIC void esp_scan_cb(void *result, STATUS status) {
+ if (esp_scan_list == NULL) {
+ // called unexpectedly
+ return;
+ }
+ if (result && status == 0) {
+ // we need to catch any memory errors
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ for (struct bss_info *bs = result; bs; bs = STAILQ_NEXT(bs, next)) {
+ mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
+ #if 1
+ // struct bss_info::ssid_len is not documented in SDK API Guide,
+ // but is present in SDK headers since 1.4.0
+ t->items[0] = mp_obj_new_bytes(bs->ssid, bs->ssid_len);
+ #else
+ t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char *)bs->ssid));
+ #endif
+ t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid));
+ t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel);
+ t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
+ t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
+ t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
+ mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t));
+ }
+ nlr_pop();
+ } else {
+ mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
+ // indicate error
+ *esp_scan_list = MP_OBJ_NULL;
+ }
+ } else {
+ // indicate error
+ *esp_scan_list = MP_OBJ_NULL;
+ }
+ esp_scan_list = NULL;
+}
+
+STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
+ require_if(self_in, STATION_IF);
+ if ((wifi_get_opmode() & STATION_MODE) == 0) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("STA must be active"));
+ }
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+ esp_scan_list = &list;
+ struct scan_config config = {0};
+ config.show_hidden = 1;
+ wifi_station_scan(&config, (scan_done_cb_t)esp_scan_cb);
+ while (esp_scan_list != NULL) {
+ // our esp_scan_cb is called via ets_loop_iter so it's safe to set the
+ // esp_scan_list variable to NULL without disabling interrupts
+ if (MP_STATE_THREAD(mp_pending_exception) != NULL) {
+ esp_scan_list = NULL;
+ mp_handle_pending(true);
+ }
+ ets_loop_iter();
+ }
+ if (list == MP_OBJ_NULL) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("scan failed"));
+ }
+ return list;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan);
+
+/// \method isconnected()
+/// Return True if connected to an AP and an IP address has been assigned,
+/// false otherwise.
+STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) {
+ wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->if_id == STATION_IF) {
+ if (wifi_station_get_connect_status() == STATION_GOT_IP) {
+ return mp_const_true;
+ }
+ } else {
+ if (wifi_softap_get_station_num() > 0) {
+ return mp_const_true;
+ }
+ }
+ return mp_const_false;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected);
+
+STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
+ wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ struct ip_info info;
+ ip_addr_t dns_addr;
+ wifi_get_ip_info(self->if_id, &info);
+ if (n_args == 1) {
+ // get
+ dns_addr = dns_getserver(0);
+ mp_obj_t tuple[4] = {
+ netutils_format_ipv4_addr((uint8_t *)&info.ip, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&info.netmask, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&info.gw, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&dns_addr, NETUTILS_BIG),
+ };
+ return mp_obj_new_tuple(4, tuple);
+ } else if (args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_dhcp)) {
+ // use DHCP to configure the IP addresses
+ require_if(args[0], STATION_IF);
+ wifi_station_dhcpc_start();
+ return mp_const_none;
+ } else {
+ // set
+ mp_obj_t *items;
+ bool restart_dhcp_server = false;
+ mp_obj_get_array_fixed_n(args[1], 4, &items);
+ netutils_parse_ipv4_addr(items[0], (void *)&info.ip, NETUTILS_BIG);
+ if (mp_obj_is_integer(items[1])) {
+ // allow numeric netmask, i.e.:
+ // 24 -> 255.255.255.0
+ // 16 -> 255.255.0.0
+ // etc...
+ uint32_t *m = (uint32_t *)&info.netmask;
+ *m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1])));
+ } else {
+ netutils_parse_ipv4_addr(items[1], (void *)&info.netmask, NETUTILS_BIG);
+ }
+ netutils_parse_ipv4_addr(items[2], (void *)&info.gw, NETUTILS_BIG);
+ netutils_parse_ipv4_addr(items[3], (void *)&dns_addr, NETUTILS_BIG);
+ // To set a static IP we have to disable DHCP first
+ if (self->if_id == STATION_IF) {
+ wifi_station_dhcpc_stop();
+ } else {
+ restart_dhcp_server = wifi_softap_dhcps_status();
+ wifi_softap_dhcps_stop();
+ }
+ if (!wifi_set_ip_info(self->if_id, &info)) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("wifi_set_ip_info() failed"));
+ }
+ dns_setserver(0, &dns_addr);
+ if (restart_dhcp_server) {
+ wifi_softap_dhcps_start();
+ }
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
+
+STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
+ if (n_args != 1 && kwargs->used != 0) {
+ mp_raise_TypeError(MP_ERROR_TEXT("either pos or kw args are allowed"));
+ }
+
+ wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ union {
+ struct station_config sta;
+ struct softap_config ap;
+ } cfg;
+
+ if (self->if_id == STATION_IF) {
+ error_check(wifi_station_get_config(&cfg.sta), "can't get STA config");
+ } else {
+ error_check(wifi_softap_get_config(&cfg.ap), "can't get AP config");
+ }
+
+ int req_if = -1;
+
+ if (kwargs->used != 0) {
+
+ for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
+ if (mp_map_slot_is_filled(kwargs, i)) {
+ switch (mp_obj_str_get_qstr(kwargs->table[i].key)) {
+ case MP_QSTR_mac: {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ);
+ if (bufinfo.len != 6) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer length"));
+ }
+ wifi_set_macaddr(self->if_id, bufinfo.buf);
+ break;
+ }
+ case MP_QSTR_ssid:
+ case MP_QSTR_essid: {
+ req_if = SOFTAP_IF;
+ size_t len;
+ const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
+ len = MIN(len, sizeof(cfg.ap.ssid));
+ memcpy(cfg.ap.ssid, s, len);
+ cfg.ap.ssid_len = len;
+ break;
+ }
+ case MP_QSTR_hidden: {
+ req_if = SOFTAP_IF;
+ cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value);
+ break;
+ }
+ case MP_QSTR_security:
+ case MP_QSTR_authmode: {
+ req_if = SOFTAP_IF;
+ cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
+ break;
+ }
+ case MP_QSTR_key:
+ case MP_QSTR_password: {
+ req_if = SOFTAP_IF;
+ size_t len;
+ const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
+ len = MIN(len, sizeof(cfg.ap.password) - 1);
+ memcpy(cfg.ap.password, s, len);
+ cfg.ap.password[len] = 0;
+ break;
+ }
+ case MP_QSTR_channel: {
+ req_if = SOFTAP_IF;
+ cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
+ break;
+ }
+ case MP_QSTR_hostname:
+ case MP_QSTR_dhcp_hostname: {
+ // TODO: Deprecated. Use network.hostname(name) instead.
+ size_t len;
+ const char *str = mp_obj_str_get_data(kwargs->table[i].value, &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
+ }
+ strcpy(mod_network_hostname, str);
+ break;
+ }
+ case MP_QSTR_protocol: {
+ wifi_set_phy_mode(mp_obj_get_int(kwargs->table[i].value));
+ break;
+ }
+ case MP_QSTR_txpower: {
+ int8_t power = mp_obj_get_float(kwargs->table[i].value) * 4;
+ system_phy_set_max_tpw(power);
+ break;
+ }
+ case MP_QSTR_pm: {
+ wifi_set_sleep_type(mp_obj_get_int(kwargs->table[i].value));
+ break;
+ }
+ default:
+ goto unknown;
+ }
+ }
+ }
+
+ // We post-check interface requirements to save on code size
+ if (req_if >= 0) {
+ require_if(args[0], req_if);
+ }
+
+ if (self->if_id == STATION_IF) {
+ error_check(wifi_station_set_config(&cfg.sta), "can't set STA config");
+ } else {
+ error_check(wifi_softap_set_config(&cfg.ap), "can't set AP config");
+ }
+
+ return mp_const_none;
+ }
+
+ // Get config
+
+ if (n_args != 2) {
+ mp_raise_TypeError(MP_ERROR_TEXT("can query only one param"));
+ }
+
+ mp_obj_t val;
+
+ qstr key = mp_obj_str_get_qstr(args[1]);
+ switch (key) {
+ case MP_QSTR_mac: {
+ uint8_t mac[6];
+ wifi_get_macaddr(self->if_id, mac);
+ return mp_obj_new_bytes(mac, sizeof(mac));
+ }
+ case MP_QSTR_ssid:
+ case MP_QSTR_essid:
+ if (self->if_id == STATION_IF) {
+ val = mp_obj_new_str((char *)cfg.sta.ssid, strlen((char *)cfg.sta.ssid));
+ } else {
+ val = mp_obj_new_str((char *)cfg.ap.ssid, cfg.ap.ssid_len);
+ }
+ break;
+ case MP_QSTR_hidden:
+ req_if = SOFTAP_IF;
+ val = mp_obj_new_bool(cfg.ap.ssid_hidden);
+ break;
+ case MP_QSTR_security:
+ case MP_QSTR_authmode:
+ req_if = SOFTAP_IF;
+ val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
+ break;
+ case MP_QSTR_channel:
+ req_if = SOFTAP_IF;
+ val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
+ break;
+ case MP_QSTR_hostname:
+ case MP_QSTR_dhcp_hostname: {
+ req_if = STATION_IF;
+ // TODO: Deprecated. Use network.hostname() instead.
+ val = mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
+ break;
+ }
+ case MP_QSTR_protocol: {
+ val = mp_obj_new_int(wifi_get_phy_mode());
+ break;
+ }
+ case MP_QSTR_pm: {
+ val = MP_OBJ_NEW_SMALL_INT(wifi_get_sleep_type());
+ break;
+ }
+ default:
+ goto unknown;
+ }
+
+ // We post-check interface requirements to save on code size
+ if (req_if >= 0) {
+ require_if(args[0], req_if);
+ }
+
+ return val;
+
+unknown:
+ mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config);
+
+STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&esp_active_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&esp_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&esp_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&esp_status_obj) },
+ { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&esp_scan_obj) },
+ { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&esp_isconnected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
+
+ // Constants
+ { MP_ROM_QSTR(MP_QSTR_PM_NONE), MP_ROM_INT(NONE_SLEEP_T) },
+ { MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(MODEM_SLEEP_T) },
+ { MP_ROM_QSTR(MP_QSTR_PM_POWERSAVE), MP_ROM_INT(LIGHT_SLEEP_T) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_network_wlan_type,
+ MP_QSTR_WLAN,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp_wlan_make_new,
+ locals_dict, &wlan_if_locals_dict
+ );
+
+STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ return mp_obj_new_int(wifi_get_phy_mode());
+ } else {
+ wifi_set_phy_mode(mp_obj_get_int(args[0]));
+ return mp_const_none;
+ }
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj, 0, 1, esp_phy_mode);
diff --git a/ports/esp8266/uart.c b/ports/esp8266/uart.c
index 978a7efc38edf..f761ecfd70cf6 100644
--- a/ports/esp8266/uart.c
+++ b/ports/esp8266/uart.c
@@ -3,7 +3,7 @@
*
* FileName: uart.c
*
- * Description: Two UART mode configration and interrupt handler.
+ * Description: Two UART mode configuration and interrupt handler.
* Check your hardware connection while use this mode.
*
* Modification history:
@@ -111,6 +111,15 @@ void uart_tx_one_char(uint8 uart, uint8 TxChar) {
WRITE_PERI_REG(UART_FIFO(uart), TxChar);
}
+int uart_txdone(uint8 uart) {
+ uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
+ if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
void uart_flush(uint8 uart) {
while (true) {
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
@@ -155,7 +164,7 @@ uart_os_config(int uart) {
*******************************************************************************/
static void uart0_rx_intr_handler(void *para) {
- /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
+ /* uart0 and uart1 intr combine together, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
* uart1 and uart0 respectively
*/
diff --git a/ports/esp8266/uart.h b/ports/esp8266/uart.h
index de0919bde056d..3c5592ff0aa88 100644
--- a/ports/esp8266/uart.h
+++ b/ports/esp8266/uart.h
@@ -101,6 +101,7 @@ bool uart_rx_wait(uint32_t timeout_us);
int uart_rx_char(void);
void uart_tx_one_char(uint8 uart, uint8 TxChar);
void uart_flush(uint8 uart);
+int uart_txdone(uint8 uart);
void uart_os_config(int uart);
void uart_setup(uint8 uart);
int uart0_get_rxbuf_len(void);
diff --git a/ports/javascript/Makefile b/ports/javascript/Makefile
deleted file mode 100644
index aea9d6ec37031..0000000000000
--- a/ports/javascript/Makefile
+++ /dev/null
@@ -1,59 +0,0 @@
-include ../../py/mkenv.mk
-
-CROSS = 0
-
-QSTR_DEFS = qstrdefsport.h
-
-include $(TOP)/py/py.mk
-include $(TOP)/extmod/extmod.mk
-
-CC = emcc
-LD = emcc
-
-INC += -I.
-INC += -I$(TOP)
-INC += -I$(BUILD)
-
-CFLAGS += -std=c99 -Wall -Werror -Wdouble-promotion -Wfloat-conversion
-CFLAGS += -O3 -DNDEBUG
-CFLAGS += $(INC)
-
-SRC_SHARED = $(addprefix shared/,\
- runtime/interrupt_char.c \
- runtime/stdout_helpers.c \
- runtime/pyexec.c \
- readline/readline.c \
- )
-
-SRC_C = \
- main.c \
- mphalport.c \
- modutime.c \
-
-SRC_QSTR += $(SRC_C)
-
-OBJ += $(PY_O)
-OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
-
-JSFLAGS += -s ASYNCIFY
-JSFLAGS += -s EXPORTED_FUNCTIONS="['_mp_js_init', '_mp_js_init_repl', '_mp_js_do_str', '_mp_js_process_char', '_mp_hal_get_interrupt_char', '_mp_sched_keyboard_interrupt']" -s EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" -s --memory-init-file 0 --js-library library.js
-
-all: $(BUILD)/micropython.js
-
-$(BUILD)/micropython.js: $(OBJ) library.js wrapper.js
- $(ECHO) "LINK $(BUILD)/firmware.js"
- $(Q)emcc $(LDFLAGS) -o $(BUILD)/firmware.js $(OBJ) $(JSFLAGS)
- cat wrapper.js $(BUILD)/firmware.js > $@
-
-min: $(BUILD)/micropython.js
- uglifyjs $< -c -o $(BUILD)/micropython.min.js
-
-test: $(BUILD)/micropython.js $(TOP)/tests/run-tests.py
- $(eval DIRNAME=ports/$(notdir $(CURDIR)))
- cd $(TOP)/tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py -j1
-
-# Disable errors for array-bounds warnings on "sp[-MP_OBJ_ITER_BUF_NSLOTS + 2]" access.
-$(BUILD)/py/vm.o: CFLAGS += -Wno-error=array-bounds
-
-include $(TOP)/py/mkrules.mk
diff --git a/ports/javascript/README.md b/ports/javascript/README.md
deleted file mode 100644
index 39808943b1043..0000000000000
--- a/ports/javascript/README.md
+++ /dev/null
@@ -1,118 +0,0 @@
-MicroPython.js
-==============
-
-MicroPython transmuted into Javascript by Emscripten.
-
-Dependencies
-------------
-
-Building micropython.js bears the same requirements as the standard MicroPython
-ports with the addition of Emscripten (and uglify-js for the minified file).
-
-Build instructions
-------------------
-
-In order to build micropython.js, run:
-
- $ make
-
-To generate the minified file micropython.min.js, run:
-
- $ make min
-
-Running with Node.js
---------------------
-
-Access the repl with:
-
- $ node build/micropython.js
-
-Stack size may be modified using:
-
- $ node build/micropython.js -X stack=64K
-
-Where stack size may be represented in Bytes, KiB or MiB.
-
-MicroPython scripts may be executed using:
-
- $ node build/micropython.js hello.py
-
-Alternatively micropython.js may by accessed by other javascript programs in node
-using the require command and the general API outlined below. For example:
-
-```javascript
-var mp_js = require('./build/micropython.js');
-
-mp_js_init(64 * 1024);
-mp_js_do_str("print('hello world')\n");
-```
-
-Running with HTML
------------------
-
-The prerequisite for browser operation of micropython.js is an element with
-the id `mp_js_stdout` which receives `print` events. The following code
-demonstrates basic functionality:
-
-```html
-
-
-
-
-
-
-
-
-
-
-```
-
-MicroPython code execution will suspend the browser so be sure to atomize usage
-within this environment. Unfortunately interrupts have not been implemented for the
-browser.
-
-Testing
--------
-
-Run the test suite using:
-
- $ make test
-
-API
----
-
-The following functions have been exposed to javascript.
-
-```
-mp_js_init(stack_size)
-```
-
-Initialize MicroPython with the given stack size in bytes. This must be
-called before attempting to interact with MicroPython.
-
-```
-mp_js_do_str(code)
-```
-
-Execute the input code. `code` must be a `string`.
-
-```
-mp_js_init_repl()
-```
-
-Initialize MicroPython repl. Must be called before entering characters into
-the repl.
-
-```
-mp_js_process_char(char)
-```
-
-Input character into MicroPython repl. `char` must be of type `number`. This
-will execute MicroPython code when necessary.
diff --git a/ports/javascript/main.c b/ports/javascript/main.c
deleted file mode 100644
index 36ea9e98bead5..0000000000000
--- a/ports/javascript/main.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013-2021 Damien P. George and 2017, 2018 Rami Ali
- *
- * 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